nl80211: Fix scan request and its related events handling with MLO
Currently, whenever a scan is started, it uses drv's first BSS only whether it is AP or STA interface. However, with AP MLD related changes, the same drv could be used by other BSSs as well which needs scanning. Hence, the current logic will not work since scan needs to be handled on a non-first BSS as well. Move the logic of always using drv's first BSS during scan events to using BSS on which the event arrived. Also, for AP MLD operation, even though the BSS is same, the link BSS also needs to be identified. Hence, add a back pointer in the BSS struct which would be used to point to the link BSS which requested the scan on that BSS. This will help in routing the scan events to an appropriate BSS ctx. Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
This commit is contained in:
parent
23456e480e
commit
fd55dfe16e
4 changed files with 89 additions and 27 deletions
|
@ -3189,7 +3189,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_send_rfkill, drv, drv->ctx);
|
||||||
rfkill_deinit(drv->rfkill);
|
rfkill_deinit(drv->rfkill);
|
||||||
|
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
|
|
||||||
if (!drv->start_iface_up)
|
if (!drv->start_iface_up)
|
||||||
(void) i802_set_iface_flags(bss, 0);
|
(void) i802_set_iface_flags(bss, 0);
|
||||||
|
@ -4207,6 +4207,22 @@ struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link)
|
||||||
|
{
|
||||||
|
u8 link_id;
|
||||||
|
|
||||||
|
if (link == bss->flink)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for_each_link(bss->valid_links, link_id) {
|
||||||
|
if (&bss->links[link_id] == link)
|
||||||
|
return link_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq)
|
static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq)
|
||||||
{
|
{
|
||||||
struct i802_link *link = nl80211_get_link(bss, link_id);
|
struct i802_link *link = nl80211_get_link(bss, link_id);
|
||||||
|
@ -10252,6 +10268,8 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
|
||||||
int err;
|
int err;
|
||||||
union wpa_event_data data;
|
union wpa_event_data data;
|
||||||
struct survey_results *survey_results;
|
struct survey_results *survey_results;
|
||||||
|
void *ctx = (bss->scan_link && bss->scan_link->ctx) ?
|
||||||
|
bss->scan_link->ctx : bss->ctx;
|
||||||
|
|
||||||
os_memset(&data, 0, sizeof(data));
|
os_memset(&data, 0, sizeof(data));
|
||||||
survey_results = &data.survey_results;
|
survey_results = &data.survey_results;
|
||||||
|
@ -10274,7 +10292,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq)
|
||||||
if (err)
|
if (err)
|
||||||
wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
|
wpa_printf(MSG_ERROR, "nl80211: Failed to process survey data");
|
||||||
else
|
else
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SURVEY, &data);
|
wpa_supplicant_event(ctx, EVENT_SURVEY, &data);
|
||||||
|
|
||||||
clean_survey_results(survey_results);
|
clean_survey_results(survey_results);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct i802_bss {
|
||||||
|
|
||||||
u16 valid_links;
|
u16 valid_links;
|
||||||
struct i802_link links[MAX_NUM_MLD_LINKS];
|
struct i802_link links[MAX_NUM_MLD_LINKS];
|
||||||
struct i802_link *flink;
|
struct i802_link *flink, *scan_link;
|
||||||
|
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int br_ifindex;
|
int br_ifindex;
|
||||||
|
@ -352,6 +352,7 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode);
|
||||||
|
|
||||||
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
void nl80211_restore_ap_mode(struct i802_bss *bss);
|
||||||
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id);
|
||||||
|
u8 nl80211_get_link_id_from_link(struct i802_bss *bss, struct i802_link *link);
|
||||||
|
|
||||||
static inline bool nl80211_link_valid(u16 links, s8 link_id)
|
static inline bool nl80211_link_valid(u16 links, s8 link_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1965,9 +1965,10 @@ static void mlme_event_dh_event(struct wpa_driver_nl80211_data *drv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
static void send_scan_event(struct i802_bss *bss, int aborted,
|
||||||
struct nlattr *tb[], int external_scan)
|
struct nlattr *tb[], int external_scan)
|
||||||
{
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
union wpa_event_data event;
|
union wpa_event_data event;
|
||||||
struct nlattr *nl;
|
struct nlattr *nl;
|
||||||
int rem;
|
int rem;
|
||||||
|
@ -1975,6 +1976,8 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
||||||
#define MAX_REPORT_FREQS 110
|
#define MAX_REPORT_FREQS 110
|
||||||
int freqs[MAX_REPORT_FREQS];
|
int freqs[MAX_REPORT_FREQS];
|
||||||
int num_freqs = 0;
|
int num_freqs = 0;
|
||||||
|
struct i802_link *mld_link;
|
||||||
|
void *ctx = bss->ctx;
|
||||||
|
|
||||||
if (!external_scan && drv->scan_for_auth) {
|
if (!external_scan && drv->scan_for_auth) {
|
||||||
drv->scan_for_auth = 0;
|
drv->scan_for_auth = 0;
|
||||||
|
@ -2038,7 +2041,24 @@ static void send_scan_event(struct wpa_driver_nl80211_data *drv, int aborted,
|
||||||
ETH_ALEN);
|
ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event);
|
/* Need to pass to the correct link ctx during AP MLD operation */
|
||||||
|
if (is_ap_interface(drv->nlmode)) {
|
||||||
|
mld_link = bss->scan_link;
|
||||||
|
if (!mld_link) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan event on unknown link");
|
||||||
|
} else if (mld_link->ctx) {
|
||||||
|
u8 link_id = nl80211_get_link_id_from_link(bss,
|
||||||
|
mld_link);
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"nl80211: Scan event for link_id %d",
|
||||||
|
link_id);
|
||||||
|
ctx = mld_link->ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, &event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3055,7 +3075,7 @@ static void qca_nl80211_scan_done_event(struct wpa_driver_nl80211_data *drv,
|
||||||
drv->scan_state = SCAN_ABORTED;
|
drv->scan_state = SCAN_ABORTED;
|
||||||
|
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv,
|
||||||
drv->ctx);
|
drv->first_bss->ctx);
|
||||||
drv->vendor_scan_cookie = 0;
|
drv->vendor_scan_cookie = 0;
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
}
|
}
|
||||||
|
@ -3894,7 +3914,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case NL80211_CMD_TRIGGER_SCAN:
|
case NL80211_CMD_TRIGGER_SCAN:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan trigger");
|
||||||
drv->scan_state = SCAN_STARTED;
|
drv->scan_state = SCAN_STARTED;
|
||||||
if (drv->scan_for_auth) {
|
if (drv->scan_for_auth) {
|
||||||
/*
|
/*
|
||||||
|
@ -3906,40 +3926,40 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
|
wpa_printf(MSG_DEBUG, "nl80211: Do not indicate scan-start event due to internal scan_for_auth");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCAN_STARTED, NULL);
|
wpa_supplicant_event(bss->ctx, EVENT_SCAN_STARTED, NULL);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_START_SCHED_SCAN:
|
case NL80211_CMD_START_SCHED_SCAN:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan started");
|
||||||
drv->scan_state = SCHED_SCAN_STARTED;
|
drv->scan_state = SCHED_SCAN_STARTED;
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCHED_SCAN_STOPPED:
|
case NL80211_CMD_SCHED_SCAN_STOPPED:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Sched scan stopped");
|
||||||
drv->scan_state = SCHED_SCAN_STOPPED;
|
drv->scan_state = SCHED_SCAN_STOPPED;
|
||||||
wpa_supplicant_event(drv->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
wpa_supplicant_event(bss->ctx, EVENT_SCHED_SCAN_STOPPED, NULL);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_NEW_SCAN_RESULTS:
|
case NL80211_CMD_NEW_SCAN_RESULTS:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
"nl80211: New scan results available");
|
"nl80211: New scan results available");
|
||||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||||
drv->scan_state = SCAN_COMPLETED;
|
drv->scan_state = SCAN_COMPLETED;
|
||||||
drv->scan_complete_events = 1;
|
drv->scan_complete_events = 1;
|
||||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
} else {
|
} else {
|
||||||
external_scan_event = 1;
|
external_scan_event = 1;
|
||||||
}
|
}
|
||||||
send_scan_event(drv, 0, tb, external_scan_event);
|
send_scan_event(bss, 0, tb, external_scan_event);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCHED_SCAN_RESULTS:
|
case NL80211_CMD_SCHED_SCAN_RESULTS:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG,
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
"nl80211: New sched scan results available");
|
"nl80211: New sched scan results available");
|
||||||
drv->scan_state = SCHED_SCAN_RESULTS;
|
drv->scan_state = SCHED_SCAN_RESULTS;
|
||||||
send_scan_event(drv, 0, tb, 0);
|
send_scan_event(bss, 0, tb, 0);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_SCAN_ABORTED:
|
case NL80211_CMD_SCAN_ABORTED:
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: Scan aborted");
|
||||||
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
if (drv->last_scan_cmd != NL80211_CMD_VENDOR)
|
||||||
drv->scan_state = SCAN_ABORTED;
|
drv->scan_state = SCAN_ABORTED;
|
||||||
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
if (drv->last_scan_cmd == NL80211_CMD_TRIGGER_SCAN) {
|
||||||
|
@ -3948,12 +3968,12 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
|
||||||
* order not to make wpa_supplicant stop its scanning.
|
* order not to make wpa_supplicant stop its scanning.
|
||||||
*/
|
*/
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = 0;
|
drv->last_scan_cmd = 0;
|
||||||
} else {
|
} else {
|
||||||
external_scan_event = 1;
|
external_scan_event = 1;
|
||||||
}
|
}
|
||||||
send_scan_event(drv, 1, tb, external_scan_event);
|
send_scan_event(bss, 1, tb, external_scan_event);
|
||||||
break;
|
break;
|
||||||
case NL80211_CMD_AUTHENTICATE:
|
case NL80211_CMD_AUTHENTICATE:
|
||||||
case NL80211_CMD_ASSOCIATE:
|
case NL80211_CMD_ASSOCIATE:
|
||||||
|
|
|
@ -153,6 +153,7 @@ fail:
|
||||||
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
struct wpa_driver_nl80211_data *drv = eloop_ctx;
|
||||||
|
struct i802_bss *bss;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
|
wpa_printf(MSG_DEBUG, "nl80211: Scan timeout - try to abort it");
|
||||||
#ifdef CONFIG_DRIVER_NL80211_QCA
|
#ifdef CONFIG_DRIVER_NL80211_QCA
|
||||||
|
@ -160,14 +161,27 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
|
nl80211_abort_vendor_scan(drv, drv->vendor_scan_cookie) == 0)
|
||||||
return;
|
return;
|
||||||
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
#endif /* CONFIG_DRIVER_NL80211_QCA */
|
||||||
if (!drv->vendor_scan_cookie &&
|
|
||||||
nl80211_abort_scan(drv->first_bss) == 0)
|
for (bss = drv->first_bss; bss; bss = bss->next) {
|
||||||
|
if (bss->scan_link)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bss) {
|
||||||
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to find scan BSS");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drv->vendor_scan_cookie &&
|
||||||
|
nl80211_abort_scan(bss) == 0) {
|
||||||
|
bss->scan_link = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan");
|
||||||
|
|
||||||
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED)
|
||||||
nl80211_restore_ap_mode(drv->first_bss);
|
nl80211_restore_ap_mode(bss);
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results");
|
||||||
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
||||||
|
@ -347,7 +361,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||||
int ret = -1, timeout;
|
int ret = -1, timeout;
|
||||||
struct nl_msg *msg = NULL;
|
struct nl_msg *msg = NULL;
|
||||||
|
|
||||||
wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: scan request");
|
wpa_dbg(bss->ctx, MSG_DEBUG, "nl80211: scan request");
|
||||||
drv->scan_for_auth = 0;
|
drv->scan_for_auth = 0;
|
||||||
|
|
||||||
if (TEST_FAIL())
|
if (TEST_FAIL())
|
||||||
|
@ -435,11 +449,20 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss,
|
||||||
}
|
}
|
||||||
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
|
wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
|
||||||
"seconds", ret, timeout);
|
"seconds", ret, timeout);
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
|
eloop_register_timeout(timeout, 0, wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
|
drv->last_scan_cmd = NL80211_CMD_TRIGGER_SCAN;
|
||||||
|
|
||||||
|
bss->scan_link = bss->flink;
|
||||||
|
if (is_ap_interface(drv->nlmode) &&
|
||||||
|
nl80211_link_valid(bss->valid_links, params->link_id)) {
|
||||||
|
wpa_dbg(bss->ctx, MSG_DEBUG,
|
||||||
|
"nl80211: Scan requested for link %d",
|
||||||
|
params->link_id);
|
||||||
|
bss->scan_link = nl80211_get_link(bss, params->link_id);
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
nlmsg_free(msg);
|
nlmsg_free(msg);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1294,9 +1317,9 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss,
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
|
"nl80211: Vendor scan requested (ret=%d) - scan timeout 30 seconds, scan cookie:0x%llx",
|
||||||
ret, (long long unsigned int) cookie);
|
ret, (long long unsigned int) cookie);
|
||||||
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, drv->ctx);
|
eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, drv, bss->ctx);
|
||||||
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
|
eloop_register_timeout(30, 0, wpa_driver_nl80211_scan_timeout,
|
||||||
drv, drv->ctx);
|
drv, bss->ctx);
|
||||||
drv->last_scan_cmd = NL80211_CMD_VENDOR;
|
drv->last_scan_cmd = NL80211_CMD_VENDOR;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
Loading…
Reference in a new issue