network: split operational states into carrier and address states

This should not change any behavior. The new states will be exposed by
later commits.
This commit is contained in:
Yu Watanabe 2019-06-16 08:58:39 +09:00
parent 46606fdda9
commit 1678fbb3c5
3 changed files with 82 additions and 39 deletions

View 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_;

View 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);

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