WNM: Move transition candidate list processing to normal scan
This makes it easier to optimize transition request processing. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
279b5486a6
commit
d0b9ab69f6
4 changed files with 89 additions and 64 deletions
|
@ -1314,6 +1314,9 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wnm_scan_process(wpa_s) > 0)
|
||||||
|
goto scan_work_done;
|
||||||
|
|
||||||
if (sme_proc_obss_scan(wpa_s) > 0)
|
if (sme_proc_obss_scan(wpa_s) > 0)
|
||||||
goto scan_work_done;
|
goto scan_work_done;
|
||||||
|
|
||||||
|
|
|
@ -445,41 +445,32 @@ static void wnm_parse_neighbor_report(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
|
static struct wpa_bss *
|
||||||
struct wpa_scan_results *scan_res,
|
compare_scan_neighbor_results(struct wpa_supplicant *wpa_s)
|
||||||
struct neighbor_report *neigh_rep,
|
|
||||||
u8 num_neigh_rep, u8 *bssid_to_connect)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
u8 i, j;
|
u8 i;
|
||||||
const u8 *ssid;
|
|
||||||
struct wpa_bss *bss = wpa_s->current_bss;
|
struct wpa_bss *bss = wpa_s->current_bss;
|
||||||
|
struct wpa_bss *target;
|
||||||
|
|
||||||
if (scan_res == NULL || num_neigh_rep == 0 || !bss)
|
if (!bss)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
|
wpa_printf(MSG_DEBUG, "WNM: Current BSS " MACSTR " RSSI %d",
|
||||||
MAC2STR(wpa_s->bssid), bss->level);
|
MAC2STR(wpa_s->bssid), bss->level);
|
||||||
|
|
||||||
for (i = 0; i < num_neigh_rep; i++) {
|
for (i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
|
||||||
struct neighbor_report *nei = &neigh_rep[i];
|
struct neighbor_report *nei;
|
||||||
struct wpa_scan_res *res = NULL;
|
|
||||||
|
|
||||||
|
nei = &wpa_s->wnm_neighbor_report_elements[i];
|
||||||
if (nei->preference_present && nei->preference == 0) {
|
if (nei->preference_present && nei->preference == 0) {
|
||||||
wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR,
|
wpa_printf(MSG_DEBUG, "Skip excluded BSS " MACSTR,
|
||||||
MAC2STR(nei->bssid));
|
MAC2STR(nei->bssid));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < scan_res->num; j++) {
|
target = wpa_bss_get_bssid(wpa_s, nei->bssid);
|
||||||
if (os_memcmp(scan_res->res[j]->bssid,
|
if (!target) {
|
||||||
neigh_rep[i].bssid, ETH_ALEN) == 0) {
|
|
||||||
res = scan_res->res[j];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
" (pref %d) not found in scan results",
|
" (pref %d) not found in scan results",
|
||||||
MAC2STR(nei->bssid),
|
MAC2STR(nei->bssid),
|
||||||
|
@ -488,9 +479,8 @@ static int compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
|
if (bss->ssid_len != target->ssid_len ||
|
||||||
if (ssid == NULL || bss->ssid_len != ssid[1] ||
|
os_memcmp(bss->ssid, target->ssid, bss->ssid_len) != 0) {
|
||||||
os_memcmp(bss->ssid, ssid + 2, ssid[1]) != 0) {
|
|
||||||
/*
|
/*
|
||||||
* TODO: Could consider allowing transition to another
|
* TODO: Could consider allowing transition to another
|
||||||
* ESS if PMF was enabled for the association.
|
* ESS if PMF was enabled for the association.
|
||||||
|
@ -503,25 +493,24 @@ static int compare_scan_neighbor_results(struct wpa_supplicant *wpa_s,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res->level < bss->level && res->level < -80) {
|
if (target->level < bss->level && target->level < -80) {
|
||||||
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
wpa_printf(MSG_DEBUG, "Candidate BSS " MACSTR
|
||||||
" (pref %d) does not have sufficient signal level (%d)",
|
" (pref %d) does not have sufficient signal level (%d)",
|
||||||
MAC2STR(nei->bssid),
|
MAC2STR(nei->bssid),
|
||||||
nei->preference_present ? nei->preference :
|
nei->preference_present ? nei->preference :
|
||||||
-1,
|
-1,
|
||||||
res->level);
|
target->level);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG,
|
wpa_printf(MSG_DEBUG,
|
||||||
"WNM: Found an acceptable prefed transition candidate BSS "
|
"WNM: Found an acceptable preferred transition candidate BSS "
|
||||||
MACSTR " (RSSI %d)",
|
MACSTR " (RSSI %d)",
|
||||||
MAC2STR(nei->bssid), res->level);
|
MAC2STR(nei->bssid), target->level);
|
||||||
os_memcpy(bssid_to_connect, nei->bssid, ETH_ALEN);
|
return target;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -537,6 +526,11 @@ static void wnm_send_bss_transition_mgmt_resp(
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Response "
|
wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Response "
|
||||||
"to " MACSTR " dialog_token=%u status=%u delay=%d",
|
"to " MACSTR " dialog_token=%u status=%u delay=%d",
|
||||||
MAC2STR(wpa_s->bssid), dialog_token, status, delay);
|
MAC2STR(wpa_s->bssid), dialog_token, status, delay);
|
||||||
|
if (!wpa_s->current_bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Current BSS not known - drop response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mgmt = (struct ieee80211_mgmt *) buf;
|
mgmt = (struct ieee80211_mgmt *) buf;
|
||||||
os_memset(&buf, 0, sizeof(buf));
|
os_memset(&buf, 0, sizeof(buf));
|
||||||
|
@ -572,56 +566,69 @@ static void wnm_send_bss_transition_mgmt_resp(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wnm_scan_response(struct wpa_supplicant *wpa_s,
|
int wnm_scan_process(struct wpa_supplicant *wpa_s)
|
||||||
struct wpa_scan_results *scan_res)
|
|
||||||
{
|
{
|
||||||
u8 bssid[ETH_ALEN];
|
struct wpa_bss *bss;
|
||||||
|
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
||||||
|
enum bss_trans_mgmt_status_code status = WNM_BSS_TM_REJECT_UNSPECIFIED;
|
||||||
|
|
||||||
if (scan_res == NULL) {
|
if (!wpa_s->wnm_neighbor_report_elements)
|
||||||
wpa_printf(MSG_ERROR, "Scan result is NULL");
|
return 0;
|
||||||
goto send_bss_resp_fail;
|
|
||||||
|
if (os_reltime_before(&wpa_s->wnm_cand_valid_until,
|
||||||
|
&wpa_s->scan_trigger_time)) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Previously stored BSS transition candidate list is not valid anymore - drop it");
|
||||||
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wpa_s->current_bss ||
|
||||||
|
os_memcmp(wpa_s->wnm_cand_from_bss, wpa_s->current_bss->bssid,
|
||||||
|
ETH_ALEN) != 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Stored BSS transition candidate list not from the current BSS - ignore it");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare the Neighbor Report and scan results */
|
/* Compare the Neighbor Report and scan results */
|
||||||
if (compare_scan_neighbor_results(wpa_s, scan_res,
|
bss = compare_scan_neighbor_results(wpa_s);
|
||||||
wpa_s->wnm_neighbor_report_elements,
|
|
||||||
wpa_s->wnm_num_neighbor_report,
|
|
||||||
bssid) == 1) {
|
|
||||||
/* Associate to the network */
|
|
||||||
struct wpa_bss *bss;
|
|
||||||
struct wpa_ssid *ssid = wpa_s->current_ssid;
|
|
||||||
|
|
||||||
bss = wpa_bss_get_bssid(wpa_s, bssid);
|
|
||||||
if (!bss) {
|
if (!bss) {
|
||||||
wpa_printf(MSG_DEBUG, "WNM: Target AP not found from "
|
wpa_printf(MSG_DEBUG, "WNM: No BSS transition candidate match found");
|
||||||
"BSS table");
|
status = WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES;
|
||||||
goto send_bss_resp_fail;
|
goto send_bss_resp_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Associate to the network */
|
||||||
/* Send the BSS Management Response - Accept */
|
/* Send the BSS Management Response - Accept */
|
||||||
if (wpa_s->wnm_reply) {
|
if (wpa_s->wnm_reply) {
|
||||||
|
wpa_s->wnm_reply = 0;
|
||||||
wnm_send_bss_transition_mgmt_resp(wpa_s,
|
wnm_send_bss_transition_mgmt_resp(wpa_s,
|
||||||
wpa_s->wnm_dialog_token,
|
wpa_s->wnm_dialog_token,
|
||||||
WNM_BSS_TM_ACCEPT,
|
WNM_BSS_TM_ACCEPT,
|
||||||
0, bssid);
|
0, bss->bssid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bss == wpa_s->current_bss) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"WNM: Already associated with the preferred candidate");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_s->reassociate = 1;
|
wpa_s->reassociate = 1;
|
||||||
wpa_supplicant_connect(wpa_s, bss, ssid);
|
wpa_supplicant_connect(wpa_s, bss, ssid);
|
||||||
wnm_deallocate_memory(wpa_s);
|
wnm_deallocate_memory(wpa_s);
|
||||||
return;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
/* Send reject response for all the failures */
|
/* Send reject response for all the failures */
|
||||||
send_bss_resp_fail:
|
send_bss_resp_fail:
|
||||||
wnm_deallocate_memory(wpa_s);
|
|
||||||
if (wpa_s->wnm_reply) {
|
if (wpa_s->wnm_reply) {
|
||||||
|
wpa_s->wnm_reply = 0;
|
||||||
wnm_send_bss_transition_mgmt_resp(wpa_s,
|
wnm_send_bss_transition_mgmt_resp(wpa_s,
|
||||||
wpa_s->wnm_dialog_token,
|
wpa_s->wnm_dialog_token,
|
||||||
WNM_BSS_TM_REJECT_UNSPECIFIED,
|
status, 0, NULL);
|
||||||
0, NULL);
|
|
||||||
}
|
}
|
||||||
return;
|
wnm_deallocate_memory(wpa_s);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -785,8 +792,8 @@ static void ieee802_11_rx_bss_trans_mgmt_req(struct wpa_supplicant *wpa_s,
|
||||||
wpa_s->wnm_cand_valid_until.sec +=
|
wpa_s->wnm_cand_valid_until.sec +=
|
||||||
wpa_s->wnm_cand_valid_until.usec / 1000000;
|
wpa_s->wnm_cand_valid_until.usec / 1000000;
|
||||||
wpa_s->wnm_cand_valid_until.usec %= 1000000;
|
wpa_s->wnm_cand_valid_until.usec %= 1000000;
|
||||||
|
os_memcpy(wpa_s->wnm_cand_from_bss, wpa_s->bssid, ETH_ALEN);
|
||||||
|
|
||||||
wpa_s->scan_res_handler = wnm_scan_response;
|
|
||||||
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
wpa_supplicant_req_scan(wpa_s, 0, 0);
|
||||||
} else if (reply) {
|
} else if (reply) {
|
||||||
enum bss_trans_mgmt_status_code status;
|
enum bss_trans_mgmt_status_code status;
|
||||||
|
|
|
@ -58,4 +58,18 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
|
||||||
u8 query_reason);
|
u8 query_reason);
|
||||||
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
|
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
|
||||||
|
int wnm_scan_process(struct wpa_supplicant *wpa_s);
|
||||||
|
|
||||||
|
#else /* CONFIG_WNM */
|
||||||
|
|
||||||
|
static inline int wnm_scan_process(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
#endif /* WNM_STA_H */
|
#endif /* WNM_STA_H */
|
||||||
|
|
|
@ -872,6 +872,7 @@ struct wpa_supplicant {
|
||||||
u8 wnm_bss_termination_duration[12];
|
u8 wnm_bss_termination_duration[12];
|
||||||
struct neighbor_report *wnm_neighbor_report_elements;
|
struct neighbor_report *wnm_neighbor_report_elements;
|
||||||
struct os_reltime wnm_cand_valid_until;
|
struct os_reltime wnm_cand_valid_until;
|
||||||
|
u8 wnm_cand_from_bss[ETH_ALEN];
|
||||||
#endif /* CONFIG_WNM */
|
#endif /* CONFIG_WNM */
|
||||||
|
|
||||||
#ifdef CONFIG_TESTING_GET_GTK
|
#ifdef CONFIG_TESTING_GET_GTK
|
||||||
|
|
Loading…
Reference in a new issue