Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7893b249 authored by Moni Shoua's avatar Moni Shoua Committed by Jeff Garzik
Browse files

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: default avatarMoni Shoua <monis@voltaire.com>
Acked-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 8047637c
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@
#define BOND_LINK_ARP_INTERV	0

static int max_bonds	= BOND_DEFAULT_MAX_BONDS;
static int num_grat_arp = 1;
static int miimon	= BOND_LINK_MON_INTERV;
static int updelay	= 0;
static int downdelay	= 0;
@@ -104,6 +105,8 @@ struct bond_params bonding_defaults;

module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
module_param(num_grat_arp, int, 0644);
MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
module_param(miimon, int, 0);
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
module_param(updelay, int, 0);
@@ -1109,14 +1112,18 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
		if (new_active && bond->params.fail_over_mac)
			memcpy(bond->dev->dev_addr,  new_active->dev->dev_addr,
				new_active->dev->addr_len);
		bond->send_grat_arp = bond->params.num_grat_arp;
		if (bond->curr_active_slave &&
			test_bit(__LINK_STATE_LINKWATCH_PENDING,
					&bond->curr_active_slave->dev->state)) {
			dprintk("delaying gratuitous arp on %s\n",
				bond->curr_active_slave->dev->name);
			bond->send_grat_arp = 1;
		} else
		} else {
			if (bond->send_grat_arp > 0) {
				bond_send_gratuitous_arp(bond);
				bond->send_grat_arp--;
			}
		}
	}
}

@@ -2144,7 +2151,7 @@ static int __bond_mii_monitor(struct bonding *bond, int have_locks)
			dprintk("sending delayed gratuitous arp on on %s\n",
				bond->curr_active_slave->dev->name);
			bond_send_gratuitous_arp(bond);
			bond->send_grat_arp = 0;
			bond->send_grat_arp--;
		}
	}
	read_lock(&bond->curr_slave_lock);
@@ -4626,6 +4633,13 @@ static int bond_check_params(struct bond_params *params)
		use_carrier = 1;
	}

	if (num_grat_arp < 0 || num_grat_arp > 255) {
		printk(KERN_WARNING DRV_NAME
		       ": Warning: num_grat_arp (%d) not in range 0-255 so it "
		       "was reset to 1 \n", num_grat_arp);
		num_grat_arp = 1;
	}

	/* reset values for 802.3ad */
	if (bond_mode == BOND_MODE_8023AD) {
		if (!miimon) {
@@ -4813,6 +4827,7 @@ static int bond_check_params(struct bond_params *params)
	params->mode = bond_mode;
	params->xmit_policy = xmit_hashtype;
	params->miimon = miimon;
	params->num_grat_arp = num_grat_arp;
	params->arp_interval = arp_interval;
	params->arp_validate = arp_validate_value;
	params->updelay = updelay;
+40 −0
Original line number Diff line number Diff line
@@ -950,6 +950,45 @@ static ssize_t bonding_store_lacp(struct device *d,
}
static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);

/*
 * Show and set the number of grat ARP to send after a failover event.
 */
static ssize_t bonding_show_n_grat_arp(struct device *d,
				   struct device_attribute *attr,
				   char *buf)
{
	struct bonding *bond = to_bond(d);

	return sprintf(buf, "%d\n", bond->params.num_grat_arp);
}

static ssize_t bonding_store_n_grat_arp(struct device *d,
				    struct device_attribute *attr,
				    const char *buf, size_t count)
{
	int new_value, ret = count;
	struct bonding *bond = to_bond(d);

	if (sscanf(buf, "%d", &new_value) != 1) {
		printk(KERN_ERR DRV_NAME
		       ": %s: no num_grat_arp value specified.\n",
		       bond->dev->name);
		ret = -EINVAL;
		goto out;
	}
	if (new_value < 0 || new_value > 255) {
		printk(KERN_ERR DRV_NAME
		       ": %s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
		       bond->dev->name, new_value);
		ret = -EINVAL;
		goto out;
	} else {
		bond->params.num_grat_arp = new_value;
	}
out:
	return ret;
}
static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
/*
 * Show and set the MII monitor interval.  There are two tricky bits
 * here.  First, if MII monitoring is activated, then we must disable
@@ -1387,6 +1426,7 @@ static struct attribute *per_bond_attrs[] = {
	&dev_attr_updelay.attr,
	&dev_attr_lacp_rate.attr,
	&dev_attr_xmit_hash_policy.attr,
	&dev_attr_num_grat_arp.attr,
	&dev_attr_miimon.attr,
	&dev_attr_primary.attr,
	&dev_attr_use_carrier.attr,
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ struct bond_params {
	int mode;
	int xmit_policy;
	int miimon;
	int num_grat_arp;
	int arp_interval;
	int arp_validate;
	int use_carrier;