diff options
author | Moni Shoua <monis@voltaire.com> | 2008-05-18 00:10:12 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-22 06:34:26 -0400 |
commit | 7893b2491a2d5f716540ac5643d78d37a7f6628b (patch) | |
tree | 2558b83e5a19b7d4a6b3c10c5bb90919bb1f3889 /drivers | |
parent | 8047637c70e4451e2ac1c17ed9a91a2f753daae7 (diff) |
bonding: Send more than one gratuitous ARP when slave takes over
With IPoIB, reception of gratuitous ARP by neighboring hosts
is essential for a successful change of slaves in case of failure.
Otherwise, they won't learn about the HW address change and need
to wait a long time until the neighboring system gives up and sends
an ARP request to learn the new HW address. This patch decreases
the chance for a lost of a gratuitous ARP packet by sending it more
than once. The number retries is configurable and can be set with a
module param.
Signed-off-by: Moni Shoua <monis@voltaire.com>
Acked-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 23 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 40 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 1 |
3 files changed, 60 insertions, 4 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2a0039f19377..fa3c2101fe75 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -88,6 +88,7 @@ | |||
88 | #define BOND_LINK_ARP_INTERV 0 | 88 | #define BOND_LINK_ARP_INTERV 0 |
89 | 89 | ||
90 | static int max_bonds = BOND_DEFAULT_MAX_BONDS; | 90 | static int max_bonds = BOND_DEFAULT_MAX_BONDS; |
91 | static int num_grat_arp = 1; | ||
91 | static int miimon = BOND_LINK_MON_INTERV; | 92 | static int miimon = BOND_LINK_MON_INTERV; |
92 | static int updelay = 0; | 93 | static int updelay = 0; |
93 | static int downdelay = 0; | 94 | static int downdelay = 0; |
@@ -104,6 +105,8 @@ struct bond_params bonding_defaults; | |||
104 | 105 | ||
105 | module_param(max_bonds, int, 0); | 106 | module_param(max_bonds, int, 0); |
106 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); | 107 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); |
108 | module_param(num_grat_arp, int, 0644); | ||
109 | MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event"); | ||
107 | module_param(miimon, int, 0); | 110 | module_param(miimon, int, 0); |
108 | MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); | 111 | MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); |
109 | module_param(updelay, int, 0); | 112 | module_param(updelay, int, 0); |
@@ -1109,14 +1112,18 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
1109 | if (new_active && bond->params.fail_over_mac) | 1112 | if (new_active && bond->params.fail_over_mac) |
1110 | memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, | 1113 | memcpy(bond->dev->dev_addr, new_active->dev->dev_addr, |
1111 | new_active->dev->addr_len); | 1114 | new_active->dev->addr_len); |
1115 | bond->send_grat_arp = bond->params.num_grat_arp; | ||
1112 | if (bond->curr_active_slave && | 1116 | if (bond->curr_active_slave && |
1113 | test_bit(__LINK_STATE_LINKWATCH_PENDING, | 1117 | test_bit(__LINK_STATE_LINKWATCH_PENDING, |
1114 | &bond->curr_active_slave->dev->state)) { | 1118 | &bond->curr_active_slave->dev->state)) { |
1115 | dprintk("delaying gratuitous arp on %s\n", | 1119 | dprintk("delaying gratuitous arp on %s\n", |
1116 | bond->curr_active_slave->dev->name); | 1120 | bond->curr_active_slave->dev->name); |
1117 | bond->send_grat_arp = 1; | 1121 | } else { |
1118 | } else | 1122 | if (bond->send_grat_arp > 0) { |
1119 | bond_send_gratuitous_arp(bond); | 1123 | bond_send_gratuitous_arp(bond); |
1124 | bond->send_grat_arp--; | ||
1125 | } | ||
1126 | } | ||
1120 | } | 1127 | } |
1121 | } | 1128 | } |
1122 | 1129 | ||
@@ -2144,7 +2151,7 @@ static int __bond_mii_monitor(struct bonding *bond, int have_locks) | |||
2144 | dprintk("sending delayed gratuitous arp on on %s\n", | 2151 | dprintk("sending delayed gratuitous arp on on %s\n", |
2145 | bond->curr_active_slave->dev->name); | 2152 | bond->curr_active_slave->dev->name); |
2146 | bond_send_gratuitous_arp(bond); | 2153 | bond_send_gratuitous_arp(bond); |
2147 | bond->send_grat_arp = 0; | 2154 | bond->send_grat_arp--; |
2148 | } | 2155 | } |
2149 | } | 2156 | } |
2150 | read_lock(&bond->curr_slave_lock); | 2157 | read_lock(&bond->curr_slave_lock); |
@@ -4626,6 +4633,13 @@ static int bond_check_params(struct bond_params *params) | |||
4626 | use_carrier = 1; | 4633 | use_carrier = 1; |
4627 | } | 4634 | } |
4628 | 4635 | ||
4636 | if (num_grat_arp < 0 || num_grat_arp > 255) { | ||
4637 | printk(KERN_WARNING DRV_NAME | ||
4638 | ": Warning: num_grat_arp (%d) not in range 0-255 so it " | ||
4639 | "was reset to 1 \n", num_grat_arp); | ||
4640 | num_grat_arp = 1; | ||
4641 | } | ||
4642 | |||
4629 | /* reset values for 802.3ad */ | 4643 | /* reset values for 802.3ad */ |
4630 | if (bond_mode == BOND_MODE_8023AD) { | 4644 | if (bond_mode == BOND_MODE_8023AD) { |
4631 | if (!miimon) { | 4645 | if (!miimon) { |
@@ -4813,6 +4827,7 @@ static int bond_check_params(struct bond_params *params) | |||
4813 | params->mode = bond_mode; | 4827 | params->mode = bond_mode; |
4814 | params->xmit_policy = xmit_hashtype; | 4828 | params->xmit_policy = xmit_hashtype; |
4815 | params->miimon = miimon; | 4829 | params->miimon = miimon; |
4830 | params->num_grat_arp = num_grat_arp; | ||
4816 | params->arp_interval = arp_interval; | 4831 | params->arp_interval = arp_interval; |
4817 | params->arp_validate = arp_validate_value; | 4832 | params->arp_validate = arp_validate_value; |
4818 | params->updelay = updelay; | 4833 | params->updelay = updelay; |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 1f028579e53b..7a61e9a14386 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -951,6 +951,45 @@ out: | |||
951 | static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); | 951 | static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp); |
952 | 952 | ||
953 | /* | 953 | /* |
954 | * Show and set the number of grat ARP to send after a failover event. | ||
955 | */ | ||
956 | static ssize_t bonding_show_n_grat_arp(struct device *d, | ||
957 | struct device_attribute *attr, | ||
958 | char *buf) | ||
959 | { | ||
960 | struct bonding *bond = to_bond(d); | ||
961 | |||
962 | return sprintf(buf, "%d\n", bond->params.num_grat_arp); | ||
963 | } | ||
964 | |||
965 | static ssize_t bonding_store_n_grat_arp(struct device *d, | ||
966 | struct device_attribute *attr, | ||
967 | const char *buf, size_t count) | ||
968 | { | ||
969 | int new_value, ret = count; | ||
970 | struct bonding *bond = to_bond(d); | ||
971 | |||
972 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
973 | printk(KERN_ERR DRV_NAME | ||
974 | ": %s: no num_grat_arp value specified.\n", | ||
975 | bond->dev->name); | ||
976 | ret = -EINVAL; | ||
977 | goto out; | ||
978 | } | ||
979 | if (new_value < 0 || new_value > 255) { | ||
980 | printk(KERN_ERR DRV_NAME | ||
981 | ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n", | ||
982 | bond->dev->name, new_value); | ||
983 | ret = -EINVAL; | ||
984 | goto out; | ||
985 | } else { | ||
986 | bond->params.num_grat_arp = new_value; | ||
987 | } | ||
988 | out: | ||
989 | return ret; | ||
990 | } | ||
991 | static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp); | ||
992 | /* | ||
954 | * Show and set the MII monitor interval. There are two tricky bits | 993 | * Show and set the MII monitor interval. There are two tricky bits |
955 | * here. First, if MII monitoring is activated, then we must disable | 994 | * here. First, if MII monitoring is activated, then we must disable |
956 | * ARP monitoring. Second, if the timer isn't running, we must | 995 | * ARP monitoring. Second, if the timer isn't running, we must |
@@ -1387,6 +1426,7 @@ static struct attribute *per_bond_attrs[] = { | |||
1387 | &dev_attr_updelay.attr, | 1426 | &dev_attr_updelay.attr, |
1388 | &dev_attr_lacp_rate.attr, | 1427 | &dev_attr_lacp_rate.attr, |
1389 | &dev_attr_xmit_hash_policy.attr, | 1428 | &dev_attr_xmit_hash_policy.attr, |
1429 | &dev_attr_num_grat_arp.attr, | ||
1390 | &dev_attr_miimon.attr, | 1430 | &dev_attr_miimon.attr, |
1391 | &dev_attr_primary.attr, | 1431 | &dev_attr_primary.attr, |
1392 | &dev_attr_use_carrier.attr, | 1432 | &dev_attr_use_carrier.attr, |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 0ce7f4ae920f..46a2ed507b33 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -125,6 +125,7 @@ struct bond_params { | |||
125 | int mode; | 125 | int mode; |
126 | int xmit_policy; | 126 | int xmit_policy; |
127 | int miimon; | 127 | int miimon; |
128 | int num_grat_arp; | ||
128 | int arp_interval; | 129 | int arp_interval; |
129 | int arp_validate; | 130 | int arp_validate; |
130 | int use_carrier; | 131 | int use_carrier; |