]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: split operational states into carrier and address states
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 15 Jun 2019 23:58:39 +0000 (08:58 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 16 Jun 2019 14:17:23 +0000 (23:17 +0900)
This should not change any behavior. The new states will be exposed by
later commits.

src/libsystemd/sd-network/network-util.h
src/network/networkd-link.c
src/network/networkd-link.h

index 6936fd536b9287d6e79d6ec7034fcffd993448b5..601d00146a4d551c90526a0d012187dd951d8d27 100644 (file)
@@ -20,5 +20,24 @@ typedef enum LinkOperationalState {
         _LINK_OPERSTATE_INVALID = -1
 } LinkOperationalState;
 
+typedef enum LinkCarrierState {
+        LINK_CARRIER_STATE_OFF              = LINK_OPERSTATE_OFF,
+        LINK_CARRIER_STATE_NO_CARRIER       = LINK_OPERSTATE_NO_CARRIER,
+        LINK_CARRIER_STATE_DORMANT          = LINK_OPERSTATE_DORMANT,
+        LINK_CARRIER_STATE_DEGRADED_CARRIER = LINK_OPERSTATE_DEGRADED_CARRIER,
+        LINK_CARRIER_STATE_CARRIER          = LINK_OPERSTATE_CARRIER,
+        LINK_CARRIER_STATE_ENSLAVED         = LINK_OPERSTATE_ENSLAVED,
+        _LINK_CARRIER_STATE_MAX,
+        _LINK_CARRIER_STATE_INVALID = -1
+} LinkCarrierState;
+
+typedef enum LinkAddressState {
+        LINK_ADDRESS_STATE_OFF,
+        LINK_ADDRESS_STATE_DEGRADED,
+        LINK_ADDRESS_STATE_ROUTABLE,
+        _LINK_ADDRESS_STATE_MAX,
+        _LINK_ADDRESS_STATE_INVALID = -1
+} LinkAddressState;
+
 const char* link_operstate_to_string(LinkOperationalState s) _const_;
 LinkOperationalState link_operstate_from_string(const char *s) _pure_;
index 56e36b7d6b5eba6aac1ed4b069a1cf14caa6667c..46ebc2b597104e713792d58f05701e079dee1450 100644 (file)
@@ -360,63 +360,85 @@ static void link_update_master_operstate(Link *link, NetDev *netdev) {
 
 void link_update_operstate(Link *link, bool also_update_master) {
         LinkOperationalState operstate;
+        LinkCarrierState carrier_state;
+        LinkAddressState address_state;
+        uint8_t scope = RT_SCOPE_NOWHERE;
+        Address *address;
         Iterator i;
 
         assert(link);
 
         if (link->kernel_operstate == IF_OPER_DORMANT)
-                operstate = LINK_OPERSTATE_DORMANT;
+                carrier_state = LINK_CARRIER_STATE_DORMANT;
         else if (link_has_carrier(link)) {
-                Address *address;
-                uint8_t scope = RT_SCOPE_NOWHERE;
-
-                /* if we have carrier, check what addresses we have */
-                SET_FOREACH(address, link->addresses, i) {
-                        if (!address_is_ready(address))
-                                continue;
-
-                        if (address->scope < scope)
-                                scope = address->scope;
-                }
-
-                /* for operstate we also take foreign addresses into account */
-                SET_FOREACH(address, link->addresses_foreign, i) {
-                        if (!address_is_ready(address))
-                                continue;
-
-                        if (address->scope < scope)
-                                scope = address->scope;
-                }
-
-                if (scope < RT_SCOPE_SITE)
-                        /* universally accessible addresses found */
-                        operstate = LINK_OPERSTATE_ROUTABLE;
-                else if (scope < RT_SCOPE_HOST)
-                        /* only link or site local addresses found */
-                        operstate = LINK_OPERSTATE_DEGRADED;
+                if (link_is_enslaved(link))
+                        carrier_state = LINK_CARRIER_STATE_ENSLAVED;
                 else
-                        /* no useful addresses found */
-                        operstate = LINK_OPERSTATE_CARRIER;
+                        carrier_state = LINK_CARRIER_STATE_CARRIER;
         } else if (link->flags & IFF_UP)
-                operstate = LINK_OPERSTATE_NO_CARRIER;
+                carrier_state = LINK_CARRIER_STATE_NO_CARRIER;
         else
-                operstate = LINK_OPERSTATE_OFF;
+                carrier_state = LINK_CARRIER_STATE_OFF;
 
-        if (IN_SET(operstate, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_CARRIER) &&
-            link_is_enslaved(link))
-                operstate = LINK_OPERSTATE_ENSLAVED;
-
-        if (operstate >= LINK_OPERSTATE_CARRIER) {
+        if (carrier_state >= LINK_CARRIER_STATE_CARRIER) {
                 Link *slave;
 
                 SET_FOREACH(slave, link->slaves, i) {
                         link_update_operstate(slave, false);
 
-                        if (slave->operstate < LINK_OPERSTATE_CARRIER)
-                                operstate = LINK_OPERSTATE_DEGRADED_CARRIER;
+                        if (slave->carrier_state < LINK_CARRIER_STATE_CARRIER)
+                                carrier_state = LINK_CARRIER_STATE_DEGRADED_CARRIER;
                 }
         }
 
+        SET_FOREACH(address, link->addresses, i) {
+                if (!address_is_ready(address))
+                        continue;
+
+                if (address->scope < scope)
+                        scope = address->scope;
+        }
+
+        /* for operstate we also take foreign addresses into account */
+        SET_FOREACH(address, link->addresses_foreign, i) {
+                if (!address_is_ready(address))
+                        continue;
+
+                if (address->scope < scope)
+                        scope = address->scope;
+        }
+
+        if (scope < RT_SCOPE_SITE)
+                /* universally accessible addresses found */
+                address_state = LINK_ADDRESS_STATE_ROUTABLE;
+        else if (scope < RT_SCOPE_HOST)
+                /* only link or site local addresses found */
+                address_state = LINK_ADDRESS_STATE_DEGRADED;
+        else
+                /* no useful addresses found */
+                address_state = LINK_ADDRESS_STATE_OFF;
+
+        /* Mapping of address and carrier state vs operational state
+         *                                                     carrier state
+         *                          | 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
+         */
+
+        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;
+        else if (carrier_state == LINK_CARRIER_STATE_CARRIER)
+                operstate = LINK_OPERSTATE_DEGRADED;
+        else
+                operstate = LINK_OPERSTATE_ENSLAVED;
+
+        link->carrier_state = carrier_state;
+        link->address_state = address_state;
+
         if (link->operstate != operstate) {
                 link->operstate = operstate;
                 link_send_changed(link, "OperationalState", NULL);
index 05b88356cfde78899b3289c2472617019ab95227..ac1532c066fc2171014fb6e9791dd10b1065c18a 100644 (file)
@@ -60,6 +60,8 @@ typedef struct Link {
 
         LinkState state;
         LinkOperationalState operstate;
+        LinkCarrierState carrier_state;
+        LinkAddressState address_state;
 
         unsigned address_messages;
         unsigned address_label_messages;