diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2013-06-24 05:49:34 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-25 19:58:38 -0400 |
commit | 8599b52e14a1611dcb563289421bee76751f1d53 (patch) | |
tree | 0eddf2fc812131c8fc9f00451ef6ec24ae0f06d1 /drivers/net/bonding/bond_main.c | |
parent | d7d35c681fb4eae1fab3d93698e26a106ca7e79e (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.c | 33 |
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; | |||
104 | static int arp_interval = BOND_LINK_ARP_INTERV; | 104 | static int arp_interval = BOND_LINK_ARP_INTERV; |
105 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; | 105 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS]; |
106 | static char *arp_validate; | 106 | static char *arp_validate; |
107 | static char *arp_all_targets; | ||
107 | static char *fail_over_mac; | 108 | static char *fail_over_mac; |
108 | static int all_slaves_active = 0; | 109 | static int all_slaves_active = 0; |
109 | static struct bond_params bonding_defaults; | 110 | static struct bond_params bonding_defaults; |
@@ -166,6 +167,8 @@ module_param(arp_validate, charp, 0); | |||
166 | MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes; " | 167 | MODULE_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"); |
170 | module_param(arp_all_targets, charp, 0); | ||
171 | MODULE_PARM_DESC(arp_all_targets, "fail on any/all arp targets timeout; 0 for any (default), 1 for all"); | ||
169 | module_param(fail_over_mac, charp, 0); | 172 | module_param(fail_over_mac, charp, 0); |
170 | MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to " | 173 | MODULE_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 | ||
222 | const 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 | |||
219 | const struct bond_parm_tbl arp_validate_tbl[] = { | 228 | const 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 | ||
2611 | static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip) | 2622 | static 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 | ||
2625 | static int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, | 2640 | static 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) | |||
4409 | static int bond_check_params(struct bond_params *params) | 4424 | static 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; |