diff options
| -rw-r--r-- | Documentation/networking/bonding.txt | 59 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_main.c | 182 | ||||
| -rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 54 | ||||
| -rw-r--r-- | drivers/net/bonding/bonding.h | 32 | ||||
| -rw-r--r-- | include/linux/if.h | 1 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 7 |
6 files changed, 325 insertions, 10 deletions
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt index afac780445cd..dc942eaf490f 100644 --- a/Documentation/networking/bonding.txt +++ b/Documentation/networking/bonding.txt | |||
| @@ -192,6 +192,17 @@ or, for backwards compatibility, the option value. E.g., | |||
| 192 | arp_interval | 192 | arp_interval |
| 193 | 193 | ||
| 194 | Specifies the ARP link monitoring frequency in milliseconds. | 194 | Specifies the ARP link monitoring frequency in milliseconds. |
| 195 | |||
| 196 | The ARP monitor works by periodically checking the slave | ||
| 197 | devices to determine whether they have sent or received | ||
| 198 | traffic recently (the precise criteria depends upon the | ||
| 199 | bonding mode, and the state of the slave). Regular traffic is | ||
| 200 | generated via ARP probes issued for the addresses specified by | ||
| 201 | the arp_ip_target option. | ||
| 202 | |||
| 203 | This behavior can be modified by the arp_validate option, | ||
| 204 | below. | ||
| 205 | |||
| 195 | If ARP monitoring is used in an etherchannel compatible mode | 206 | If ARP monitoring is used in an etherchannel compatible mode |
| 196 | (modes 0 and 2), the switch should be configured in a mode | 207 | (modes 0 and 2), the switch should be configured in a mode |
| 197 | that evenly distributes packets across all links. If the | 208 | that evenly distributes packets across all links. If the |
| @@ -213,6 +224,54 @@ arp_ip_target | |||
| 213 | maximum number of targets that can be specified is 16. The | 224 | maximum number of targets that can be specified is 16. The |
| 214 | default value is no IP addresses. | 225 | default value is no IP addresses. |
| 215 | 226 | ||
| 227 | arp_validate | ||
| 228 | |||
| 229 | Specifies whether or not ARP probes and replies should be | ||
| 230 | validated in the active-backup mode. This causes the ARP | ||
| 231 | monitor to examine the incoming ARP requests and replies, and | ||
| 232 | only consider a slave to be up if it is receiving the | ||
| 233 | appropriate ARP traffic. | ||
| 234 | |||
| 235 | Possible values are: | ||
| 236 | |||
| 237 | none or 0 | ||
| 238 | |||
| 239 | No validation is performed. This is the default. | ||
| 240 | |||
| 241 | active or 1 | ||
| 242 | |||
| 243 | Validation is performed only for the active slave. | ||
| 244 | |||
| 245 | backup or 2 | ||
| 246 | |||
| 247 | Validation is performed only for backup slaves. | ||
| 248 | |||
| 249 | all or 3 | ||
| 250 | |||
| 251 | Validation is performed for all slaves. | ||
| 252 | |||
| 253 | For the active slave, the validation checks ARP replies to | ||
| 254 | confirm that they were generated by an arp_ip_target. Since | ||
| 255 | backup slaves do not typically receive these replies, the | ||
| 256 | validation performed for backup slaves is on the ARP request | ||
| 257 | sent out via the active slave. It is possible that some | ||
| 258 | switch or network configurations may result in situations | ||
| 259 | wherein the backup slaves do not receive the ARP requests; in | ||
| 260 | such a situation, validation of backup slaves must be | ||
| 261 | disabled. | ||
| 262 | |||
| 263 | This option is useful in network configurations in which | ||
| 264 | multiple bonding hosts are concurrently issuing ARPs to one or | ||
| 265 | more targets beyond a common switch. Should the link between | ||
| 266 | the switch and target fail (but not the switch itself), the | ||
| 267 | probe traffic generated by the multiple bonding instances will | ||
| 268 | fool the standard ARP monitor into considering the links as | ||
| 269 | still up. Use of the arp_validate option can resolve this, as | ||
| 270 | the ARP monitor will only consider ARP requests and replies | ||
| 271 | associated with its own instance of bonding. | ||
| 272 | |||
| 273 | This option was added in bonding version 3.1.0. | ||
| 274 | |||
| 216 | downdelay | 275 | downdelay |
| 217 | 276 | ||
| 218 | Specifies the time, in milliseconds, to wait before disabling | 277 | Specifies the time, in milliseconds, to wait before disabling |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bafe62f7c9b7..fd521b05db83 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
| @@ -96,6 +96,7 @@ static char *lacp_rate = NULL; | |||
| 96 | static char *xmit_hash_policy = NULL; | 96 | static char *xmit_hash_policy = NULL; |
| 97 | static int arp_interval = BOND_LINK_ARP_INTERV; | 97 | static int arp_interval = BOND_LINK_ARP_INTERV; |
| 98 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; | 98 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; |
| 99 | static char *arp_validate = NULL; | ||
| 99 | struct bond_params bonding_defaults; | 100 | struct bond_params bonding_defaults; |
| 100 | 101 | ||
| 101 | module_param(max_bonds, int, 0); | 102 | module_param(max_bonds, int, 0); |
| @@ -127,6 +128,8 @@ module_param(arp_interval, int, 0); | |||
| 127 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); | 128 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); |
| 128 | module_param_array(arp_ip_target, charp, NULL, 0); | 129 | module_param_array(arp_ip_target, charp, NULL, 0); |
| 129 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); | 130 | MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form"); |
| 131 | module_param(arp_validate, charp, 0); | ||
| 132 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all"); | ||
| 130 | 133 | ||
| 131 | /*----------------------------- Global variables ----------------------------*/ | 134 | /*----------------------------- Global variables ----------------------------*/ |
| 132 | 135 | ||
| @@ -170,6 +173,14 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = { | |||
| 170 | { NULL, -1}, | 173 | { NULL, -1}, |
| 171 | }; | 174 | }; |
| 172 | 175 | ||
| 176 | struct bond_parm_tbl arp_validate_tbl[] = { | ||
| 177 | { "none", BOND_ARP_VALIDATE_NONE}, | ||
| 178 | { "active", BOND_ARP_VALIDATE_ACTIVE}, | ||
| 179 | { "backup", BOND_ARP_VALIDATE_BACKUP}, | ||
| 180 | { "all", BOND_ARP_VALIDATE_ALL}, | ||
| 181 | { NULL, -1}, | ||
| 182 | }; | ||
| 183 | |||
| 173 | /*-------------------------- Forward declarations ---------------------------*/ | 184 | /*-------------------------- Forward declarations ---------------------------*/ |
| 174 | 185 | ||
| 175 | static void bond_send_gratuitous_arp(struct bonding *bond); | 186 | static void bond_send_gratuitous_arp(struct bonding *bond); |
| @@ -1424,6 +1435,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1424 | 1435 | ||
| 1425 | bond_compute_features(bond); | 1436 | bond_compute_features(bond); |
| 1426 | 1437 | ||
| 1438 | new_slave->last_arp_rx = jiffies; | ||
| 1439 | |||
| 1427 | if (bond->params.miimon && !bond->params.use_carrier) { | 1440 | if (bond->params.miimon && !bond->params.use_carrier) { |
| 1428 | link_reporting = bond_check_dev_link(bond, slave_dev, 1); | 1441 | link_reporting = bond_check_dev_link(bond, slave_dev, 1); |
| 1429 | 1442 | ||
| @@ -1785,7 +1798,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
| 1785 | dev_set_mac_address(slave_dev, &addr); | 1798 | dev_set_mac_address(slave_dev, &addr); |
| 1786 | 1799 | ||
| 1787 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | | 1800 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | |
| 1788 | IFF_SLAVE_INACTIVE | IFF_BONDING); | 1801 | IFF_SLAVE_INACTIVE | IFF_BONDING | |
| 1802 | IFF_SLAVE_NEEDARP); | ||
| 1789 | 1803 | ||
| 1790 | kfree(slave); | 1804 | kfree(slave); |
| 1791 | 1805 | ||
| @@ -2298,6 +2312,25 @@ static int bond_has_ip(struct bonding *bond) | |||
| 2298 | return 0; | 2312 | return 0; |
| 2299 | } | 2313 | } |
| 2300 | 2314 | ||
| 2315 | static int bond_has_this_ip(struct bonding *bond, u32 ip) | ||
| 2316 | { | ||
| 2317 | struct vlan_entry *vlan, *vlan_next; | ||
| 2318 | |||
| 2319 | if (ip == bond->master_ip) | ||
| 2320 | return 1; | ||
| 2321 | |||
| 2322 | if (list_empty(&bond->vlan_list)) | ||
| 2323 | return 0; | ||
| 2324 | |||
| 2325 | list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list, | ||
| 2326 | vlan_list) { | ||
| 2327 | if (ip == vlan->vlan_ip) | ||
| 2328 | return 1; | ||
| 2329 | } | ||
| 2330 | |||
| 2331 | return 0; | ||
| 2332 | } | ||
| 2333 | |||
| 2301 | /* | 2334 | /* |
| 2302 | * We go to the (large) trouble of VLAN tagging ARP frames because | 2335 | * We go to the (large) trouble of VLAN tagging ARP frames because |
| 2303 | * switches in VLAN mode (especially if ports are configured as | 2336 | * switches in VLAN mode (especially if ports are configured as |
| @@ -2436,6 +2469,93 @@ static void bond_send_gratuitous_arp(struct bonding *bond) | |||
| 2436 | } | 2469 | } |
| 2437 | } | 2470 | } |
| 2438 | 2471 | ||
| 2472 | static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip) | ||
| 2473 | { | ||
| 2474 | int i; | ||
| 2475 | u32 *targets = bond->params.arp_targets; | ||
| 2476 | |||
| 2477 | targets = bond->params.arp_targets; | ||
| 2478 | for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) { | ||
| 2479 | dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] " | ||
| 2480 | "%u.%u.%u.%u bhti(tip) %d\n", | ||
| 2481 | NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]), | ||
| 2482 | bond_has_this_ip(bond, tip)); | ||
| 2483 | if (sip == targets[i]) { | ||
| 2484 | if (bond_has_this_ip(bond, tip)) | ||
| 2485 | slave->last_arp_rx = jiffies; | ||
| 2486 | return; | ||
| 2487 | } | ||
| 2488 | } | ||
| 2489 | } | ||
| 2490 | |||
| 2491 | static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) | ||
| 2492 | { | ||
| 2493 | struct arphdr *arp; | ||
| 2494 | struct slave *slave; | ||
| 2495 | struct bonding *bond; | ||
| 2496 | unsigned char *arp_ptr; | ||
| 2497 | u32 sip, tip; | ||
| 2498 | |||
| 2499 | if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) | ||
| 2500 | goto out; | ||
| 2501 | |||
| 2502 | bond = dev->priv; | ||
| 2503 | read_lock(&bond->lock); | ||
| 2504 | |||
| 2505 | dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n", | ||
| 2506 | bond->dev->name, skb->dev ? skb->dev->name : "NULL", | ||
| 2507 | orig_dev ? orig_dev->name : "NULL"); | ||
| 2508 | |||
| 2509 | slave = bond_get_slave_by_dev(bond, orig_dev); | ||
| 2510 | if (!slave || !slave_do_arp_validate(bond, slave)) | ||
| 2511 | goto out_unlock; | ||
| 2512 | |||
| 2513 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | ||
| 2514 | if (!pskb_may_pull(skb, (sizeof(struct arphdr) + | ||
| 2515 | (2 * dev->addr_len) + | ||
| 2516 | (2 * sizeof(u32))))) | ||
| 2517 | goto out_unlock; | ||
| 2518 | |||
| 2519 | arp = skb->nh.arph; | ||
| 2520 | if (arp->ar_hln != dev->addr_len || | ||
| 2521 | skb->pkt_type == PACKET_OTHERHOST || | ||
| 2522 | skb->pkt_type == PACKET_LOOPBACK || | ||
| 2523 | arp->ar_hrd != htons(ARPHRD_ETHER) || | ||
| 2524 | arp->ar_pro != htons(ETH_P_IP) || | ||
| 2525 | arp->ar_pln != 4) | ||
| 2526 | goto out_unlock; | ||
| 2527 | |||
| 2528 | arp_ptr = (unsigned char *)(arp + 1); | ||
| 2529 | arp_ptr += dev->addr_len; | ||
| 2530 | memcpy(&sip, arp_ptr, 4); | ||
| 2531 | arp_ptr += 4 + dev->addr_len; | ||
| 2532 | memcpy(&tip, arp_ptr, 4); | ||
| 2533 | |||
| 2534 | dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u" | ||
| 2535 | " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name, | ||
| 2536 | slave->state, bond->params.arp_validate, | ||
| 2537 | slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip)); | ||
| 2538 | |||
| 2539 | /* | ||
| 2540 | * Backup slaves won't see the ARP reply, but do come through | ||
| 2541 | * here for each ARP probe (so we swap the sip/tip to validate | ||
| 2542 | * the probe). In a "redundant switch, common router" type of | ||
| 2543 | * configuration, the ARP probe will (hopefully) travel from | ||
| 2544 | * the active, through one switch, the router, then the other | ||
| 2545 | * switch before reaching the backup. | ||
| 2546 | */ | ||
| 2547 | if (slave->state == BOND_STATE_ACTIVE) | ||
| 2548 | bond_validate_arp(bond, slave, sip, tip); | ||
| 2549 | else | ||
| 2550 | bond_validate_arp(bond, slave, tip, sip); | ||
| 2551 | |||
| 2552 | out_unlock: | ||
| 2553 | read_unlock(&bond->lock); | ||
| 2554 | out: | ||
| 2555 | dev_kfree_skb(skb); | ||
| 2556 | return NET_RX_SUCCESS; | ||
| 2557 | } | ||
| 2558 | |||
| 2439 | /* | 2559 | /* |
| 2440 | * this function is called regularly to monitor each slave's link | 2560 | * this function is called regularly to monitor each slave's link |
| 2441 | * ensuring that traffic is being sent and received when arp monitoring | 2561 | * ensuring that traffic is being sent and received when arp monitoring |
| @@ -2600,7 +2720,8 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) | |||
| 2600 | */ | 2720 | */ |
| 2601 | bond_for_each_slave(bond, slave, i) { | 2721 | bond_for_each_slave(bond, slave, i) { |
| 2602 | if (slave->link != BOND_LINK_UP) { | 2722 | if (slave->link != BOND_LINK_UP) { |
| 2603 | if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) { | 2723 | if ((jiffies - slave_last_rx(bond, slave)) <= |
| 2724 | delta_in_ticks) { | ||
| 2604 | 2725 | ||
| 2605 | slave->link = BOND_LINK_UP; | 2726 | slave->link = BOND_LINK_UP; |
| 2606 | 2727 | ||
| @@ -2645,7 +2766,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) | |||
| 2645 | 2766 | ||
| 2646 | if ((slave != bond->curr_active_slave) && | 2767 | if ((slave != bond->curr_active_slave) && |
| 2647 | (!bond->current_arp_slave) && | 2768 | (!bond->current_arp_slave) && |
| 2648 | (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) && | 2769 | (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) && |
| 2649 | bond_has_ip(bond))) { | 2770 | bond_has_ip(bond))) { |
| 2650 | /* a backup slave has gone down; three times | 2771 | /* a backup slave has gone down; three times |
| 2651 | * the delta allows the current slave to be | 2772 | * the delta allows the current slave to be |
| @@ -2692,7 +2813,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev) | |||
| 2692 | * if it is up and needs to take over as the curr_active_slave | 2813 | * if it is up and needs to take over as the curr_active_slave |
| 2693 | */ | 2814 | */ |
| 2694 | if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || | 2815 | if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) || |
| 2695 | (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) && | 2816 | (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) && |
| 2696 | bond_has_ip(bond))) && | 2817 | bond_has_ip(bond))) && |
| 2697 | ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { | 2818 | ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) { |
| 2698 | 2819 | ||
| @@ -3315,6 +3436,21 @@ static void bond_unregister_lacpdu(struct bonding *bond) | |||
| 3315 | dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); | 3436 | dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); |
| 3316 | } | 3437 | } |
| 3317 | 3438 | ||
| 3439 | void bond_register_arp(struct bonding *bond) | ||
| 3440 | { | ||
| 3441 | struct packet_type *pt = &bond->arp_mon_pt; | ||
| 3442 | |||
| 3443 | pt->type = htons(ETH_P_ARP); | ||
| 3444 | pt->dev = NULL; /*bond->dev;XXX*/ | ||
| 3445 | pt->func = bond_arp_rcv; | ||
| 3446 | dev_add_pack(pt); | ||
| 3447 | } | ||
| 3448 | |||
| 3449 | void bond_unregister_arp(struct bonding *bond) | ||
| 3450 | { | ||
| 3451 | dev_remove_pack(&bond->arp_mon_pt); | ||
| 3452 | } | ||
| 3453 | |||
| 3318 | /*---------------------------- Hashing Policies -----------------------------*/ | 3454 | /*---------------------------- Hashing Policies -----------------------------*/ |
| 3319 | 3455 | ||
| 3320 | /* | 3456 | /* |
| @@ -3401,6 +3537,9 @@ static int bond_open(struct net_device *bond_dev) | |||
| 3401 | } else { | 3537 | } else { |
| 3402 | arp_timer->function = (void *)&bond_loadbalance_arp_mon; | 3538 | arp_timer->function = (void *)&bond_loadbalance_arp_mon; |
| 3403 | } | 3539 | } |
| 3540 | if (bond->params.arp_validate) | ||
| 3541 | bond_register_arp(bond); | ||
| 3542 | |||
| 3404 | add_timer(arp_timer); | 3543 | add_timer(arp_timer); |
| 3405 | } | 3544 | } |
| 3406 | 3545 | ||
| @@ -3428,6 +3567,9 @@ static int bond_close(struct net_device *bond_dev) | |||
| 3428 | bond_unregister_lacpdu(bond); | 3567 | bond_unregister_lacpdu(bond); |
| 3429 | } | 3568 | } |
| 3430 | 3569 | ||
| 3570 | if (bond->params.arp_validate) | ||
| 3571 | bond_unregister_arp(bond); | ||
| 3572 | |||
| 3431 | write_lock_bh(&bond->lock); | 3573 | write_lock_bh(&bond->lock); |
| 3432 | 3574 | ||
| 3433 | 3575 | ||
| @@ -4281,6 +4423,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl) | |||
| 4281 | 4423 | ||
| 4282 | static int bond_check_params(struct bond_params *params) | 4424 | static int bond_check_params(struct bond_params *params) |
| 4283 | { | 4425 | { |
| 4426 | int arp_validate_value; | ||
| 4427 | |||
| 4284 | /* | 4428 | /* |
| 4285 | * Convert string parameters. | 4429 | * Convert string parameters. |
| 4286 | */ | 4430 | */ |
| @@ -4484,6 +4628,29 @@ static int bond_check_params(struct bond_params *params) | |||
| 4484 | arp_interval = 0; | 4628 | arp_interval = 0; |
| 4485 | } | 4629 | } |
| 4486 | 4630 | ||
| 4631 | if (arp_validate) { | ||
| 4632 | if (bond_mode != BOND_MODE_ACTIVEBACKUP) { | ||
| 4633 | printk(KERN_ERR DRV_NAME | ||
| 4634 | ": arp_validate only supported in active-backup mode\n"); | ||
| 4635 | return -EINVAL; | ||
| 4636 | } | ||
| 4637 | if (!arp_interval) { | ||
| 4638 | printk(KERN_ERR DRV_NAME | ||
| 4639 | ": arp_validate requires arp_interval\n"); | ||
| 4640 | return -EINVAL; | ||
| 4641 | } | ||
| 4642 | |||
| 4643 | arp_validate_value = bond_parse_parm(arp_validate, | ||
| 4644 | arp_validate_tbl); | ||
| 4645 | if (arp_validate_value == -1) { | ||
| 4646 | printk(KERN_ERR DRV_NAME | ||
| 4647 | ": Error: invalid arp_validate \"%s\"\n", | ||
| 4648 | arp_validate == NULL ? "NULL" : arp_validate); | ||
| 4649 | return -EINVAL; | ||
| 4650 | } | ||
| 4651 | } else | ||
| 4652 | arp_validate_value = 0; | ||
| 4653 | |||
| 4487 | if (miimon) { | 4654 | if (miimon) { |
| 4488 | printk(KERN_INFO DRV_NAME | 4655 | printk(KERN_INFO DRV_NAME |
| 4489 | ": MII link monitoring set to %d ms\n", | 4656 | ": MII link monitoring set to %d ms\n", |
| @@ -4492,8 +4659,10 @@ static int bond_check_params(struct bond_params *params) | |||
| 4492 | int i; | 4659 | int i; |
| 4493 | 4660 | ||
| 4494 | printk(KERN_INFO DRV_NAME | 4661 | printk(KERN_INFO DRV_NAME |
| 4495 | ": ARP monitoring set to %d ms with %d target(s):", | 4662 | ": ARP monitoring set to %d ms, validate %s, with %d target(s):", |
| 4496 | arp_interval, arp_ip_count); | 4663 | arp_interval, |
| 4664 | arp_validate_tbl[arp_validate_value].modename, | ||
| 4665 | arp_ip_count); | ||
| 4497 | 4666 | ||
| 4498 | for (i = 0; i < arp_ip_count; i++) | 4667 | for (i = 0; i < arp_ip_count; i++) |
| 4499 | printk (" %s", arp_ip_target[i]); | 4668 | printk (" %s", arp_ip_target[i]); |
| @@ -4527,6 +4696,7 @@ static int bond_check_params(struct bond_params *params) | |||
| 4527 | params->xmit_policy = xmit_hashtype; | 4696 | params->xmit_policy = xmit_hashtype; |
| 4528 | params->miimon = miimon; | 4697 | params->miimon = miimon; |
| 4529 | params->arp_interval = arp_interval; | 4698 | params->arp_interval = arp_interval; |
| 4699 | params->arp_validate = arp_validate_value; | ||
| 4530 | params->updelay = updelay; | 4700 | params->updelay = updelay; |
| 4531 | params->downdelay = downdelay; | 4701 | params->downdelay = downdelay; |
| 4532 | params->use_carrier = use_carrier; | 4702 | params->use_carrier = use_carrier; |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 15b6a29bb4d4..ced9ed8f995a 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
| @@ -51,6 +51,7 @@ extern struct bond_params bonding_defaults; | |||
| 51 | extern struct bond_parm_tbl bond_mode_tbl[]; | 51 | extern struct bond_parm_tbl bond_mode_tbl[]; |
| 52 | extern struct bond_parm_tbl bond_lacp_tbl[]; | 52 | extern struct bond_parm_tbl bond_lacp_tbl[]; |
| 53 | extern struct bond_parm_tbl xmit_hashtype_tbl[]; | 53 | extern struct bond_parm_tbl xmit_hashtype_tbl[]; |
| 54 | extern struct bond_parm_tbl arp_validate_tbl[]; | ||
| 54 | 55 | ||
| 55 | static int expected_refcount = -1; | 56 | static int expected_refcount = -1; |
| 56 | static struct class *netdev_class; | 57 | static struct class *netdev_class; |
| @@ -503,6 +504,53 @@ out: | |||
| 503 | static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); | 504 | static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash); |
| 504 | 505 | ||
| 505 | /* | 506 | /* |
| 507 | * Show and set arp_validate. | ||
| 508 | */ | ||
| 509 | static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf) | ||
| 510 | { | ||
| 511 | struct bonding *bond = to_bond(cd); | ||
| 512 | |||
| 513 | return sprintf(buf, "%s %d\n", | ||
| 514 | arp_validate_tbl[bond->params.arp_validate].modename, | ||
| 515 | bond->params.arp_validate) + 1; | ||
| 516 | } | ||
| 517 | |||
| 518 | static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count) | ||
| 519 | { | ||
| 520 | int new_value; | ||
| 521 | struct bonding *bond = to_bond(cd); | ||
| 522 | |||
| 523 | new_value = bond_parse_parm((char *)buf, arp_validate_tbl); | ||
| 524 | if (new_value < 0) { | ||
| 525 | printk(KERN_ERR DRV_NAME | ||
| 526 | ": %s: Ignoring invalid arp_validate value %s\n", | ||
| 527 | bond->dev->name, buf); | ||
| 528 | return -EINVAL; | ||
| 529 | } | ||
| 530 | if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) { | ||
| 531 | printk(KERN_ERR DRV_NAME | ||
| 532 | ": %s: arp_validate only supported in active-backup mode.\n", | ||
| 533 | bond->dev->name); | ||
| 534 | return -EINVAL; | ||
| 535 | } | ||
| 536 | printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n", | ||
| 537 | bond->dev->name, arp_validate_tbl[new_value].modename, | ||
| 538 | new_value); | ||
| 539 | |||
| 540 | if (!bond->params.arp_validate && new_value) { | ||
| 541 | bond_register_arp(bond); | ||
| 542 | } else if (bond->params.arp_validate && !new_value) { | ||
| 543 | bond_unregister_arp(bond); | ||
| 544 | } | ||
| 545 | |||
| 546 | bond->params.arp_validate = new_value; | ||
| 547 | |||
| 548 | return count; | ||
| 549 | } | ||
| 550 | |||
| 551 | static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate); | ||
| 552 | |||
| 553 | /* | ||
| 506 | * Show and set the arp timer interval. There are two tricky bits | 554 | * Show and set the arp timer interval. There are two tricky bits |
| 507 | * here. First, if ARP monitoring is activated, then we must disable | 555 | * here. First, if ARP monitoring is activated, then we must disable |
| 508 | * MII monitoring. Second, if the ARP timer isn't running, we must | 556 | * MII monitoring. Second, if the ARP timer isn't running, we must |
| @@ -914,6 +962,11 @@ static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, si | |||
| 914 | "ARP monitoring. Disabling ARP monitoring...\n", | 962 | "ARP monitoring. Disabling ARP monitoring...\n", |
| 915 | bond->dev->name); | 963 | bond->dev->name); |
| 916 | bond->params.arp_interval = 0; | 964 | bond->params.arp_interval = 0; |
| 965 | if (bond->params.arp_validate) { | ||
| 966 | bond_unregister_arp(bond); | ||
| 967 | bond->params.arp_validate = | ||
| 968 | BOND_ARP_VALIDATE_NONE; | ||
| 969 | } | ||
| 917 | /* Kill ARP timer, else it brings bond's link down */ | 970 | /* Kill ARP timer, else it brings bond's link down */ |
| 918 | if (bond->mii_timer.function) { | 971 | if (bond->mii_timer.function) { |
| 919 | printk(KERN_INFO DRV_NAME | 972 | printk(KERN_INFO DRV_NAME |
| @@ -1273,6 +1326,7 @@ static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, N | |||
| 1273 | static struct attribute *per_bond_attrs[] = { | 1326 | static struct attribute *per_bond_attrs[] = { |
| 1274 | &class_device_attr_slaves.attr, | 1327 | &class_device_attr_slaves.attr, |
| 1275 | &class_device_attr_mode.attr, | 1328 | &class_device_attr_mode.attr, |
| 1329 | &class_device_attr_arp_validate.attr, | ||
| 1276 | &class_device_attr_arp_interval.attr, | 1330 | &class_device_attr_arp_interval.attr, |
| 1277 | &class_device_attr_arp_ip_target.attr, | 1331 | &class_device_attr_arp_ip_target.attr, |
| 1278 | &class_device_attr_downdelay.attr, | 1332 | &class_device_attr_downdelay.attr, |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 17caafe58247..db16fee40a5f 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
| @@ -22,8 +22,8 @@ | |||
| 22 | #include "bond_3ad.h" | 22 | #include "bond_3ad.h" |
| 23 | #include "bond_alb.h" | 23 | #include "bond_alb.h" |
| 24 | 24 | ||
| 25 | #define DRV_VERSION "3.0.3" | 25 | #define DRV_VERSION "3.1.0-test" |
| 26 | #define DRV_RELDATE "March 23, 2006" | 26 | #define DRV_RELDATE "September 9, 2006" |
| 27 | #define DRV_NAME "bonding" | 27 | #define DRV_NAME "bonding" |
| 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" | 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" |
| 29 | 29 | ||
| @@ -126,6 +126,7 @@ struct bond_params { | |||
| 126 | int xmit_policy; | 126 | int xmit_policy; |
| 127 | int miimon; | 127 | int miimon; |
| 128 | int arp_interval; | 128 | int arp_interval; |
| 129 | int arp_validate; | ||
| 129 | int use_carrier; | 130 | int use_carrier; |
| 130 | int updelay; | 131 | int updelay; |
| 131 | int downdelay; | 132 | int downdelay; |
| @@ -151,6 +152,7 @@ struct slave { | |||
| 151 | struct slave *prev; | 152 | struct slave *prev; |
| 152 | int delay; | 153 | int delay; |
| 153 | u32 jiffies; | 154 | u32 jiffies; |
| 155 | u32 last_arp_rx; | ||
| 154 | s8 link; /* one of BOND_LINK_XXXX */ | 156 | s8 link; /* one of BOND_LINK_XXXX */ |
| 155 | s8 state; /* one of BOND_STATE_XXXX */ | 157 | s8 state; /* one of BOND_STATE_XXXX */ |
| 156 | u32 original_flags; | 158 | u32 original_flags; |
| @@ -198,6 +200,7 @@ struct bonding { | |||
| 198 | struct bond_params params; | 200 | struct bond_params params; |
| 199 | struct list_head vlan_list; | 201 | struct list_head vlan_list; |
| 200 | struct vlan_group *vlgrp; | 202 | struct vlan_group *vlgrp; |
| 203 | struct packet_type arp_mon_pt; | ||
| 201 | }; | 204 | }; |
| 202 | 205 | ||
| 203 | /** | 206 | /** |
| @@ -228,6 +231,25 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) | |||
| 228 | return (struct bonding *)slave->dev->master->priv; | 231 | return (struct bonding *)slave->dev->master->priv; |
| 229 | } | 232 | } |
| 230 | 233 | ||
| 234 | #define BOND_ARP_VALIDATE_NONE 0 | ||
| 235 | #define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE) | ||
| 236 | #define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP) | ||
| 237 | #define BOND_ARP_VALIDATE_ALL (BOND_ARP_VALIDATE_ACTIVE | \ | ||
| 238 | BOND_ARP_VALIDATE_BACKUP) | ||
| 239 | |||
| 240 | extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave) | ||
| 241 | { | ||
| 242 | return bond->params.arp_validate & (1 << slave->state); | ||
| 243 | } | ||
| 244 | |||
| 245 | extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave) | ||
| 246 | { | ||
| 247 | if (slave_do_arp_validate(bond, slave)) | ||
| 248 | return slave->last_arp_rx; | ||
| 249 | |||
| 250 | return slave->dev->last_rx; | ||
| 251 | } | ||
| 252 | |||
| 231 | static inline void bond_set_slave_inactive_flags(struct slave *slave) | 253 | static inline void bond_set_slave_inactive_flags(struct slave *slave) |
| 232 | { | 254 | { |
| 233 | struct bonding *bond = slave->dev->master->priv; | 255 | struct bonding *bond = slave->dev->master->priv; |
| @@ -235,12 +257,14 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave) | |||
| 235 | bond->params.mode != BOND_MODE_ALB) | 257 | bond->params.mode != BOND_MODE_ALB) |
| 236 | slave->state = BOND_STATE_BACKUP; | 258 | slave->state = BOND_STATE_BACKUP; |
| 237 | slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; | 259 | slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; |
| 260 | if (slave_do_arp_validate(bond, slave)) | ||
| 261 | slave->dev->priv_flags |= IFF_SLAVE_NEEDARP; | ||
| 238 | } | 262 | } |
| 239 | 263 | ||
| 240 | static inline void bond_set_slave_active_flags(struct slave *slave) | 264 | static inline void bond_set_slave_active_flags(struct slave *slave) |
| 241 | { | 265 | { |
| 242 | slave->state = BOND_STATE_ACTIVE; | 266 | slave->state = BOND_STATE_ACTIVE; |
| 243 | slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; | 267 | slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP); |
| 244 | } | 268 | } |
| 245 | 269 | ||
| 246 | static inline void bond_set_master_3ad_flags(struct bonding *bond) | 270 | static inline void bond_set_master_3ad_flags(struct bonding *bond) |
| @@ -284,6 +308,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl); | |||
| 284 | const char *bond_mode_name(int mode); | 308 | const char *bond_mode_name(int mode); |
| 285 | void bond_select_active_slave(struct bonding *bond); | 309 | void bond_select_active_slave(struct bonding *bond); |
| 286 | void bond_change_active_slave(struct bonding *bond, struct slave *new_active); | 310 | void bond_change_active_slave(struct bonding *bond, struct slave *new_active); |
| 311 | void bond_register_arp(struct bonding *); | ||
| 312 | void bond_unregister_arp(struct bonding *); | ||
| 287 | 313 | ||
| 288 | #endif /* _LINUX_BONDING_H */ | 314 | #endif /* _LINUX_BONDING_H */ |
| 289 | 315 | ||
diff --git a/include/linux/if.h b/include/linux/if.h index a023ec1274fe..8018c2e22c0c 100644 --- a/include/linux/if.h +++ b/include/linux/if.h | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | #define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ | 60 | #define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ |
| 61 | #define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ | 61 | #define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ |
| 62 | #define IFF_BONDING 0x20 /* bonding master or slave */ | 62 | #define IFF_BONDING 0x20 /* bonding master or slave */ |
| 63 | #define IFF_SLAVE_NEEDARP 0x40 /* need ARPs for validation */ | ||
| 63 | 64 | ||
| 64 | #define IF_GET_IFACE 0x0001 /* for querying only */ | 65 | #define IF_GET_IFACE 0x0001 /* for querying only */ |
| 65 | #define IF_GET_PROTO 0x0002 | 66 | #define IF_GET_PROTO 0x0002 |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 43289127b458..afd80eff2725 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
| @@ -1016,7 +1016,8 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) | |||
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | /* On bonding slaves other than the currently active slave, suppress | 1018 | /* On bonding slaves other than the currently active slave, suppress |
| 1019 | * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast. | 1019 | * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and |
| 1020 | * ARP on active-backup slaves with arp_validate enabled. | ||
| 1020 | */ | 1021 | */ |
| 1021 | static inline int skb_bond_should_drop(struct sk_buff *skb) | 1022 | static inline int skb_bond_should_drop(struct sk_buff *skb) |
| 1022 | { | 1023 | { |
| @@ -1025,6 +1026,10 @@ static inline int skb_bond_should_drop(struct sk_buff *skb) | |||
| 1025 | 1026 | ||
| 1026 | if (master && | 1027 | if (master && |
| 1027 | (dev->priv_flags & IFF_SLAVE_INACTIVE)) { | 1028 | (dev->priv_flags & IFF_SLAVE_INACTIVE)) { |
| 1029 | if ((dev->priv_flags & IFF_SLAVE_NEEDARP) && | ||
| 1030 | skb->protocol == __constant_htons(ETH_P_ARP)) | ||
| 1031 | return 0; | ||
| 1032 | |||
| 1028 | if (master->priv_flags & IFF_MASTER_ALB) { | 1033 | if (master->priv_flags & IFF_MASTER_ALB) { |
| 1029 | if (skb->pkt_type != PACKET_BROADCAST && | 1034 | if (skb->pkt_type != PACKET_BROADCAST && |
| 1030 | skb->pkt_type != PACKET_MULTICAST) | 1035 | skb->pkt_type != PACKET_MULTICAST) |
