better config sync without suppressing
This commit is contained in:
@@ -246,6 +246,13 @@ class BridgeLinkStateWatcher:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if failing_members:
|
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)
|
matured_failing_members = self._track_failing_members(failing_members, now)
|
||||||
if not matured_failing_members:
|
if not matured_failing_members:
|
||||||
self._set_last_action(
|
self._set_last_action(
|
||||||
@@ -311,6 +318,39 @@ class BridgeLinkStateWatcher:
|
|||||||
state = states.get(ifname)
|
state = states.get(ifname)
|
||||||
return state is not None and state.link_ready
|
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]:
|
def _track_failing_members(self, failing_members: list[str], now: float) -> list[str]:
|
||||||
"""Record first-seen timestamps and return failures that exceeded the holdoff."""
|
"""Record first-seen timestamps and return failures that exceeded the holdoff."""
|
||||||
with self._lock:
|
with self._lock:
|
||||||
|
|||||||
Reference in New Issue
Block a user