From 076f1ea1d9d78a2ecca678e3a7dddec128ff19fc Mon Sep 17 00:00:00 2001 From: Beni Lev Date: Mon, 21 Aug 2017 19:43:53 +0300 Subject: [PATCH] OCE: Add RSSI based association rejection support (AP) An AP might reject a STA association request due to low RSSI. In such case, the AP informs the STA the desired RSSI improvement and a retry timeout. The STA might retry to associate even if the RSSI hasn't improved if the retry timeout expired. Signed-off-by: Beni Lev --- hostapd/config_file.c | 4 ++++ hostapd/hostapd.conf | 15 +++++++++++++++ src/ap/ap_config.c | 3 +++ src/ap/ap_config.h | 3 +++ src/ap/ieee802_11.c | 28 ++++++++++++++++++++++------ src/ap/ieee802_11.h | 3 +++ src/ap/ieee802_11_shared.c | 16 ++++++++++++++++ 7 files changed, 66 insertions(+), 6 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index cb8d26fce..19ccb30cd 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -4156,6 +4156,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } bss->multi_ap = val; + } else if (os_strcmp(buf, "rssi_reject_assoc_rssi") == 0) { + conf->rssi_reject_assoc_rssi = atoi(pos); + } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) { + conf->rssi_reject_assoc_timeout = atoi(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index e934b9f34..d234a4339 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -2295,6 +2295,21 @@ own_ip_addr=127.0.0.1 # Default is 0 = OCE disabled #oce=0 +# RSSI-based assocition rejection +# +# Reject STA association if RSSI is below given threshold (in dBm) +# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled) +# Note: This rejection happens based on a signal strength detected while +# receiving a single frame and as such, there is significant risk of the value +# not being accurate and this resulting in valid stations being rejected. As +# such, this functionality is not recommended to be used for purposes other than +# testing. +#rssi_reject_assoc_rssi=-75 +# +# Association retry delay in seconds allowed by the STA if RSSI has not met the +# threshold (range: 0..255, default=30). +#rssi_reject_assoc_timeout=30 + ##### Fast Session Transfer (FST) support ##################################### # # The options in this section are only available when the build configuration diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 68abb8e32..95a34763b 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -241,6 +241,9 @@ struct hostapd_config * hostapd_config_defaults(void) * environments for the current frequency band in the country. */ conf->country[2] = ' '; + conf->rssi_reject_assoc_rssi = 0; + conf->rssi_reject_assoc_timeout = 30; + return conf; } diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index f0645dcf9..c49e2c1c4 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -849,6 +849,9 @@ struct hostapd_config { #define CH_SWITCH_VHT_ENABLED BIT(0) #define CH_SWITCH_VHT_DISABLED BIT(1) unsigned int ch_switch_vht_config; + + int rssi_reject_assoc_rssi; + int rssi_reject_assoc_timeout; }; diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 026cbf025..d36430801 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -2976,7 +2976,7 @@ static int add_associated_sta(struct hostapd_data *hapd, static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 status_code, int reassoc, - const u8 *ies, size_t ies_len) + const u8 *ies, size_t ies_len, int rssi) { int send_len; u8 *buf; @@ -3021,6 +3021,16 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, /* Extended supported rates */ p = hostapd_eid_ext_supp_rates(hapd, p); +#ifdef CONFIG_MBO + if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS && + rssi != 0) { + int delta = hapd->iconf->rssi_reject_assoc_rssi - rssi; + + p = hostapd_eid_mbo_rssi_assoc_rej(hapd, p, buf + buflen - p, + delta); + } +#endif /* CONFIG_MBO */ + #ifdef CONFIG_IEEE80211R_AP if (sta && status_code == WLAN_STATUS_SUCCESS) { /* IEEE 802.11r: Mobility Domain Information, Fast BSS @@ -3292,7 +3302,7 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta) reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS, sta->fils_pending_assoc_is_reassoc, sta->fils_pending_assoc_req, - sta->fils_pending_assoc_req_len); + sta->fils_pending_assoc_req_len, 0); os_free(sta->fils_pending_assoc_req); sta->fils_pending_assoc_req = NULL; sta->fils_pending_assoc_req_len = 0; @@ -3329,7 +3339,7 @@ void fils_hlp_timeout(void *eloop_ctx, void *eloop_data) static void handle_assoc(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len, - int reassoc) + int reassoc, int rssi) { u16 capab_info, listen_interval, seq_ctrl, fc; u16 resp = WLAN_STATUS_SUCCESS, reply_res; @@ -3512,6 +3522,12 @@ static void handle_assoc(struct hostapd_data *hapd, resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto fail; } + + if (hapd->iconf->rssi_reject_assoc_rssi && rssi && + rssi < hapd->iconf->rssi_reject_assoc_rssi) { + resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS; + goto fail; + } #endif /* CONFIG_MBO */ /* @@ -3710,7 +3726,7 @@ static void handle_assoc(struct hostapd_data *hapd, #endif /* CONFIG_FILS */ reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos, - left); + left, rssi); os_free(tmp); /* @@ -4155,12 +4171,12 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, break; case WLAN_FC_STYPE_ASSOC_REQ: wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); - handle_assoc(hapd, mgmt, len, 0); + handle_assoc(hapd, mgmt, len, 0, ssi_signal); ret = 1; break; case WLAN_FC_STYPE_REASSOC_REQ: wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); - handle_assoc(hapd, mgmt, len, 1); + handle_assoc(hapd, mgmt, len, 1, ssi_signal); ret = 1; break; case WLAN_FC_STYPE_DISASSOC: diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index b57f2d0ba..11747e135 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -122,6 +122,9 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len); u8 hostapd_mbo_ie_len(struct hostapd_data *hapd); +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta); + #else /* CONFIG_MBO */ static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index f6c655fd3..82bc086a7 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -682,6 +682,22 @@ u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) #ifdef CONFIG_MBO +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta) +{ + u8 mbo[4]; + + mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT; + mbo[1] = 2; + /* Delta RSSI */ + mbo[2] = delta; + /* Retry delay */ + mbo[3] = hapd->iconf->rssi_reject_assoc_timeout; + + return eid + mbo_add_ie(eid, len, mbo, 4); +} + + u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) { u8 mbo[9], *mbo_pos = mbo;