From 02b3ab67931b7f54ab6b3b6cbcd444407f69a536 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Tue, 16 Apr 2019 17:37:41 -0500 Subject: [PATCH] manager: Run an interface dump on startup Instead of handling NEW_WIPHY events and WIHPY_DUMP events in a similar fashion, split up the paths to optimize iwd startup time. There's fundamentally no reason to wait a second (and eat up file-descriptor resources for timers unnecessarily) when we can simply start an interface dump right after the wiphy dump. In case a new wiphy is added in the middle of a wiphy dump, we will likely get a new wiphy event anyway, in which case a setup_timeout will be created and we will ignore this phy during the interface dump processing. This also optimizes the case of iwd being re-started, in which case there are no interfaces present. --- src/manager.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/src/manager.c b/src/manager.c index 068cb4ef..2c0e481c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -578,18 +578,54 @@ static void manager_config_notify(struct l_genl_msg *msg, void *user_data) } } +static void manager_interface_dump_callback(struct l_genl_msg *msg, + void *user_data) +{ + struct wiphy_setup_state *state; + struct l_genl_attr attr; + + l_debug(""); + + if (!l_genl_attr_init(&attr, msg)) + return; + + state = manager_find_pending(manager_parse_wiphy_id(&attr)); + if (!state || state->setup_timeout) + return; + + manager_get_interface_cb(msg, state); +} + +static void manager_interface_dump_done(void *user_data) +{ + const struct l_queue_entry *entry; + + for (entry = l_queue_get_entries(pending_wiphys); + entry; entry = entry->next) { + struct wiphy_setup_state *state = entry->data; + + /* phy might have been detected after the initial dump */ + if (state->setup_timeout || state->pending_cmd_count) + continue; + + /* If we are here, then there are no interfaces for this phy */ + manager_create_interfaces(state); + } +} + static void manager_wiphy_dump_callback(struct l_genl_msg *msg, void *user_data) { l_debug(""); - manager_new_wiphy_event(msg); + manager_rx_cmd_new_wiphy(msg); } bool manager_init(struct l_genl_family *in, const char *if_whitelist, const char *if_blacklist) { struct l_genl_msg *msg; - unsigned int id; + unsigned int wiphy_dump; + unsigned int interface_dump; nl80211 = in; @@ -608,14 +644,27 @@ bool manager_init(struct l_genl_family *in, } msg = l_genl_msg_new(NL80211_CMD_GET_WIPHY); - id = l_genl_family_dump(nl80211, msg, - manager_wiphy_dump_callback, NULL, NULL); - if (!id) { + wiphy_dump = l_genl_family_dump(nl80211, msg, + manager_wiphy_dump_callback, + NULL, NULL); + if (!wiphy_dump) { l_error("Initial wiphy information dump failed"); l_genl_msg_unref(msg); return false; } + msg = l_genl_msg_new(NL80211_CMD_GET_INTERFACE); + interface_dump = l_genl_family_dump(nl80211, msg, + manager_interface_dump_callback, + NULL, + manager_interface_dump_done); + if (!interface_dump) { + l_error("Initial interface information dump failed"); + l_genl_msg_unref(msg); + l_genl_family_cancel(nl80211, wiphy_dump); + return false; + } + return true; }