diff --git a/man/networkctl.xml b/man/networkctl.xml index 497d88a15f8..7d461786d75 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -96,8 +96,7 @@ degraded-carrier - for bond or bridge master, one of the bonding or bridge slave network interfaces is - in off, no-carrier, or dormant state + one of the bonding or bridge slave network interfaces is in off, no-carrier, or dormant state, and the master interface has no address. @@ -110,7 +109,9 @@ degraded - the link has carrier and addresses valid on the local link configured + the link has carrier and addresses valid on the local link configured. For bond or + bridge master this means that not all slave network interfaces have carrier but at least + one does. @@ -122,7 +123,8 @@ routable - the link has carrier and routable address configured + the link has carrier and routable address configured. For bond or bridge master it is + not necessary for all slave network interfaces to have carrier, but at least one must. diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index d16090dbcd2..62dd892afaa 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1775,11 +1775,15 @@ void link_update_operstate(Link *link, bool also_update_master) { * | off | no-carrier | dormant | degraded-carrier | carrier | enslaved * ------------------------------------------------------------------------------ * off | off | no-carrier | dormant | degraded-carrier | carrier | enslaved - * address_state degraded | off | no-carrier | dormant | degraded-carrier | degraded | enslaved - * routable | off | no-carrier | dormant | degraded-carrier | routable | routable + * address_state degraded | off | no-carrier | dormant | degraded | degraded | enslaved + * routable | off | no-carrier | dormant | routable | routable | routable */ - if (carrier_state < LINK_CARRIER_STATE_CARRIER || address_state == LINK_ADDRESS_STATE_OFF) + if (carrier_state == LINK_CARRIER_STATE_DEGRADED_CARRIER && address_state == LINK_ADDRESS_STATE_ROUTABLE) + operstate = LINK_OPERSTATE_ROUTABLE; + else if (carrier_state == LINK_CARRIER_STATE_DEGRADED_CARRIER && address_state == LINK_ADDRESS_STATE_DEGRADED) + operstate = LINK_OPERSTATE_DEGRADED; + else if (carrier_state < LINK_CARRIER_STATE_CARRIER || address_state == LINK_ADDRESS_STATE_OFF) operstate = (LinkOperationalState) carrier_state; else if (address_state == LINK_ADDRESS_STATE_ROUTABLE) operstate = LINK_OPERSTATE_ROUTABLE; diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 5658433bca8..b5ef83a9c08 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -3950,7 +3950,7 @@ class NetworkdBondTests(unittest.TestCase, Utilities): self.wait_operstate('dummy98', 'off') self.wait_operstate('test1', 'enslaved') - self.wait_operstate('bond99', 'degraded-carrier') + self.wait_operstate('bond99', 'routable') check_output('ip link set dummy98 up') @@ -4121,7 +4121,7 @@ class NetworkdBridgeTests(unittest.TestCase, Utilities): self.assertRegex(output, 'ff00::/8 table local (proto kernel )?metric 256 (linkdown )?pref medium') remove_link('test1') - self.wait_operstate('bridge99', 'degraded-carrier') + self.wait_operstate('bridge99', 'routable') output = check_output('ip -d link show bridge99') print(output)