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.
This commit is contained in:
James Prestwood 2019-05-13 12:07:43 -07:00 committed by Denis Kenzior
parent 7c7aafa812
commit 79dd04c13a
1 changed files with 60 additions and 33 deletions

View File

@ -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);
}