[PATCH v2 2/2] ANQP/hostapd: Add more data to the ANQP RNR response.

sharadanandk at gmail.com sharadanandk at gmail.com
Tue Feb 8 08:59:31 PST 2022


From: Sharadanand Karanjkar <skaranjkar at datto.com>

Adding more data apart from BSSID, Channel number -
- SSID
- HE Capabilities
- HE Operations
- HT Capabilities.
- HT Operations.
- Load BSS.

Signed-off-by: Sharadanand Karanjkar <skaranjkar at datto.com>
---
Changes to PATCHv1:
- Fixing white space errors.
---
 src/ap/beacon.c              |   8 +--
 src/ap/ieee802_11.c          |   4 +-
 src/ap/ieee802_11.h          |   4 +-
 src/ap/ieee802_11_he.c       |  33 ++++++++---
 src/ap/neighbor_db.c         | 111 ++++++++++++++++++++++++++++++++++-
 src/common/ieee802_11_defs.h |   5 ++
 wpa_supplicant/mesh_mpm.c    |   4 +-
 7 files changed, 148 insertions(+), 21 deletions(-)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 8cd1c4170..3004834d5 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -578,8 +578,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 
 #ifdef CONFIG_IEEE80211AX
 	if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
-		pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP);
-		pos = hostapd_eid_he_operation(hapd, pos);
+		pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP, false);
+		pos = hostapd_eid_he_operation(hapd, pos, false);
 		pos = hostapd_eid_spatial_reuse(hapd, pos);
 		pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos);
 		pos = hostapd_eid_he_6ghz_band_cap(hapd, pos);
@@ -1601,8 +1601,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 #ifdef CONFIG_IEEE80211AX
 	if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
 		tailpos = hostapd_eid_he_capab(hapd, tailpos,
-					       IEEE80211_MODE_AP);
-		tailpos = hostapd_eid_he_operation(hapd, tailpos);
+					       IEEE80211_MODE_AP, false);
+		tailpos = hostapd_eid_he_operation(hapd, tailpos, false);
 		tailpos = hostapd_eid_spatial_reuse(hapd, tailpos);
 		tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos);
 		tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index f63292537..581fd0007 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -5149,8 +5149,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 
 #ifdef CONFIG_IEEE80211AX
 	if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) {
-		p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
-		p = hostapd_eid_he_operation(hapd, p);
+		p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP, false);
+		p = hostapd_eid_he_operation(hapd, p, false);
 		p = hostapd_eid_spatial_reuse(hapd, p);
 		p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
 		p = hostapd_eid_he_6ghz_band_cap(hapd, p);
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index c59ad5e38..4d7677e2a 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -59,8 +59,8 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
-			  enum ieee80211_op_mode opmode);
-u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid);
+			  enum ieee80211_op_mode opmode, bool forRnr);
+u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid, bool forRnr);
 u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid);
 u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid);
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index 6cd6c90dc..010e0f4ed 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -81,7 +81,7 @@ static int ieee80211_invalid_he_cap_size(const u8 *buf, size_t len)
 
 
 u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
-			  enum ieee80211_op_mode opmode)
+			  enum ieee80211_op_mode opmode, bool for_rnr)
 {
 	struct ieee80211_he_capabilities *cap;
 	struct hostapd_hw_modes *mode = hapd->iface->current_mode;
@@ -115,9 +115,17 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
 
 	ie_size += mcs_nss_size + ppet_size;
 
-	*pos++ = WLAN_EID_EXTENSION;
-	*pos++ = 1 + ie_size;
-	*pos++ = WLAN_EID_EXT_HE_CAPABILITIES;
+	if(for_rnr)
+	{
+		*pos++ = WMM_NEIGHBOR_HE_CAPB;
+		*pos++ = ie_size;
+	}
+	else
+	{
+		*pos++ = WLAN_EID_EXTENSION;
+		*pos++ = 1 + ie_size;
+		*pos++ = WLAN_EID_EXT_HE_CAPABILITIES;
+	}
 
 	cap = (struct ieee80211_he_capabilities *) pos;
 	os_memset(cap, 0, sizeof(*cap));
@@ -161,7 +169,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid,
 }
 
 
-u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
+u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid, bool for_rnr)
 {
 	struct ieee80211_he_operation *oper;
 	u8 *pos = eid;
@@ -173,10 +181,17 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid)
 
 	if (is_6ghz_op_class(hapd->iconf->op_class))
 		oper_size += 5;
-
-	*pos++ = WLAN_EID_EXTENSION;
-	*pos++ = 1 + oper_size;
-	*pos++ = WLAN_EID_EXT_HE_OPERATION;
+	if(for_rnr)
+	{
+		*pos++ = WMM_NEIGHBOR_HE_OPER;
+		*pos++ = oper_size;
+	}
+	else
+	{
+		*pos++ = WLAN_EID_EXTENSION;
+		*pos++ = 1 + oper_size;
+		*pos++ = WLAN_EID_EXT_HE_OPERATION;
+	}
 
 	oper = (struct ieee80211_he_operation *) pos;
 	os_memset(oper, 0, sizeof(*oper));
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index 229edd2a9..8013285ca 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -217,6 +217,26 @@ static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
 }
 #endif /* NEED_AP_MLME */
 
+#ifdef NEED_AP_MLME
+static void hostapd_neighbor_bss_load(struct hostapd_data *hapd, struct wpabuf **nr)
+{
+#ifdef CONFIG_TESTING_OPTIONS
+       if (hapd->conf->bss_load_test_set) {
+               wpabuf_put_u8(*nr, WMM_NEIGHBOR_BSS_LOAD);
+               wpabuf_put_u8(*nr, 5);
+               wpabuf_put_data(*nr, hapd->conf->bss_load_test, 5);
+               return;
+       }
+#endif /* CONFIG_TESTING_OPTIONS */
+       if (hapd->conf->bss_load_update_period) {
+               wpabuf_put_u8(*nr, WMM_NEIGHBOR_BSS_LOAD);
+               wpabuf_put_u8(*nr, 5);
+               wpabuf_put_le16(*nr, hapd->num_sta);
+               wpabuf_put_u8(*nr, hapd->iface->channel_utilization);
+               wpabuf_put_le16(*nr, 0); /* no available admission capabity */
+       }
+}
+#endif
 
 void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 {
@@ -231,6 +251,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 	enum nr_chan_width width;
 	u32 bssid_info;
 	struct wpabuf *nr;
+	int len = 0;
 
 	if (!(hapd->conf->radio_measurements[0] &
 	      WLAN_RRM_CAPS_NEIGHBOR_REPORT))
@@ -291,9 +312,49 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 
 	/*
 	 * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
-	 * phy type + wide bandwidth channel subelement.
+	 * phy type + wide bandwidth channel subelement + SSID len.
 	 */
-	nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
+	len += ETH_ALEN + 4 + 1 + 1 + 1 + 5 + 2 + ssid.ssid_len;
+	if(ht)
+	{
+		// Adding length for ht cap and ht oper.
+		if(!is_6ghz_op_class(op_class))
+		{
+		        len += sizeof(struct ieee80211_ht_capabilities) + 2;
+			len += sizeof(struct ieee80211_ht_operation) + 2;
+		}
+	}
+	if(vht)
+	{
+		// Adding length for vht cap and ht vht oper.
+		if(!is_6ghz_op_class(op_class))
+		{
+		        len += sizeof(struct ieee80211_vht_capabilities) + 2;
+			len += sizeof(struct ieee80211_vht_operation) + 2;
+		}
+	}
+
+	if(he)
+	{
+		// Adding length for he cap and he oper length.
+		len += sizeof(struct ieee80211_he_capabilities) + 2 + 1;
+		len += sizeof(struct ieee80211_he_operation) + 2;
+		if(is_6ghz_op_class(op_class) )
+		{
+		        len += 5;
+		}
+	}
+
+#ifdef CONFIG_TESTING_OPTIONS
+	if (hapd->conf->bss_load_test_set) {
+		len += 5;
+	}
+#endif /* CONFIG_TESTING_OPTIONS */
+	if (hapd->conf->bss_load_update_period) {
+		len += 5;
+	}
+
+	nr = wpabuf_alloc(len);
 	if (!nr)
 		return;
 
@@ -314,6 +375,52 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
 	wpabuf_put_u8(nr, center_freq1_idx);
 	wpabuf_put_u8(nr, center_freq2_idx);
 
+	if(ht && !is_6ghz_op_class(op_class))
+	{
+		u8* tmp1;
+		u8* tmp = os_zalloc(sizeof(struct ieee80211_ht_capabilities) +
+                                                    sizeof(struct ieee80211_ht_operation) + 4);
+		tmp1 = hostapd_eid_ht_capabilities(hapd, tmp);
+		tmp1 = hostapd_eid_ht_operation(hapd, tmp1);
+		wpabuf_put_data(nr, tmp, sizeof(struct ieee80211_ht_capabilities) +
+                                                    sizeof(struct ieee80211_ht_operation) + 4);
+		os_free(tmp);
+	}
+
+	if(vht && !is_6ghz_op_class(op_class))
+	{
+		u8* tmp1;
+		u8* tmp = os_zalloc(sizeof(struct ieee80211_vht_capabilities) +
+		                                    sizeof(struct ieee80211_vht_operation) +4);
+		tmp1 = hostapd_eid_vht_capabilities(hapd, tmp, 0);
+		tmp1 = hostapd_eid_vht_operation(hapd, tmp1);
+		wpabuf_put_data(nr, tmp, sizeof(struct ieee80211_vht_capabilities) +
+                                                sizeof(struct ieee80211_vht_operation) +4);
+		os_free(tmp);
+	}
+
+	if(he)
+	{
+		u8* tmp, *tmp1, *tmp2;
+		if(is_6ghz_op_class(op_class) )
+		    tmp = os_zalloc(sizeof(struct ieee80211_ht_capabilities) +
+                                                        sizeof(struct ieee80211_ht_operation) + 4 + 5 + 1);
+		else
+		    tmp = os_zalloc(sizeof(struct ieee80211_ht_capabilities) +
+                                                        sizeof(struct ieee80211_ht_operation) + 4 + 1);
+		tmp1 = hostapd_eid_he_capab(hapd, tmp, IEEE80211_MODE_AP, true);
+		tmp2 = hostapd_eid_he_operation(hapd, tmp1, true);
+		wpabuf_put_data(nr, tmp, tmp2 - tmp );
+		os_free(tmp);
+	}
+
+	// TODO: Add more IEs
+	hostapd_neighbor_bss_load(hapd, &nr);
+
+	wpabuf_put_u8(nr, WMM_NEIGHBOR_SSID);
+	wpabuf_put_u8(nr, ssid.ssid_len);
+	wpabuf_put_data(nr, ssid.ssid, ssid.ssid_len);
+
 	hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
 			     hapd->iconf->civic, hapd->iconf->stationary_ap, 0);
 
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 928b53500..3b228aaf8 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1871,6 +1871,11 @@ enum bss_trans_mgmt_status_code {
 #define WNM_NEIGHBOR_MULTIPLE_BSSID             71
 #define WNM_NEIGHBOR_VHT_CAPAB                 191
 #define WNM_NEIGHBOR_VHT_OPER                  192
+#define WMM_NEIGHBOR_HE_CAPB                   193
+#define WMM_NEIGHBOR_HE_OPER                   194
+#define WMM_NEIGHBOR_BSS_LOAD                  195
+#define WMM_NEIGHBOR_HE_BSS_LOAD               196
+#define WMM_NEIGHBOR_SSID                      197
 
 /* QoS action */
 enum qos_action {
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 2eb9a7ef6..765842b6b 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -384,8 +384,8 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 				3 + sizeof(struct ieee80211_he_6ghz_band_cap)];
 
 		pos = hostapd_eid_he_capab(bss, he_capa_oper,
-					   IEEE80211_MODE_MESH);
-		pos = hostapd_eid_he_operation(bss, pos);
+					   IEEE80211_MODE_MESH, false);
+		pos = hostapd_eid_he_operation(bss, pos, false);
 		pos = hostapd_eid_he_6ghz_band_cap(bss, pos);
 		wpabuf_put_data(buf, he_capa_oper, pos - he_capa_oper);
 	}
-- 
2.30.2




More information about the Hostap mailing list