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/bonding.h | |
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/bonding.h')
-rw-r--r-- | drivers/net/bonding/bonding.h | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 486e532f77e4..3fb73cc8c34a 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -144,6 +144,7 @@ struct bond_params { | |||
144 | u8 num_peer_notif; | 144 | u8 num_peer_notif; |
145 | int arp_interval; | 145 | int arp_interval; |
146 | int arp_validate; | 146 | int arp_validate; |
147 | int arp_all_targets; | ||
147 | int use_carrier; | 148 | int use_carrier; |
148 | int fail_over_mac; | 149 | int fail_over_mac; |
149 | int updelay; | 150 | int updelay; |
@@ -179,6 +180,7 @@ struct slave { | |||
179 | int delay; | 180 | int delay; |
180 | unsigned long jiffies; | 181 | unsigned long jiffies; |
181 | unsigned long last_arp_rx; | 182 | unsigned long last_arp_rx; |
183 | unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS]; | ||
182 | s8 link; /* one of BOND_LINK_XXXX */ | 184 | s8 link; /* one of BOND_LINK_XXXX */ |
183 | s8 new_link; | 185 | s8 new_link; |
184 | u8 backup:1, /* indicates backup slave. Value corresponds with | 186 | u8 backup:1, /* indicates backup slave. Value corresponds with |
@@ -322,6 +324,9 @@ static inline bool bond_is_active_slave(struct slave *slave) | |||
322 | #define BOND_FOM_ACTIVE 1 | 324 | #define BOND_FOM_ACTIVE 1 |
323 | #define BOND_FOM_FOLLOW 2 | 325 | #define BOND_FOM_FOLLOW 2 |
324 | 326 | ||
327 | #define BOND_ARP_TARGETS_ANY 0 | ||
328 | #define BOND_ARP_TARGETS_ALL 1 | ||
329 | |||
325 | #define BOND_ARP_VALIDATE_NONE 0 | 330 | #define BOND_ARP_VALIDATE_NONE 0 |
326 | #define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE) | 331 | #define BOND_ARP_VALIDATE_ACTIVE (1 << BOND_STATE_ACTIVE) |
327 | #define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP) | 332 | #define BOND_ARP_VALIDATE_BACKUP (1 << BOND_STATE_BACKUP) |
@@ -334,11 +339,31 @@ static inline int slave_do_arp_validate(struct bonding *bond, | |||
334 | return bond->params.arp_validate & (1 << bond_slave_state(slave)); | 339 | return bond->params.arp_validate & (1 << bond_slave_state(slave)); |
335 | } | 340 | } |
336 | 341 | ||
342 | /* Get the oldest arp which we've received on this slave for bond's | ||
343 | * arp_targets. | ||
344 | */ | ||
345 | static inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond, | ||
346 | struct slave *slave) | ||
347 | { | ||
348 | int i = 1; | ||
349 | unsigned long ret = slave->target_last_arp_rx[0]; | ||
350 | |||
351 | for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++) | ||
352 | if (time_before(slave->target_last_arp_rx[i], ret)) | ||
353 | ret = slave->target_last_arp_rx[i]; | ||
354 | |||
355 | return ret; | ||
356 | } | ||
357 | |||
337 | static inline unsigned long slave_last_rx(struct bonding *bond, | 358 | static inline unsigned long slave_last_rx(struct bonding *bond, |
338 | struct slave *slave) | 359 | struct slave *slave) |
339 | { | 360 | { |
340 | if (slave_do_arp_validate(bond, slave)) | 361 | if (slave_do_arp_validate(bond, slave)) { |
341 | return slave->last_arp_rx; | 362 | if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL) |
363 | return slave_oldest_target_arp_rx(bond, slave); | ||
364 | else | ||
365 | return slave->last_arp_rx; | ||
366 | } | ||
342 | 367 | ||
343 | return slave->dev->last_rx; | 368 | return slave->dev->last_rx; |
344 | } | 369 | } |
@@ -486,6 +511,7 @@ extern const struct bond_parm_tbl bond_lacp_tbl[]; | |||
486 | extern const struct bond_parm_tbl bond_mode_tbl[]; | 511 | extern const struct bond_parm_tbl bond_mode_tbl[]; |
487 | extern const struct bond_parm_tbl xmit_hashtype_tbl[]; | 512 | extern const struct bond_parm_tbl xmit_hashtype_tbl[]; |
488 | extern const struct bond_parm_tbl arp_validate_tbl[]; | 513 | extern const struct bond_parm_tbl arp_validate_tbl[]; |
514 | extern const struct bond_parm_tbl arp_all_targets_tbl[]; | ||
489 | extern const struct bond_parm_tbl fail_over_mac_tbl[]; | 515 | extern const struct bond_parm_tbl fail_over_mac_tbl[]; |
490 | extern const struct bond_parm_tbl pri_reselect_tbl[]; | 516 | extern const struct bond_parm_tbl pri_reselect_tbl[]; |
491 | extern struct bond_parm_tbl ad_select_tbl[]; | 517 | extern struct bond_parm_tbl ad_select_tbl[]; |