diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2006-09-23 00:54:53 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-25 20:08:09 -0400 |
commit | f5b2b966f032f22d3a289045a5afd4afa09f09c6 (patch) | |
tree | cb3c505d8f444438bed09353788f6c96150f68ad | |
parent | 70298705bb29fb7982b85089adf17cd37b94baa7 (diff) |
[PATCH] bonding: Validate probe replies in ARP monitor
Add logic to check ARP request / reply packets used for ARP
monitor link integrity checking.
The current method simply examines the slave device to see if it
has sent and received traffic; this can be fooled by extraneous traffic.
For example, if multiple hosts running bonding are behind a common
switch, the probe traffic from the multiple instances of bonding will
update the tx/rx times on each other's slave devices.
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-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) |