diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 95a7d75e53..e43c04567a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2515,6 +2515,15 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { log_link_debug(link, "Saved new link: ifindex=%i, iftype=%s(%u), kind=%s", link->ifindex, strna(arphrd_to_name(link->iftype)), link->iftype, strna(link->kind)); + /* If contained in this set, the link is wireless and the corresponding NL80211_CMD_NEW_INTERFACE + * message arrived too early. Request the wireless link information again. + */ + if (set_remove(manager->new_wlan_ifindices, INT_TO_PTR(link->ifindex))) { + r = link_get_wlan_interface(link); + if (r < 0) + log_link_warning_errno(link, r, "Failed to get wireless interface, ignoring: %m"); + } + *ret = TAKE_PTR(link); return 0; } diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index f82117cc1e..ad668215e7 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -614,6 +614,7 @@ Manager* manager_free(Manager *m) { m->request_queue = ordered_set_free(m->request_queue); m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref); + m->new_wlan_ifindices = set_free(m->new_wlan_ifindices); m->links_by_name = hashmap_free(m->links_by_name); m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr); m->links_by_dhcp_pd_subnet_prefix = hashmap_free(m->links_by_dhcp_pd_subnet_prefix); diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h index e6183af0e4..c9cbcf9289 100644 --- a/src/network/networkd-manager.h +++ b/src/network/networkd-manager.h @@ -38,6 +38,7 @@ struct Manager { bool manage_foreign_rules; Set *dirty_links; + Set *new_wlan_ifindices; char *state_file; LinkOperationalState operational_state; diff --git a/src/network/networkd-wifi.c b/src/network/networkd-wifi.c index e35857261e..1a3754b29c 100644 --- a/src/network/networkd-wifi.c +++ b/src/network/networkd-wifi.c @@ -92,6 +92,19 @@ int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *me if (r < 0) { log_debug_errno(r, "nl80211: received %s(%u) message for link '%"PRIu32"' we don't know about, ignoring.", strna(nl80211_cmd_to_string(cmd)), cmd, ifindex); + + /* The NL80211_CMD_NEW_INTERFACE message might arrive before RTM_NEWLINK, in which case a + * link will not have been created yet. Store the interface index such that the wireless + * properties of the link (such as wireless interface type) are queried again after the link + * is created. + */ + if (cmd == NL80211_CMD_NEW_INTERFACE) { + r = set_ensure_put(&manager->new_wlan_ifindices, NULL, INT_TO_PTR(ifindex)); + if (r < 0) + log_warning_errno(r, "Failed to add new wireless interface index to set, ignoring: %m"); + } else if (cmd == NL80211_CMD_DEL_INTERFACE) + set_remove(manager->new_wlan_ifindices, INT_TO_PTR(ifindex)); + return 0; }