Linux Ethernet Bonding Driver HOWTO
- Latest update: 23 September 2009
+ Latest update: 27 April 2011
Initial release : Thomas Davis <tadavis at lbl.gov>
Corrections, HA extensions : 2000/10/03-15 :
chosen.
num_grat_arp
-
- Specifies the number of gratuitous ARPs to be issued after a
- failover event. One gratuitous ARP is issued immediately after
- the failover, subsequent ARPs are sent at a rate of one per link
- monitor interval (arp_interval or miimon, whichever is active).
-
- The valid range is 0 - 255; the default value is 1. This option
- affects only the active-backup mode. This option was added for
- bonding version 3.3.0.
-
num_unsol_na
- Specifies the number of unsolicited IPv6 Neighbor Advertisements
- to be issued after a failover event. One unsolicited NA is issued
- immediately after the failover.
-
- The valid range is 0 - 255; the default value is 1. This option
- affects only the active-backup mode. This option was added for
- bonding version 3.4.0.
+ Specify the number of peer notifications (gratuitous ARPs and
+ unsolicited IPv6 Neighbor Advertisements) to be issued after a
+ failover event. As soon as the link is up on the new slave
+ (possibly immediately) a peer notification is sent on the
+ bonding device and each VLAN sub-device. This is repeated at
+ each link monitor interval (arp_interval or miimon, whichever
+ is active) if the number is greater than 1.
+
+ The valid range is 0 - 255; the default value is 1. These options
+ affect only the active-backup mode. These options were added for
+ bonding versions 3.3.0 and 3.4.0 respectively.
+
+ From Linux 2.6.40 and bonding version 3.7.1, these notifications
+ are generated by the ipv4 and ipv6 code and the numbers of
+ repetitions cannot be set independently.
primary
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
static int tx_queues = BOND_DEFAULT_TX_QUEUES;
+static int num_peer_notif = 1;
static int miimon = BOND_LINK_MON_INTERV;
static int updelay;
static int downdelay;
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
module_param(tx_queues, int, 0);
MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)");
+module_param_named(num_grat_arp, num_peer_notif, int, 0644);
+MODULE_PARM_DESC(num_grat_arp, "Number of peer notifications to send on failover event (alias of num_unsol_na)");
+module_param_named(num_unsol_na, num_peer_notif, int, 0644);
+MODULE_PARM_DESC(num_unsol_na, "Number of peer notifications to send on failover event (alias of num_grat_arp)");
module_param(miimon, int, 0);
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
module_param(updelay, int, 0);
return bestslave;
}
+static bool bond_should_notify_peers(struct bonding *bond)
+{
+ struct slave *slave = bond->curr_active_slave;
+
+ pr_debug("bond_should_notify_peers: bond %s slave %s\n",
+ bond->dev->name, slave ? slave->dev->name : "NULL");
+
+ if (!slave || !bond->send_peer_notif ||
+ test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
+ return false;
+
+ bond->send_peer_notif--;
+ return true;
+}
+
/**
* change_active_interface - change the active slave into the specified one
* @bond: our bonding struct
bond_set_slave_inactive_flags(old_active);
if (new_active) {
+ bool should_notify_peers = false;
+
bond_set_slave_active_flags(new_active);
if (bond->params.fail_over_mac)
bond_do_fail_over_mac(bond, new_active,
old_active);
+ if (netif_running(bond->dev)) {
+ bond->send_peer_notif =
+ bond->params.num_peer_notif;
+ should_notify_peers =
+ bond_should_notify_peers(bond);
+ }
+
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
netdev_bonding_change(bond->dev, NETDEV_BONDING_FAILOVER);
+ if (should_notify_peers)
+ netdev_bonding_change(bond->dev,
+ NETDEV_NOTIFY_PEERS);
read_lock(&bond->lock);
write_lock_bh(&bond->curr_slave_lock);
{
struct bonding *bond = container_of(work, struct bonding,
mii_work.work);
+ bool should_notify_peers = false;
read_lock(&bond->lock);
if (bond->kill_timers)
if (bond->slave_cnt == 0)
goto re_arm;
+ should_notify_peers = bond_should_notify_peers(bond);
+
if (bond_miimon_inspect(bond)) {
read_unlock(&bond->lock);
rtnl_lock();
msecs_to_jiffies(bond->params.miimon));
out:
read_unlock(&bond->lock);
+
+ if (should_notify_peers) {
+ rtnl_lock();
+ netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
+ rtnl_unlock();
+ }
}
static __be32 bond_glean_dev_ip(struct net_device *dev)
{
struct bonding *bond = container_of(work, struct bonding,
arp_work.work);
+ bool should_notify_peers = false;
int delta_in_ticks;
read_lock(&bond->lock);
if (bond->slave_cnt == 0)
goto re_arm;
+ should_notify_peers = bond_should_notify_peers(bond);
+
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
read_unlock(&bond->lock);
rtnl_lock();
queue_delayed_work(bond->wq, &bond->arp_work, delta_in_ticks);
out:
read_unlock(&bond->lock);
+
+ if (should_notify_peers) {
+ rtnl_lock();
+ netdev_bonding_change(bond->dev, NETDEV_NOTIFY_PEERS);
+ rtnl_unlock();
+ }
}
/*-------------------------- netdev event handling --------------------------*/
write_lock_bh(&bond->lock);
+ bond->send_peer_notif = 0;
+
/* signal timers not to re-arm */
bond->kill_timers = 1;
use_carrier = 1;
}
+ if (num_peer_notif < 0 || num_peer_notif > 255) {
+ pr_warning("Warning: num_grat_arp/num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
+ num_peer_notif);
+ num_peer_notif = 1;
+ }
+
/* reset values for 802.3ad */
if (bond_mode == BOND_MODE_8023AD) {
if (!miimon) {
params->mode = bond_mode;
params->xmit_policy = xmit_hashtype;
params->miimon = miimon;
+ params->num_peer_notif = num_peer_notif;
params->arp_interval = arp_interval;
params->arp_validate = arp_validate_value;
params->updelay = updelay;
static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
bonding_show_ad_select, bonding_store_ad_select);
+/*
+ * Show and set the number of peer notifications to send after a failover event.
+ */
+static ssize_t bonding_show_num_peer_notif(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+ return sprintf(buf, "%d\n", bond->params.num_peer_notif);
+}
+
+static ssize_t bonding_store_num_peer_notif(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct bonding *bond = to_bond(d);
+ int err = kstrtou8(buf, 10, &bond->params.num_peer_notif);
+ return err ? err : count;
+}
+static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
+ bonding_show_num_peer_notif, bonding_store_num_peer_notif);
+static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
+ bonding_show_num_peer_notif, bonding_store_num_peer_notif);
+
/*
* Show and set the MII monitor interval. There are two tricky bits
* here. First, if MII monitoring is activated, then we must disable
&dev_attr_lacp_rate.attr,
&dev_attr_ad_select.attr,
&dev_attr_xmit_hash_policy.attr,
+ &dev_attr_num_grat_arp.attr,
+ &dev_attr_num_unsol_na.attr,
&dev_attr_miimon.attr,
&dev_attr_primary.attr,
&dev_attr_primary_reselect.attr,