[PATCH 4/9] 6G: Add HE 6 GHz band capability element in beacon and response frame

Rajkumar Manoharan <[email protected]>
Newsgroups gmane.linux.drivers.hostap
Message-ID <[email protected]>
Construct HE 6 GHz Band Capabilities element (IEEE 802.11ax/D6.0,
9.4.2.261) from HT and VHT capabilities.

Signed-off-by: Rajkumar Manoharan <[email protected]>
---
 src/ap/beacon.c        | 14 ++++++++++++++
 src/ap/ieee802_11.c    |  1 +
 src/ap/ieee802_11.h    |  1 +
 src/ap/ieee802_11_he.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 62 insertions(+)

diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 47ced9a166de..fab6035c6130 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -464,6 +464,12 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 			3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
 			3 + sizeof(struct ieee80211_spatial_reuse);
 	}
+
+	if (hapd->iconf->ieee80211ax &&
+	    is_6ghz_op_class(hapd->iconf->op_class)) {
+		buflen += sizeof(struct ieee80211_he_6ghz_oper_info) +
+			  3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+	}
 #endif /* CONFIG_IEEE80211AX */
 
 	buflen += hostapd_mbo_ie_len(hapd);
@@ -570,6 +576,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
 		pos = hostapd_eid_he_operation(hapd, pos);
 		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);
 	}
 #endif /* CONFIG_IEEE80211AX */
 
@@ -1162,6 +1169,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 			3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) +
 			3 + sizeof(struct ieee80211_spatial_reuse);
 	}
+
+	if (hapd->iconf->ieee80211ax &&
+	    is_6ghz_op_class(hapd->iconf->op_class)) {
+		tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) +
+			3 + sizeof(struct ieee80211_he_6ghz_band_cap);
+	}
 #endif /* CONFIG_IEEE80211AX */
 
 	tail_len += hostapd_mbo_ie_len(hapd);
@@ -1288,6 +1301,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 		tailpos = hostapd_eid_he_operation(hapd, tailpos);
 		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);
 	}
 #endif /* CONFIG_IEEE80211AX */
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 28ac7aa4b283..18ce144d373f 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -3785,6 +3785,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
 		p = hostapd_eid_he_operation(hapd, p);
 		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);
 	}
 #endif /* CONFIG_IEEE80211AX */
 
diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
index c7bdb4b2b113..ba505628982d 100644
--- a/src/ap/ieee802_11.h
+++ b/src/ap/ieee802_11.h
@@ -63,6 +63,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_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);
 
 int hostapd_ht_operation_update(struct hostapd_iface *iface);
 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c
index 57c6b18f4bf8..2c1b41d28cc4 100644
--- a/src/ap/ieee802_11_he.c
+++ b/src/ap/ieee802_11_he.c
@@ -311,6 +311,52 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid)
 }
 
 
+u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid)
+{
+	struct ieee80211_he_6ghz_band_cap *cap;
+	u32 vht_cap = hapd->iface->conf->vht_capab;
+	u8 ht_info = hapd->iface->current_mode->a_mpdu_params;
+	u8 params;
+	u8 *pos;
+
+	if (!is_6ghz_op_class(hapd->iconf->op_class))
+		return eid;
+
+	pos = eid;
+	*pos++ = WLAN_EID_EXTENSION;
+	*pos++ = 1 + sizeof(*cap);
+	*pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP;
+
+	/* Minimum MPDU Start Spacing B0..B2 */
+	params = (ht_info >> 2) & HE_6GHZ_BAND_CAP_MIN_MPDU_START_SPACE_MASK;
+
+	/* Maximum A-MPDU Length Exponent B3..B5 */
+	params |= ((((vht_cap & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >>
+		     VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT) &
+		    HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) <<
+		   HE_6GHZ_BAND_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
+
+	/* Maximum MPDU Length B6..B7 */
+	params |= ((((vht_cap & VHT_CAP_MAX_MPDU_LENGTH_MASK) >>
+		     VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT) &
+		    HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_MASK) <<
+		   HE_6GHZ_BAND_CAP_MAX_MPDU_LENGTH_SHIFT);
+
+	cap = (struct ieee80211_he_6ghz_band_cap *) pos;
+	cap->a_mpdu_params = params;
+	cap->info = HE_6GHZ_BAND_CAP_SMPS_DISABLED;
+	if (vht_cap & VHT_CAP_RX_ANTENNA_PATTERN)
+		cap->info |= HE_6GHZ_BAND_CAP_RX_ANTENNA_PATTERN;
+
+	if (vht_cap & VHT_CAP_TX_ANTENNA_PATTERN)
+		cap->info |= HE_6GHZ_BAND_CAP_TX_ANTENNA_PATTERN;
+
+	pos += sizeof(*cap);
+
+	return pos;
+}
+
+
 void hostapd_get_he_capab(struct hostapd_data *hapd,
 			  const struct ieee80211_he_capabilities *he_cap,
 			  struct ieee80211_he_capabilities *neg_he_cap,
-- 
2.7.4
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.