From 34bf3c005148b88e953232cd6cb3db448aea5ccd Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 15 Feb 2019 12:35:30 +0900 Subject: [PATCH] network: extend 'enslaved' state to bridge slave interfaces Currently, the interface's operstate is set to 'enslaved' only when it is managed by networkd. --- src/network/networkd-link.c | 53 ++++++++++++++++++++++++++----------- src/network/networkd-link.h | 2 ++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 77f345aeda..2be5c2853a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -328,6 +328,24 @@ static int link_enable_ipv6(Link *link) { return 0; } +static bool link_is_enslaved(Link *link) { + if (link->flags & IFF_SLAVE) + /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */ + return true; + + if (!link->enslaved_raw) + return false; + + if (!link->network) + return false; + + if (link->network->bridge) + /* TODO: support the case when link is not managed by networkd. */ + return true; + + return false; +} + void link_update_operstate(Link *link, bool also_update_bond_master) { LinkOperationalState operstate; @@ -373,7 +391,7 @@ void link_update_operstate(Link *link, bool also_update_bond_master) { operstate = LINK_OPERSTATE_OFF; if (IN_SET(operstate, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_CARRIER) && - link->flags & IFF_SLAVE) + link_is_enslaved(link)) operstate = LINK_OPERSTATE_ENSLAVED; if (IN_SET(operstate, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_ENSLAVED, LINK_OPERSTATE_ROUTABLE) && @@ -2514,6 +2532,8 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li assert(link); assert(link->network); + assert(link->enslaving > 0); + assert(!link->enslaved_raw); link->enslaving--; @@ -2528,8 +2548,10 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li } else log_link_debug(link, "Joined netdev"); - if (link->enslaving <= 0) + if (link->enslaving == 0) { + link->enslaved_raw = true; link_joined(link); + } return 1; } @@ -2546,12 +2568,8 @@ static int link_enter_join_netdev(Link *link) { link_set_state(link, LINK_STATE_CONFIGURING); link_dirty(link); - - if (!link->network->bridge && - !link->network->bond && - !link->network->vrf && - hashmap_isempty(link->network->stacked_netdevs)) - return link_joined(link); + link->enslaving = 0; + link->enslaved_raw = false; if (link->network->bond) { if (link->network->bond->state == NETDEV_STATE_READY && @@ -2563,6 +2581,8 @@ static int link_enter_join_netdev(Link *link) { LOG_NETDEV_INTERFACE(link->network->bond), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname)); + link->enslaving++; + r = netdev_join(link->network->bond, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, @@ -2572,8 +2592,6 @@ static int link_enter_join_netdev(Link *link) { link_enter_failed(link); return r; } - - link->enslaving++; } if (link->network->bridge) { @@ -2582,6 +2600,8 @@ static int link_enter_join_netdev(Link *link) { LOG_NETDEV_INTERFACE(link->network->bridge), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname)); + link->enslaving++; + r = netdev_join(link->network->bridge, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, @@ -2591,8 +2611,6 @@ static int link_enter_join_netdev(Link *link) { link_enter_failed(link); return r; } - - link->enslaving++; } if (link->network->vrf) { @@ -2601,6 +2619,8 @@ static int link_enter_join_netdev(Link *link) { LOG_NETDEV_INTERFACE(link->network->vrf), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname)); + link->enslaving++; + r = netdev_join(link->network->vrf, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, @@ -2610,8 +2630,6 @@ static int link_enter_join_netdev(Link *link) { link_enter_failed(link); return r; } - - link->enslaving++; } HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { @@ -2626,6 +2644,8 @@ static int link_enter_join_netdev(Link *link) { LOG_NETDEV_INTERFACE(netdev), LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname)); + link->enslaving++; + r = netdev_join(netdev, link, netdev_join_handler); if (r < 0) { log_struct_errno(LOG_WARNING, r, @@ -2635,10 +2655,11 @@ static int link_enter_join_netdev(Link *link) { link_enter_failed(link); return r; } - - link->enslaving++; } + if (link->enslaving == 0) + return link_joined(link); + return 0; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index 37be3e3bb3..fca8c083ec 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -76,6 +76,8 @@ typedef struct Link { unsigned routing_policy_rule_messages; unsigned routing_policy_rule_remove_messages; unsigned enslaving; + /* link_is_enslaved() has additional checks. So, it is named _raw. */ + bool enslaved_raw; Set *addresses; Set *addresses_foreign;