network: register already enslaved interfaces when their master appears (#43557)
When networkd starts or restarts, links are enumerated in ifindex order. A slave enumerated before its master cannot register itself in link_append_to_master(), as the master Link object does not exist yet. The master then wrongly believes it has no slaves until the next RTM_NEWLINK message for the slave arrives. The stale slaves set affects operational state propagation (degraded-carrier detection) and any code that inspects the slaves of a master. For instance, on restart, when networkd thinks that the master has no slaves yet, we try to set the bond fail-over policy, which the kernel then refuses because in reality the bond does have slaves. To fix the issue, this updates the list of slaves after enumeration. Co-authored-by: Yu Watanabe <watanabe.yu+github@gmail.com>
This commit is contained in:
@@ -1035,7 +1035,7 @@ static void link_free_bound_by_list(Link *link) {
|
||||
link_dirty(link);
|
||||
}
|
||||
|
||||
static int link_append_to_master(Link *link) {
|
||||
int link_append_to_master(Link *link) {
|
||||
Link *master;
|
||||
int r;
|
||||
|
||||
|
||||
@@ -222,6 +222,7 @@ int link_get_master(Link *link, Link **ret);
|
||||
int link_getlink_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
|
||||
int link_call_getlink(Link *link, link_netlink_message_handler_t callback);
|
||||
int link_handle_bound_to_list(Link *link);
|
||||
int link_append_to_master(Link *link);
|
||||
|
||||
void link_enter_failed(Link *link);
|
||||
void link_set_state(Link *link, LinkState state);
|
||||
|
||||
@@ -939,7 +939,18 @@ static int manager_enumerate_links(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
|
||||
r = manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Slave interfaces enumerated before the master could not register themselves, as the master Link
|
||||
* object did not exist yet at that time. Register them now, so that the slaves set correctly
|
||||
* reflects the kernel state. */
|
||||
Link *link;
|
||||
HASHMAP_FOREACH(link, m->links_by_index)
|
||||
RET_GATHER(r, link_append_to_master(link));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int manager_enumerate_qdisc(Manager *m) {
|
||||
|
||||
Reference in New Issue
Block a user