From 79dd04c13ab4f4058abe35353017cce766680b50 Mon Sep 17 00:00:00 2001 From: James Prestwood Date: Mon, 13 May 2019 12:07:43 -0700 Subject: [PATCH] test-runner: in native HW mode, check for AP capabilities The test should be aborted if there are not enough radios that support AP mode. The iftype attribute will now be parsed during the wiphy dump and a flag is set on the wiphy so we know to skip this radio when creating the hostapd instances. Since hostapd gets started first, it will automatically choose all the radios it needs which support AP mode. This leaves the remainder of the radios (potentially STA only) for IWD. --- tools/test-runner.c | 93 +++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/tools/test-runner.c b/tools/test-runner.c index 91ede14b..e41ac958 100644 --- a/tools/test-runner.c +++ b/tools/test-runner.c @@ -159,6 +159,7 @@ struct wiphy { char *interface_name; char *hostapd_ctrl_interface; char *hostapd_config; + bool can_ap; }; static bool check_verbosity(const char *app) @@ -1186,6 +1187,7 @@ static bool configure_hw_radios(struct l_settings *hw_settings, configure: wiphy->id = create_hwsim_radio(wiphy->name, channels, p2p_device, use_chanctx); + wiphy->can_ap = true; if (wiphy->id < 0) { l_free(wiphy); @@ -1313,6 +1315,9 @@ static bool configure_hostapd_instances(struct l_settings *hw_settings, goto done; } + if (!wiphy->can_ap) + continue; + wiphys[i] = wiphy; break; } @@ -2315,54 +2320,76 @@ static struct wiphy *wiphy_find(int wiphy_id) return l_queue_find(wiphy_list, wiphy_match, L_INT_TO_PTR(wiphy_id)); } +static void parse_supported_iftypes(uint16_t *iftypes, + struct l_genl_attr *attr) +{ + uint16_t type, len; + const void *data; + + while (l_genl_attr_next(attr, &type, &len, &data)) { + /* + * NL80211_IFTYPE_UNSPECIFIED can be ignored, so we start + * at the first bit + */ + if (type > sizeof(uint16_t) * 8) { + l_warn("unsupported iftype: %u", type); + continue; + } + + *iftypes |= 1 << (type - 1); + } +} + static void wiphy_dump_callback(struct l_genl_msg *msg, void *user_data) { struct wiphy *wiphy; struct l_genl_attr attr; - uint32_t id; + struct l_genl_attr nested; + uint32_t id = UINT32_MAX; uint16_t type, len; const void *data; - const char *name; - uint32_t name_len; + const char *name = NULL; + uint32_t name_len = 0; + uint16_t iftypes = 0; if (!l_genl_attr_init(&attr, msg)) return; - /* - * The wiphy attribute, name and generation are always the first - * three attributes (in that order) in every NEW_WIPHY & DEL_WIPHY - * message. If not, then error out with a warning and ignore the - * whole message. - */ - if (!l_genl_attr_next(&attr, &type, &len, &data)) + while (l_genl_attr_next(&attr, &type, &len, &data)) { + switch (type) { + case NL80211_ATTR_WIPHY: + if (len != sizeof(uint32_t)) + return; + + id = *((uint32_t *) data); + + if (wiphy_find(id)) + return; + + break; + case NL80211_ATTR_WIPHY_NAME: + if (len > sizeof(((struct wiphy *) 0)->name)) + return; + + name = data; + name_len = len; + + break; + case NL80211_ATTR_SUPPORTED_IFTYPES: + if (l_genl_attr_recurse(&attr, &nested)) + parse_supported_iftypes(&iftypes, &nested); + + break; + } + } + + if (id == UINT32_MAX || !name) return; - if (type != NL80211_ATTR_WIPHY) - return; - - if (len != sizeof(uint32_t)) - return; - - id = *((uint32_t *) data); - - if (wiphy_find(id)) - return; - - if (!l_genl_attr_next(&attr, &type, &len, &data)) - return; - - if (type != NL80211_ATTR_WIPHY_NAME) - return; - - if (len > sizeof(((struct wiphy *) 0)->name)) - return; - - name = data; - name_len = len; - wiphy = l_new(struct wiphy, 1); strncpy(wiphy->name, name, name_len); wiphy->id = id; + wiphy->can_ap = iftypes & (1 << NL80211_IFTYPE_AP); l_queue_push_tail(wiphy_list, wiphy); }