Skip to content

Commit 21a75f0

Browse files
jay-vosburghdavem330
authored andcommitted
bonding: Fix ARP monitor validation
The current logic in bond_arp_rcv will accept an incoming ARP for validation if (a) the receiving slave is either "active" (which includes the currently active slave, or the current ARP slave) or, (b) there is a currently active slave, and it has received an ARP since it became active. For case (b), the receiving slave isn't the currently active slave, and is receiving the original broadcast ARP request, not an ARP reply from the target. This logic can fail if there is no currently active slave. In this situation, the ARP probe logic cycles through all slaves, assigning each in turn as the "current_arp_slave" for one arp_interval, then setting that one as "active," and sending an ARP probe from that slave. The current logic expects the ARP reply to arrive on the sending current_arp_slave, however, due to switch FDB updating delays, the reply may be directed to another slave. This can arise if the bonding slaves and switch are working, but the ARP target is not responding. When the ARP target recovers, a condition may result wherein the ARP target host replies faster than the switch can update its forwarding table, causing each ARP reply to be sent to the previous current_arp_slave. This will never pass the logic in bond_arp_rcv, as neither of the above conditions (a) or (b) are met. Some experimentation on a LAN shows ARP reply round trips in the 200 usec range, but my available switches never update their FDB in less than 4000 usec. This patch changes the logic in bond_arp_rcv to additionally accept an ARP reply for validation on any slave if there is a current ARP slave and it sent an ARP probe during the previous arp_interval. Fixes: aeea64a ("bonding: don't trust arp requests unless active slave really works") Cc: Veaceslav Falico <[email protected]> Cc: Andy Gospodarek <[email protected]> Signed-off-by: Jay Vosburgh <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c05235d commit 21a75f0

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ static void bond_uninit(struct net_device *bond_dev);
214214
static struct rtnl_link_stats64 *bond_get_stats(struct net_device *bond_dev,
215215
struct rtnl_link_stats64 *stats);
216216
static void bond_slave_arr_handler(struct work_struct *work);
217+
static bool bond_time_in_interval(struct bonding *bond, unsigned long last_act,
218+
int mod);
217219

218220
/*---------------------------- General routines -----------------------------*/
219221

@@ -2459,7 +2461,7 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
24592461
struct slave *slave)
24602462
{
24612463
struct arphdr *arp = (struct arphdr *)skb->data;
2462-
struct slave *curr_active_slave;
2464+
struct slave *curr_active_slave, *curr_arp_slave;
24632465
unsigned char *arp_ptr;
24642466
__be32 sip, tip;
24652467
int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
@@ -2506,26 +2508,41 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
25062508
&sip, &tip);
25072509

25082510
curr_active_slave = rcu_dereference(bond->curr_active_slave);
2511+
curr_arp_slave = rcu_dereference(bond->current_arp_slave);
25092512

2510-
/* Backup slaves won't see the ARP reply, but do come through
2511-
* here for each ARP probe (so we swap the sip/tip to validate
2512-
* the probe). In a "redundant switch, common router" type of
2513-
* configuration, the ARP probe will (hopefully) travel from
2514-
* the active, through one switch, the router, then the other
2515-
* switch before reaching the backup.
2513+
/* We 'trust' the received ARP enough to validate it if:
2514+
*
2515+
* (a) the slave receiving the ARP is active (which includes the
2516+
* current ARP slave, if any), or
2517+
*
2518+
* (b) the receiving slave isn't active, but there is a currently
2519+
* active slave and it received valid arp reply(s) after it became
2520+
* the currently active slave, or
2521+
*
2522+
* (c) there is an ARP slave that sent an ARP during the prior ARP
2523+
* interval, and we receive an ARP reply on any slave. We accept
2524+
* these because switch FDB update delays may deliver the ARP
2525+
* reply to a slave other than the sender of the ARP request.
25162526
*
2517-
* We 'trust' the arp requests if there is an active slave and
2518-
* it received valid arp reply(s) after it became active. This
2519-
* is done to avoid endless looping when we can't reach the
2527+
* Note: for (b), backup slaves are receiving the broadcast ARP
2528+
* request, not a reply. This request passes from the sending
2529+
* slave through the L2 switch(es) to the receiving slave. Since
2530+
* this is checking the request, sip/tip are swapped for
2531+
* validation.
2532+
*
2533+
* This is done to avoid endless looping when we can't reach the
25202534
* arp_ip_target and fool ourselves with our own arp requests.
25212535
*/
2522-
25232536
if (bond_is_active_slave(slave))
25242537
bond_validate_arp(bond, slave, sip, tip);
25252538
else if (curr_active_slave &&
25262539
time_after(slave_last_rx(bond, curr_active_slave),
25272540
curr_active_slave->last_link_up))
25282541
bond_validate_arp(bond, slave, tip, sip);
2542+
else if (curr_arp_slave && (arp->ar_op == htons(ARPOP_REPLY)) &&
2543+
bond_time_in_interval(bond,
2544+
dev_trans_start(curr_arp_slave->dev), 1))
2545+
bond_validate_arp(bond, slave, sip, tip);
25292546

25302547
out_unlock:
25312548
if (arp != (struct arphdr *)skb->data)

0 commit comments

Comments
 (0)