History

bonding: fix state transition issue in link monitoring

Since de77ecd4ef02 ("bonding: improve link-status update in mii-monitoring"), the bonding driver has utilized two separate variables to indicate the next link state a particular slave should transition to. Each is used to communicate to a different portion of the link state change commit logic; one to the bond_miimon_commit function itself, and another to the state transition logic. Unfortunately, the two variables can become unsynchronized, resulting in incorrect link state transitions within bonding. This can cause slaves to become stuck in an incorrect link state until a subsequent carrier state transition. The issue occurs when a special case in bond_slave_netdev_event sets slave->link directly to BOND_LINK_FAIL. On the next pass through bond_miimon_inspect after the slave goes carrier up, the BOND_LINK_FAIL case will set the proposed next state (link_new_state) to BOND_LINK_UP, but the new_link to BOND_LINK_DOWN. The setting of the final link state from new_link comes after that from link_new_state, and so the slave will end up incorrectly in _DOWN state. Resolve this by combining the two variables into one.

Jay Vosburgh committed 7 years ago

Commit 1899bb31 parent 41de23e2 files · +23 −24Browse files

Showing the changes to include (1 of 2 files). Show all

Unified · Split

include/net/bonding.h+1−2
@@ -159,7 +159,6 @@ struct slave { · 158 unmodified lines
159159 unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
160160 s8 link; /* one of BOND_LINK_XXXX */
161161 s8 link_new_state; /* one of BOND_LINK_XXXX */
162− s8 new_link;
163162 u8 backup:1, /* indicates backup slave. Value corresponds with
164163 BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
165164 inactive:1, /* indicates inactive slave */
@@ -549,7 +548,7 @@ static inline void bond_propose_link_state(struct slave *slave, int state) · 383 unmodified lines
549548
550549 static inline void bond_commit_link_state(struct slave *slave, bool notify)
551550 {
552− if (slave->link == slave->link_new_state)
551+ if (slave->link_new_state == BOND_LINK_NOCHANGE)
553552 return;
554553
555554 slave->link = slave->link_new_state;