mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-22 06:29:23 +01:00
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:
parent
7c7aafa812
commit
79dd04c13a
@ -159,6 +159,7 @@ struct wiphy {
|
|||||||
char *interface_name;
|
char *interface_name;
|
||||||
char *hostapd_ctrl_interface;
|
char *hostapd_ctrl_interface;
|
||||||
char *hostapd_config;
|
char *hostapd_config;
|
||||||
|
bool can_ap;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool check_verbosity(const char *app)
|
static bool check_verbosity(const char *app)
|
||||||
@ -1186,6 +1187,7 @@ static bool configure_hw_radios(struct l_settings *hw_settings,
|
|||||||
configure:
|
configure:
|
||||||
wiphy->id = create_hwsim_radio(wiphy->name, channels,
|
wiphy->id = create_hwsim_radio(wiphy->name, channels,
|
||||||
p2p_device, use_chanctx);
|
p2p_device, use_chanctx);
|
||||||
|
wiphy->can_ap = true;
|
||||||
|
|
||||||
if (wiphy->id < 0) {
|
if (wiphy->id < 0) {
|
||||||
l_free(wiphy);
|
l_free(wiphy);
|
||||||
@ -1313,6 +1315,9 @@ static bool configure_hostapd_instances(struct l_settings *hw_settings,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wiphy->can_ap)
|
||||||
|
continue;
|
||||||
|
|
||||||
wiphys[i] = wiphy;
|
wiphys[i] = wiphy;
|
||||||
break;
|
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));
|
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)
|
static void wiphy_dump_callback(struct l_genl_msg *msg, void *user_data)
|
||||||
{
|
{
|
||||||
struct wiphy *wiphy;
|
struct wiphy *wiphy;
|
||||||
struct l_genl_attr attr;
|
struct l_genl_attr attr;
|
||||||
uint32_t id;
|
struct l_genl_attr nested;
|
||||||
|
uint32_t id = UINT32_MAX;
|
||||||
uint16_t type, len;
|
uint16_t type, len;
|
||||||
const void *data;
|
const void *data;
|
||||||
const char *name;
|
const char *name = NULL;
|
||||||
uint32_t name_len;
|
uint32_t name_len = 0;
|
||||||
|
uint16_t iftypes = 0;
|
||||||
|
|
||||||
if (!l_genl_attr_init(&attr, msg))
|
if (!l_genl_attr_init(&attr, msg))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
while (l_genl_attr_next(&attr, &type, &len, &data)) {
|
||||||
* The wiphy attribute, name and generation are always the first
|
switch (type) {
|
||||||
* three attributes (in that order) in every NEW_WIPHY & DEL_WIPHY
|
case NL80211_ATTR_WIPHY:
|
||||||
* message. If not, then error out with a warning and ignore the
|
if (len != sizeof(uint32_t))
|
||||||
* whole message.
|
return;
|
||||||
*/
|
|
||||||
if (!l_genl_attr_next(&attr, &type, &len, &data))
|
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;
|
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);
|
wiphy = l_new(struct wiphy, 1);
|
||||||
strncpy(wiphy->name, name, name_len);
|
strncpy(wiphy->name, name, name_len);
|
||||||
wiphy->id = id;
|
wiphy->id = id;
|
||||||
|
wiphy->can_ap = iftypes & (1 << NL80211_IFTYPE_AP);
|
||||||
|
|
||||||
l_queue_push_tail(wiphy_list, wiphy);
|
l_queue_push_tail(wiphy_list, wiphy);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user