[2/4] hostapd: add RSSI based association rejection support

Message ID 1503333835-15264-2-git-send-email-andrei.otcheretianski@intel.com
State New
Headers show

Commit Message

Otcheretianski, Andrei Aug. 21, 2017, 4:43 p.m.
From: Beni Lev <beni.lev@intel.com>

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 <beni.lev@intel.com>
---
 hostapd/config_file.c      |  4 ++++
 hostapd/hostapd.conf       |  9 +++++++++
 src/ap/ap_config.c         |  3 +++
 src/ap/ap_config.h         |  3 +++
 src/ap/ieee802_11.c        | 25 +++++++++++++++++++------
 src/ap/ieee802_11.h        |  3 +++
 src/ap/ieee802_11_shared.c | 14 ++++++++++++++
 7 files changed, 55 insertions(+), 6 deletions(-)

Patch

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index cc799d4..4062569 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3740,6 +3740,10 @@  static int hostapd_config_fill(struct hostapd_config *conf,
 	} else if (os_strcmp(buf, "dpp_csign_expiry") == 0) {
 		bss->dpp_csign_expiry = strtol(pos, NULL, 0);
 #endif /* CONFIG_DPP */
+	} 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 7ad3206..63a47f3 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -2225,3 +2225,12 @@  own_ip_addr=127.0.0.1
 #bss=wlan0_1
 #bssid=00:13:10:95:fe:0b
 # ...
+
+# RSSI based assocition rejection settings
+#
+# Reject STA association if RSSI is below given threshold(in dBm)
+#rssi_reject_assoc_rssi=-75
+#
+# Assoc retry delay in seconds allowed by the STA if RSSI has not met the
+# threshold. (default=30)
+#rssi_reject_assoc_timeout=60
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 07a13f8..eb4e293 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -219,6 +219,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 8e5ff52..514aaf5 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -785,6 +785,9 @@  struct hostapd_config {
 	struct he_phy_capabilities_info he_phy_capab;
 	struct he_operation he_op;
 #endif /* CONFIG_IEEE80211AX */
+
+	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 7999611..6f51214 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2576,7 +2576,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;
@@ -2621,6 +2621,13 @@  static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 	/* Extended supported rates */
 	p = hostapd_eid_ext_supp_rates(hapd, p);
 
+	if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS) {
+		int delta = hapd->iconf->rssi_reject_assoc_rssi - rssi;
+
+		p = hostapd_eid_mbo_rssi_assoc_rej(hapd, p, buf + buflen - p,
+						   delta);
+	}
+
 #ifdef CONFIG_IEEE80211R_AP
 	if (sta && status_code == WLAN_STATUS_SUCCESS) {
 		/* IEEE 802.11r: Mobility Domain Information, Fast BSS
@@ -2820,7 +2827,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;
@@ -2860,7 +2867,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;
@@ -2931,6 +2938,12 @@  static void handle_assoc(struct hostapd_data *hapd,
 	}
 
 	sta = ap_get_sta(hapd, mgmt->sa);
+
+	if (hapd->iconf->rssi_reject_assoc_rssi &&
+	    rssi < hapd->iconf->rssi_reject_assoc_rssi) {
+		resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS;
+		goto fail;
+	}
 #ifdef CONFIG_IEEE80211R_AP
 	if (sta && sta->auth_alg == WLAN_AUTH_FT &&
 	    (sta->flags & WLAN_STA_AUTH) == 0) {
@@ -3218,7 +3231,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);
 
 	/*
@@ -3652,12 +3665,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, fi->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, fi->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 0653fb2..97cfdaf 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -112,6 +112,9 @@  static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd,
 }
 #endif /* CONFIG_SAE */
 
+u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid,
+				    size_t len, int delta);
+
 #ifdef CONFIG_MBO
 
 u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len);
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index 902f64f..66fb4ef 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -539,6 +539,20 @@  u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
 	return pos;
 }
 
+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);
+}
 
 #ifdef CONFIG_MBO