From d58c3bd8b76f9ba6674b00e09a9e563970358a30 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Tue, 13 Mar 2018 08:50:28 +0530 Subject: [PATCH] hostapd: Ignore LOW_ACK event for co-operative steering clients Ignore hostapd_event_sta_low_ack for a station which has agreed to steering by checking the agreed_to_steer flag. This flag will be set whenever a station accepts the BSS transition request from the AP. Without this ignoring of the LOW_ACK event, the steering in-progress might be affected due to disassociation. In this way AP will allow some time (two seconds) for the station to move away and reset the flag after the timeout. Co-Developed-by: Tamizh Chelvam Signed-off-by: Rajkumar Manoharan Signed-off-by: Tamizh chelvam --- src/ap/drv_callbacks.c | 2 +- src/ap/sta_info.c | 4 ++++ src/ap/sta_info.h | 1 + src/ap/wnm_ap.c | 27 +++++++++++++++++++++++++++ src/ap/wnm_ap.h | 1 + 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index f0d6a4ccb..b9443ee24 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -642,7 +642,7 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta = ap_get_sta(hapd, addr); - if (!sta || !hapd->conf->disassoc_low_ack) + if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer) return; hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 49a0dbe85..154879c06 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -361,6 +361,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_free(sta->ext_capability); +#ifdef CONFIG_WNM_AP + eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); +#endif /* CONFIG_WNM_AP */ + os_free(sta); } diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index b4e7806db..255ac1fee 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -115,6 +115,7 @@ struct sta_info { unsigned int added_unassoc:1; unsigned int pending_wds_enable:1; unsigned int power_capab:1; + unsigned int agreed_to_steer:1; u16 auth_alg; diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index f0462829f..710fe502b 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -341,6 +341,19 @@ static void ieee802_11_rx_bss_trans_mgmt_query(struct hostapd_data *hapd, } +void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + if (sta->agreed_to_steer) { + wpa_printf(MSG_DEBUG, "%s: Reset steering flag for STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->agreed_to_steer = 0; + } +} + + static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, const u8 *addr, const u8 *frm, size_t len) @@ -348,6 +361,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, u8 dialog_token, status_code, bss_termination_delay; const u8 *pos, *end; int enabled = hapd->conf->bss_transition; + struct sta_info *sta; #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled) @@ -379,11 +393,23 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, "bss_termination_delay=%u", MAC2STR(addr), dialog_token, status_code, bss_termination_delay); + sta = ap_get_sta(hapd, addr); + if (!sta) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for received BSS TM Response", + MAC2STR(addr)); + return; + } + if (status_code == WNM_BSS_TM_ACCEPT) { if (end - pos < ETH_ALEN) { wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field"); return; } + sta->agreed_to_steer = 1; + eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); + eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer, + hapd, sta); wpa_printf(MSG_DEBUG, "WNM: Target BSSID: " MACSTR, MAC2STR(pos)); wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR @@ -393,6 +419,7 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, MAC2STR(pos)); pos += ETH_ALEN; } else { + sta->agreed_to_steer = 0; wpa_msg(hapd->msg_ctx, MSG_INFO, BSS_TM_RESP MACSTR " status_code=%u bss_termination_delay=%u", MAC2STR(addr), status_code, bss_termination_delay); diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h index a44eadb85..56d0f881e 100644 --- a/src/ap/wnm_ap.h +++ b/src/ap/wnm_ap.h @@ -23,5 +23,6 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta, const u8 *bss_term_dur, const char *url, const u8 *nei_rep, size_t nei_rep_len, const u8 *mbo_attrs, size_t mbo_len); +void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx); #endif /* WNM_AP_H */