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;
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) &&
assert(link);
assert(link->network);
+ assert(link->enslaving > 0);
+ assert(!link->enslaved_raw);
link->enslaving--;
} else
log_link_debug(link, "Joined netdev");
- if (link->enslaving <= 0)
+ if (link->enslaving == 0) {
+ link->enslaved_raw = true;
link_joined(link);
+ }
return 1;
}
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 &&
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,
link_enter_failed(link);
return r;
}
-
- link->enslaving++;
}
if (link->network->bridge) {
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,
link_enter_failed(link);
return r;
}
-
- link->enslaving++;
}
if (link->network->vrf) {
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,
link_enter_failed(link);
return r;
}
-
- link->enslaving++;
}
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
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,
link_enter_failed(link);
return r;
}
-
- link->enslaving++;
}
+ if (link->enslaving == 0)
+ return link_joined(link);
+
return 0;
}