Skip to content

Commit 0410d07

Browse files
jiriwiesnerdavem330
authored andcommitted
bonding: fix active-backup failover for current ARP slave
When the ARP monitor is used for link detection, ARP replies are validated for all slaves (arp_validate=3) and fail_over_mac is set to active, two slaves of an active-backup bond may get stuck in a state where both of them are active and pass packets that they receive to the bond. This state makes IPv6 duplicate address detection fail. The state is reached thus: 1. The current active slave goes down because the ARP target is not reachable. 2. The current ARP slave is chosen and made active. 3. A new slave is enslaved. This new slave becomes the current active slave and can reach the ARP target. As a result, the current ARP slave stays active after the enslave action has finished and the log is littered with "PROBE BAD" messages: > bond0: PROBE: c_arp ens10 && cas ens11 BAD The workaround is to remove the slave with "going back" status from the bond and re-enslave it. This issue was encountered when DPDK PMD interfaces were being enslaved to an active-backup bond. I would be possible to fix the issue in bond_enslave() or bond_change_active_slave() but the ARP monitor was fixed instead to keep most of the actions changing the current ARP slave in the ARP monitor code. The current ARP slave is set as inactive and backup during the commit phase. A new state, BOND_LINK_FAIL, has been introduced for slaves in the context of the ARP monitor. This allows administrators to see how slaves are rotated for sending ARP requests and attempts are made to find a new active slave. Fixes: b2220ca ("bonding: refactor ARP active-backup monitor") Signed-off-by: Jiri Wiesner <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent eabe861 commit 0410d07

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,9 @@ static int bond_ab_arp_inspect(struct bonding *bond)
29482948
if (bond_time_in_interval(bond, last_rx, 1)) {
29492949
bond_propose_link_state(slave, BOND_LINK_UP);
29502950
commit++;
2951+
} else if (slave->link == BOND_LINK_BACK) {
2952+
bond_propose_link_state(slave, BOND_LINK_FAIL);
2953+
commit++;
29512954
}
29522955
continue;
29532956
}
@@ -3056,6 +3059,19 @@ static void bond_ab_arp_commit(struct bonding *bond)
30563059

30573060
continue;
30583061

3062+
case BOND_LINK_FAIL:
3063+
bond_set_slave_link_state(slave, BOND_LINK_FAIL,
3064+
BOND_SLAVE_NOTIFY_NOW);
3065+
bond_set_slave_inactive_flags(slave,
3066+
BOND_SLAVE_NOTIFY_NOW);
3067+
3068+
/* A slave has just been enslaved and has become
3069+
* the current active slave.
3070+
*/
3071+
if (rtnl_dereference(bond->curr_active_slave))
3072+
RCU_INIT_POINTER(bond->current_arp_slave, NULL);
3073+
continue;
3074+
30593075
default:
30603076
slave_err(bond->dev, slave->dev,
30613077
"impossible: link_new_state %d on slave\n",
@@ -3106,8 +3122,6 @@ static bool bond_ab_arp_probe(struct bonding *bond)
31063122
return should_notify_rtnl;
31073123
}
31083124

3109-
bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER);
3110-
31113125
bond_for_each_slave_rcu(bond, slave, iter) {
31123126
if (!found && !before && bond_slave_is_up(slave))
31133127
before = slave;

0 commit comments

Comments
 (0)