diff --git a/backend/src/utilities/bridge_link_state_manager.py b/backend/src/utilities/bridge_link_state_manager.py index bf894e6..c8c1a1f 100644 --- a/backend/src/utilities/bridge_link_state_manager.py +++ b/backend/src/utilities/bridge_link_state_manager.py @@ -246,6 +246,13 @@ class BridgeLinkStateWatcher: ) if failing_members: + config_source = self._find_config_sync_source(states, preferred_ifname=source_ifname) + if config_source is not None and self._has_config_mismatch(config_source, states): + with self._lock: + self._failing_since = {} + self._sync_member_configuration(config_source, states) + return + matured_failing_members = self._track_failing_members(failing_members, now) if not matured_failing_members: self._set_last_action( @@ -311,6 +318,39 @@ class BridgeLinkStateWatcher: state = states.get(ifname) return state is not None and state.link_ready + def _find_config_sync_source( + self, + states: dict[str, MemberLinkState], + preferred_ifname: Optional[str] = None, + ) -> Optional[str]: + """Pick a healthy member whose configuration should be mirrored to siblings.""" + candidates: list[str] = [] + if preferred_ifname: + candidates.append(preferred_ifname) + candidates.extend(ifname for ifname in sorted(states) if ifname != preferred_ifname) + + for ifname in candidates: + if self._is_source_eligible(ifname, states): + return ifname + + return None + + def _has_config_mismatch(self, source_ifname: str, states: dict[str, MemberLinkState]) -> bool: + """Return whether any sibling differs from the chosen source configuration.""" + source = states.get(source_ifname) + if source is None: + return False + + for target_ifname, target in states.items(): + if target_ifname == source_ifname: + continue + if source.mtu is not None and target.mtu is not None and source.mtu != target.mtu: + return True + if source.ethernet_profile is not None and target.ethernet_profile is not None and source.ethernet_profile != target.ethernet_profile: + return True + + return False + def _track_failing_members(self, failing_members: list[str], now: float) -> list[str]: """Record first-seen timestamps and return failures that exceeded the holdoff.""" with self._lock: