diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2013-06-24 05:49:29 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-25 19:58:37 -0400 |
commit | 87a7b84b588c2ddbde890890855aef18ec34174e (patch) | |
tree | 5c050d6899bcb84d0366dedefbf690e8fbdc3dc1 /drivers/net/bonding | |
parent | 277e2a84c12e0d4af77d0f0a52623211eb6ab223 (diff) |
bonding: add helper function bond_get_targets_ip(targets, ip)
Add function bond_get_targets_ip(targets, ip) which searches through
targets array of ips (arp_targets) and returns the position of first
match. If ip == 0, returns the first free slot. On failure to find the
ip or free slot, return -1.
Use it to verify if the arp we've received is valid and in sysfs.
v1->v2:
Fix "[2/6] bonding: add helper function bond_get_targets_ip(targets, ip)",
per Nikolay's advice, to verify if source ip != 0.0.0.0, otherwise we might
update 'null' arp_ip_targets' last_rx. Also, address style.
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 21 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 54 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 16 |
3 files changed, 46 insertions, 45 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 3b31c19972d4..976d28e3498a 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2610,19 +2610,16 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2610 | 2610 | ||
2611 | static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) | 2611 | static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) |
2612 | { | 2612 | { |
2613 | int i; | 2613 | if (!sip || !bond_has_this_ip(bond, tip)) { |
2614 | __be32 *targets = bond->params.arp_targets; | 2614 | pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip); |
2615 | return; | ||
2616 | } | ||
2615 | 2617 | ||
2616 | for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { | 2618 | if (bond_get_targets_ip(bond->params.arp_targets, sip) == -1) { |
2617 | pr_debug("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n", | 2619 | pr_debug("bva: sip %pI4 not found in targets\n", &sip); |
2618 | &sip, &tip, i, &targets[i], | 2620 | return; |
2619 | bond_has_this_ip(bond, tip)); | ||
2620 | if (sip == targets[i]) { | ||
2621 | if (bond_has_this_ip(bond, tip)) | ||
2622 | slave->last_arp_rx = jiffies; | ||
2623 | return; | ||
2624 | } | ||
2625 | } | 2621 | } |
2622 | slave->last_arp_rx = jiffies; | ||
2626 | } | 2623 | } |
2627 | 2624 | ||
2628 | static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, | 2625 | static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, |
@@ -4839,7 +4836,7 @@ static int __net_init bond_net_init(struct net *net) | |||
4839 | 4836 | ||
4840 | bond_create_proc_dir(bn); | 4837 | bond_create_proc_dir(bn); |
4841 | bond_create_sysfs(bn); | 4838 | bond_create_sysfs(bn); |
4842 | 4839 | ||
4843 | return 0; | 4840 | return 0; |
4844 | } | 4841 | } |
4845 | 4842 | ||
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index f8bee4c0cbf1..ece57f146a60 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -591,7 +591,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, | |||
591 | const char *buf, size_t count) | 591 | const char *buf, size_t count) |
592 | { | 592 | { |
593 | __be32 newtarget; | 593 | __be32 newtarget; |
594 | int i = 0, done = 0, ret = count; | 594 | int i = 0, ret = -EINVAL; |
595 | struct bonding *bond = to_bond(d); | 595 | struct bonding *bond = to_bond(d); |
596 | __be32 *targets; | 596 | __be32 *targets; |
597 | 597 | ||
@@ -602,57 +602,44 @@ static ssize_t bonding_store_arp_targets(struct device *d, | |||
602 | if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { | 602 | if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { |
603 | pr_err("%s: invalid ARP target %pI4 specified for addition\n", | 603 | pr_err("%s: invalid ARP target %pI4 specified for addition\n", |
604 | bond->dev->name, &newtarget); | 604 | bond->dev->name, &newtarget); |
605 | ret = -EINVAL; | ||
606 | goto out; | 605 | goto out; |
607 | } | 606 | } |
608 | /* look for an empty slot to put the target in, and check for dupes */ | 607 | |
609 | for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { | 608 | if (bond_get_targets_ip(targets, newtarget) != -1) { /* dup */ |
610 | if (targets[i] == newtarget) { /* duplicate */ | 609 | pr_err("%s: ARP target %pI4 is already present\n", |
611 | pr_err("%s: ARP target %pI4 is already present\n", | 610 | bond->dev->name, &newtarget); |
612 | bond->dev->name, &newtarget); | 611 | goto out; |
613 | ret = -EINVAL; | ||
614 | goto out; | ||
615 | } | ||
616 | if (targets[i] == 0) { | ||
617 | pr_info("%s: adding ARP target %pI4.\n", | ||
618 | bond->dev->name, &newtarget); | ||
619 | done = 1; | ||
620 | targets[i] = newtarget; | ||
621 | } | ||
622 | } | 612 | } |
623 | if (!done) { | 613 | |
614 | i = bond_get_targets_ip(targets, 0); /* first free slot */ | ||
615 | if (i == -1) { | ||
624 | pr_err("%s: ARP target table is full!\n", | 616 | pr_err("%s: ARP target table is full!\n", |
625 | bond->dev->name); | 617 | bond->dev->name); |
626 | ret = -EINVAL; | ||
627 | goto out; | 618 | goto out; |
628 | } | 619 | } |
629 | 620 | ||
621 | pr_info("%s: adding ARP target %pI4.\n", bond->dev->name, | ||
622 | &newtarget); | ||
623 | targets[i] = newtarget; | ||
630 | } else if (buf[0] == '-') { | 624 | } else if (buf[0] == '-') { |
631 | if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { | 625 | if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) { |
632 | pr_err("%s: invalid ARP target %pI4 specified for removal\n", | 626 | pr_err("%s: invalid ARP target %pI4 specified for removal\n", |
633 | bond->dev->name, &newtarget); | 627 | bond->dev->name, &newtarget); |
634 | ret = -EINVAL; | ||
635 | goto out; | 628 | goto out; |
636 | } | 629 | } |
637 | 630 | ||
638 | for (i = 0; (i < BOND_MAX_ARP_TARGETS) && !done; i++) { | 631 | i = bond_get_targets_ip(targets, newtarget); |
639 | if (targets[i] == newtarget) { | 632 | if (i == -1) { |
640 | int j; | ||
641 | pr_info("%s: removing ARP target %pI4.\n", | ||
642 | bond->dev->name, &newtarget); | ||
643 | for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j+1]; j++) | ||
644 | targets[j] = targets[j+1]; | ||
645 | |||
646 | targets[j] = 0; | ||
647 | done = 1; | ||
648 | } | ||
649 | } | ||
650 | if (!done) { | ||
651 | pr_info("%s: unable to remove nonexistent ARP target %pI4.\n", | 633 | pr_info("%s: unable to remove nonexistent ARP target %pI4.\n", |
652 | bond->dev->name, &newtarget); | 634 | bond->dev->name, &newtarget); |
653 | ret = -EINVAL; | ||
654 | goto out; | 635 | goto out; |
655 | } | 636 | } |
637 | |||
638 | pr_info("%s: removing ARP target %pI4.\n", bond->dev->name, | ||
639 | &newtarget); | ||
640 | for (; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++) | ||
641 | targets[i] = targets[i+1]; | ||
642 | targets[i] = 0; | ||
656 | } else { | 643 | } else { |
657 | pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n", | 644 | pr_err("no command found in arp_ip_targets file for bond %s. Use +<addr> or -<addr>.\n", |
658 | bond->dev->name); | 645 | bond->dev->name); |
@@ -660,6 +647,7 @@ static ssize_t bonding_store_arp_targets(struct device *d, | |||
660 | goto out; | 647 | goto out; |
661 | } | 648 | } |
662 | 649 | ||
650 | ret = count; | ||
663 | out: | 651 | out: |
664 | return ret; | 652 | return ret; |
665 | } | 653 | } |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index c990b42cf7a1..486e532f77e4 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -464,6 +464,22 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond, | |||
464 | return NULL; | 464 | return NULL; |
465 | } | 465 | } |
466 | 466 | ||
467 | /* Check if the ip is present in arp ip list, or first free slot if ip == 0 | ||
468 | * Returns -1 if not found, index if found | ||
469 | */ | ||
470 | static inline int bond_get_targets_ip(__be32 *targets, __be32 ip) | ||
471 | { | ||
472 | int i; | ||
473 | |||
474 | for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) | ||
475 | if (targets[i] == ip) | ||
476 | return i; | ||
477 | else if (targets[i] == 0) | ||
478 | break; | ||
479 | |||
480 | return -1; | ||
481 | } | ||
482 | |||
467 | /* exported from bond_main.c */ | 483 | /* exported from bond_main.c */ |
468 | extern int bond_net_id; | 484 | extern int bond_net_id; |
469 | extern const struct bond_parm_tbl bond_lacp_tbl[]; | 485 | extern const struct bond_parm_tbl bond_lacp_tbl[]; |