aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_main.c
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2013-06-24 05:49:34 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-25 19:58:38 -0400
commit8599b52e14a1611dcb563289421bee76751f1d53 (patch)
tree0eddf2fc812131c8fc9f00451ef6ec24ae0f06d1 /drivers/net/bonding/bond_main.c
parentd7d35c681fb4eae1fab3d93698e26a106ca7e79e (diff)
bonding: add an option to fail when any of arp_ip_target is inaccessible
Currently, we fail only when all of the ips in arp_ip_target are gone. However, in some situations we might need to fail if even one host from arp_ip_target becomes unavailable. All situations, obviously, rely on the idea that we need *completely* functional network, with all interfaces/addresses working correctly. One real world example might be: vlans on top on bond (hybrid port). If bond and vlans have ips assigned and we have their peers monitored via arp_ip_target - in case of switch misconfiguration (trunk/access port), slave driver malfunction or tagged/untagged traffic dropped on the way - we will be able to switch to another slave. Though any other configuration needs that if we need to have access to all arp_ip_targets. This patch adds this possibility by adding a new parameter - arp_all_targets (both as a module parameter and as a sysfs knob). It can be set to: 0 or any (the default) - which works exactly as it's working now - the slave is up if any of the arp_ip_targets are up. 1 or all - the slave is up if all of the arp_ip_targets are up. This parameter can be changed on the fly (via sysfs), and requires the mode to be active-backup and arp_validate to be enabled (it obeys the arp_validate config on which slaves to validate). Internally it's done through: 1) Add target_last_arp_rx[BOND_MAX_ARP_TARGETS] array to slave struct. It's an array of jiffies, meaning that slave->target_last_arp_rx[i] is the last time we've received arp from bond->params.arp_targets[i] on this slave. 2) If we successfully validate an arp from bond->params.arp_targets[i] in bond_validate_arp() - update the slave->target_last_arp_rx[i] with the current jiffies value. 3) When getting slave's last_rx via slave_last_rx(), we return the oldest time when we've received an arp from any address in bond->params.arp_targets[]. If the value of arp_all_targets == 0 - we still work the same way as before. Also, update the documentation to reflect the new parameter. v3->v4: Kill the forgotten rtnl_unlock(), rephrase the documentation part to be more clear, don't fail setting arp_all_targets if arp_validate is not set - it has no effect anyway but can be easier to set up. Also, print a warning if the last arp_ip_target is removed while the arp_interval is on, but not the arp_validate. v2->v3: Use _bh spinlock, remove useless rtnl_lock() and use jiffies for new arp_ip_target last arp, instead of slave_last_rx(). On bond_enslave(), use the same initialization value for target_last_arp_rx[] as is used for the default last_arp_rx, to avoid useless interface flaps. Also, instead of failing to remove the last arp_ip_target just print a warning - otherwise it might break existing scripts. v1->v2: Correctly handle adding/removing hosts in arp_ip_target - we need to shift/initialize all slave's target_last_arp_rx. Also, don't fail module loading on arp_all_targets misconfiguration, just disable it, and some minor style fixes. Signed-off-by: Veaceslav Falico <vfalico@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r--drivers/net/bonding/bond_main.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index d3a70c0d0edd..142d55dc526e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -104,6 +104,7 @@ static char *xmit_hash_policy;
104static int arp_interval = BOND_LINK_ARP_INTERV; 104static int arp_interval = BOND_LINK_ARP_INTERV;
105static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; 105static char *arp_ip_target[BOND_MAX_ARP_TARGETS];
106static char *arp_validate; 106static char *arp_validate;
107static char *arp_all_targets;
107static char *fail_over_mac; 108static char *fail_over_mac;
108static int all_slaves_active = 0; 109static int all_slaves_active = 0;
109static struct bond_params bonding_defaults; 110static struct bond_params bonding_defaults;
@@ -166,6 +167,8 @@ module_param(arp_validate, charp, 0);
166MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes; " 167MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes; "
167 "0 for none (default), 1 for active, " 168 "0 for none (default), 1 for active, "
168 "2 for backup, 3 for all"); 169 "2 for backup, 3 for all");
170module_param(arp_all_targets, charp, 0);
171MODULE_PARM_DESC(arp_all_targets, "fail on any/all arp targets timeout; 0 for any (default), 1 for all");
169module_param(fail_over_mac, charp, 0); 172module_param(fail_over_mac, charp, 0);
170MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to " 173MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to "
171 "the same MAC; 0 for none (default), " 174 "the same MAC; 0 for none (default), "
@@ -216,6 +219,12 @@ const struct bond_parm_tbl xmit_hashtype_tbl[] = {
216{ NULL, -1}, 219{ NULL, -1},
217}; 220};
218 221
222const struct bond_parm_tbl arp_all_targets_tbl[] = {
223{ "any", BOND_ARP_TARGETS_ANY},
224{ "all", BOND_ARP_TARGETS_ALL},
225{ NULL, -1},
226};
227
219const struct bond_parm_tbl arp_validate_tbl[] = { 228const struct bond_parm_tbl arp_validate_tbl[] = {
220{ "none", BOND_ARP_VALIDATE_NONE}, 229{ "none", BOND_ARP_VALIDATE_NONE},
221{ "active", BOND_ARP_VALIDATE_ACTIVE}, 230{ "active", BOND_ARP_VALIDATE_ACTIVE},
@@ -1483,7 +1492,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1483 struct slave *new_slave = NULL; 1492 struct slave *new_slave = NULL;
1484 struct sockaddr addr; 1493 struct sockaddr addr;
1485 int link_reporting; 1494 int link_reporting;
1486 int res = 0; 1495 int res = 0, i;
1487 1496
1488 if (!bond->params.use_carrier && 1497 if (!bond->params.use_carrier &&
1489 slave_dev->ethtool_ops->get_link == NULL && 1498 slave_dev->ethtool_ops->get_link == NULL &&
@@ -1712,6 +1721,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1712 1721
1713 new_slave->last_arp_rx = jiffies - 1722 new_slave->last_arp_rx = jiffies -
1714 (msecs_to_jiffies(bond->params.arp_interval) + 1); 1723 (msecs_to_jiffies(bond->params.arp_interval) + 1);
1724 for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
1725 new_slave->target_last_arp_rx[i] = new_slave->last_arp_rx;
1715 1726
1716 if (bond->params.miimon && !bond->params.use_carrier) { 1727 if (bond->params.miimon && !bond->params.use_carrier) {
1717 link_reporting = bond_check_dev_link(bond, slave_dev, 1); 1728 link_reporting = bond_check_dev_link(bond, slave_dev, 1);
@@ -2610,16 +2621,20 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2610 2621
2611static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) 2622static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip)
2612{ 2623{
2624 int i;
2625
2613 if (!sip || !bond_has_this_ip(bond, tip)) { 2626 if (!sip || !bond_has_this_ip(bond, tip)) {
2614 pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip); 2627 pr_debug("bva: sip %pI4 tip %pI4 not found\n", &sip, &tip);
2615 return; 2628 return;
2616 } 2629 }
2617 2630
2618 if (bond_get_targets_ip(bond->params.arp_targets, sip) == -1) { 2631 i = bond_get_targets_ip(bond->params.arp_targets, sip);
2632 if (i == -1) {
2619 pr_debug("bva: sip %pI4 not found in targets\n", &sip); 2633 pr_debug("bva: sip %pI4 not found in targets\n", &sip);
2620 return; 2634 return;
2621 } 2635 }
2622 slave->last_arp_rx = jiffies; 2636 slave->last_arp_rx = jiffies;
2637 slave->target_last_arp_rx[i] = jiffies;
2623} 2638}
2624 2639
2625static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, 2640static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
@@ -4409,6 +4424,7 @@ int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
4409static int bond_check_params(struct bond_params *params) 4424static int bond_check_params(struct bond_params *params)
4410{ 4425{
4411 int arp_validate_value, fail_over_mac_value, primary_reselect_value, i; 4426 int arp_validate_value, fail_over_mac_value, primary_reselect_value, i;
4427 int arp_all_targets_value;
4412 4428
4413 /* 4429 /*
4414 * Convert string parameters. 4430 * Convert string parameters.
@@ -4634,6 +4650,18 @@ static int bond_check_params(struct bond_params *params)
4634 } else 4650 } else
4635 arp_validate_value = 0; 4651 arp_validate_value = 0;
4636 4652
4653 arp_all_targets_value = 0;
4654 if (arp_all_targets) {
4655 arp_all_targets_value = bond_parse_parm(arp_all_targets,
4656 arp_all_targets_tbl);
4657
4658 if (arp_all_targets_value == -1) {
4659 pr_err("Error: invalid arp_all_targets_value \"%s\"\n",
4660 arp_all_targets);
4661 arp_all_targets_value = 0;
4662 }
4663 }
4664
4637 if (miimon) { 4665 if (miimon) {
4638 pr_info("MII link monitoring set to %d ms\n", miimon); 4666 pr_info("MII link monitoring set to %d ms\n", miimon);
4639 } else if (arp_interval) { 4667 } else if (arp_interval) {
@@ -4698,6 +4726,7 @@ static int bond_check_params(struct bond_params *params)
4698 params->num_peer_notif = num_peer_notif; 4726 params->num_peer_notif = num_peer_notif;
4699 params->arp_interval = arp_interval; 4727 params->arp_interval = arp_interval;
4700 params->arp_validate = arp_validate_value; 4728 params->arp_validate = arp_validate_value;
4729 params->arp_all_targets = arp_all_targets_value;
4701 params->updelay = updelay; 4730 params->updelay = updelay;
4702 params->downdelay = downdelay; 4731 params->downdelay = downdelay;
4703 params->use_carrier = use_carrier; 4732 params->use_carrier = use_carrier;