link fix
This commit is contained in:
@@ -552,58 +552,87 @@ class BridgeLinkStateWatcher:
|
|||||||
if source_profile is None or target_profile is None or source_profile == target_profile:
|
if source_profile is None or target_profile is None or source_profile == target_profile:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
cmd = [_ETHTOOL_BIN, "-s", target_ifname]
|
|
||||||
change_summary: Optional[str] = None
|
change_summary: Optional[str] = None
|
||||||
|
commands: list[tuple[list[str], str]] = []
|
||||||
if source_profile.autoneg is True:
|
if source_profile.autoneg is True:
|
||||||
if source_profile.speed_mbps is not None and source_profile.duplex is not None:
|
if source_profile.speed_mbps is not None and source_profile.duplex is not None:
|
||||||
# A remote peer can pull this port down to a lower negotiated speed while autoneg
|
# A remote peer can pull this port down to a lower negotiated speed while autoneg
|
||||||
# stays enabled locally. Mirror that effective mode while keeping autoneg enabled
|
# stays enabled locally. Mirror that effective mode while keeping autoneg enabled
|
||||||
# on the sibling so its far-end peer can still negotiate successfully.
|
# on the sibling so its far-end peer can still negotiate successfully.
|
||||||
cmd.extend(
|
commands.append(
|
||||||
|
(
|
||||||
|
[
|
||||||
|
_ETHTOOL_BIN,
|
||||||
|
"-s",
|
||||||
|
target_ifname,
|
||||||
|
"speed",
|
||||||
|
str(source_profile.speed_mbps),
|
||||||
|
"duplex",
|
||||||
|
source_profile.duplex,
|
||||||
|
"autoneg",
|
||||||
|
"on",
|
||||||
|
],
|
||||||
|
(
|
||||||
|
f"{target_ifname} link={source_profile.speed_mbps}Mb/"
|
||||||
|
f"{source_profile.duplex}/autoneg-on"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
commands.append(([_ETHTOOL_BIN, "-s", target_ifname, "autoneg", "on"], f"{target_ifname} link=autoneg-on"))
|
||||||
|
elif source_profile.autoneg is False and source_profile.speed_mbps is not None and source_profile.duplex is not None:
|
||||||
|
# Do not force autoneg off on sibling ports. The far-end peer on that segment may
|
||||||
|
# still rely on autoneg, and forcing a fixed mode here can leave the link down.
|
||||||
|
commands.append(
|
||||||
|
(
|
||||||
[
|
[
|
||||||
|
_ETHTOOL_BIN,
|
||||||
|
"-s",
|
||||||
|
target_ifname,
|
||||||
"speed",
|
"speed",
|
||||||
str(source_profile.speed_mbps),
|
str(source_profile.speed_mbps),
|
||||||
"duplex",
|
"duplex",
|
||||||
source_profile.duplex,
|
source_profile.duplex,
|
||||||
"autoneg",
|
"autoneg",
|
||||||
"on",
|
"on",
|
||||||
]
|
],
|
||||||
|
(
|
||||||
|
f"{target_ifname} link={source_profile.speed_mbps}Mb/"
|
||||||
|
f"{source_profile.duplex}/autoneg-on-safe"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
change_summary = (
|
|
||||||
f"{target_ifname} link={source_profile.speed_mbps}Mb/"
|
|
||||||
f"{source_profile.duplex}/autoneg-on"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cmd.extend(["autoneg", "on"])
|
|
||||||
change_summary = f"{target_ifname} link=autoneg-on"
|
|
||||||
elif source_profile.autoneg is False and source_profile.speed_mbps is not None and source_profile.duplex is not None:
|
|
||||||
cmd.extend(
|
|
||||||
[
|
|
||||||
"speed",
|
|
||||||
str(source_profile.speed_mbps),
|
|
||||||
"duplex",
|
|
||||||
source_profile.duplex,
|
|
||||||
"autoneg",
|
|
||||||
"off",
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
change_summary = (
|
commands.append(
|
||||||
f"{target_ifname} link={source_profile.speed_mbps}Mb/"
|
(
|
||||||
f"{source_profile.duplex}/autoneg-off"
|
[_ETHTOOL_BIN, "-s", target_ifname, "autoneg", "on"],
|
||||||
|
f"{target_ifname} link=autoneg-on-safe",
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
last_error: Optional[Exception] = None
|
||||||
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
for cmd, summary in commands:
|
||||||
except (FileNotFoundError, subprocess.CalledProcessError) as exc:
|
try:
|
||||||
logger.debug(
|
subprocess.run(cmd, capture_output=True, text=True, check=True)
|
||||||
"Failed to synchronize ethtool profile from %s to %s on bridge=%s: %s",
|
change_summary = summary
|
||||||
source_ifname,
|
break
|
||||||
target_ifname,
|
except (FileNotFoundError, subprocess.CalledProcessError) as exc:
|
||||||
self.bridge_name,
|
last_error = exc
|
||||||
exc,
|
logger.debug(
|
||||||
)
|
"Failed to synchronize ethtool profile from %s to %s on bridge=%s with %s: %s",
|
||||||
|
source_ifname,
|
||||||
|
target_ifname,
|
||||||
|
self.bridge_name,
|
||||||
|
cmd,
|
||||||
|
exc,
|
||||||
|
)
|
||||||
|
|
||||||
|
if change_summary is None:
|
||||||
|
if last_error is not None:
|
||||||
|
self._set_last_action(
|
||||||
|
f"failed to sync link profile from {source_ifname} to {target_ifname}: {last_error}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
self._mark_managed_change(target_ifname)
|
self._mark_managed_change(target_ifname)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DeleteOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, RedoOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@@ -242,7 +242,12 @@ export default function Network() {
|
|||||||
okText="Reset"
|
okText="Reset"
|
||||||
cancelText="Cancel"
|
cancelText="Cancel"
|
||||||
>
|
>
|
||||||
<Button loading={resetBusyInterface === record.name}>Reset defaults</Button>
|
<Button
|
||||||
|
icon={<RedoOutlined />}
|
||||||
|
loading={resetBusyInterface === record.name}
|
||||||
|
aria-label={`Reset ${record.name} to defaults`}
|
||||||
|
title={`Reset ${record.name} to defaults`}
|
||||||
|
/>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user