network: make degraded-carrier bond/bridge as routable (#27776)

This makes a bond or bridge interface in the degraded-carrier state but has a routable address
handled as routable operational state.

If the carrier is degraded but the address state is routable then the operational state should be
seen as routable and not degraded because that may be the case for bonds if some of the links are down,
but when that happens the bond as whole is still routable.

This also makes operational state to degraded if address state is degraded even if the link state is
degraded-carrier.

Fixes #22713.
This commit is contained in:
Henrik Holst 2023-06-15 06:32:10 +02:00 committed by GitHub
parent 4dad6101fd
commit cf4dbd84ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 15 additions and 9 deletions

View File

@ -96,8 +96,7 @@
<varlistentry>
<term>degraded-carrier</term>
<listitem>
<para>for bond or bridge master, one of the bonding or bridge slave network interfaces is
in off, no-carrier, or dormant state</para>
<para>one of the bonding or bridge slave network interfaces is in off, no-carrier, or dormant state, and the master interface has no address.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -110,7 +109,9 @@
<varlistentry>
<term>degraded</term>
<listitem>
<para>the link has carrier and addresses valid on the local link configured</para>
<para>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.</para>
</listitem>
</varlistentry>
<varlistentry>
@ -122,7 +123,8 @@
<varlistentry>
<term>routable</term>
<listitem>
<para>the link has carrier and routable address configured</para>
<para>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.</para>
</listitem>
</varlistentry>
</variablelist>

View File

@ -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;

View File

@ -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)