[PATCH v3 5/8] ap: advertise DBE capability if driver has it

Johannes Berg johannes at sipsolutions.net
Fri Apr 24 00:11:57 PDT 2026


From: Johannes Berg <johannes.berg at intel.com>

If the driver has DBE capability, then the DBE capabilities
field must be created. Do this based on the EHT capability
the driver is advertising.

Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
 src/ap/ieee802_11_uhr.c      | 43 ++++++++++++++++++++++++++++++++++--
 src/common/ieee802_11_defs.h |  9 ++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/src/ap/ieee802_11_uhr.c b/src/ap/ieee802_11_uhr.c
index 6538e0e0b9ea..2476b3412b75 100644
--- a/src/ap/ieee802_11_uhr.c
+++ b/src/ap/ieee802_11_uhr.c
@@ -24,6 +24,7 @@ size_t hostapd_eid_uhr_capab_len(struct hostapd_data *hapd,
 {
 	struct hostapd_hw_modes *mode;
 	struct uhr_capabilities *uhr_cap;
+	size_t len = 3 /* ext elem header */ + 6 /* MAC + PHY */;
 
 	mode = hapd->iface->current_mode;
 	if (!mode)
@@ -33,7 +34,10 @@ size_t hostapd_eid_uhr_capab_len(struct hostapd_data *hapd,
 	if (!uhr_cap->uhr_supported)
 		return 0;
 
-	return 3 /* ext elem header */ + 6 /* MAC + PHY */;
+	if (uhr_cap->mac[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP)
+		len++;
+
+	return len;
 }
 
 
@@ -41,6 +45,8 @@ u8 * hostapd_eid_uhr_capab(struct hostapd_data *hapd, u8 *eid,
 			   enum ieee80211_op_mode opmode)
 {
 	struct hostapd_hw_modes *mode;
+	struct he_capabilities *he_cap;
+	struct eht_capabilities *eht_cap;
 	struct uhr_capabilities *uhr_cap;
 	struct ieee80211_uhr_capabilities *cap;
 	u8 *pos = eid, *length_pos;
@@ -49,8 +55,12 @@ u8 * hostapd_eid_uhr_capab(struct hostapd_data *hapd, u8 *eid,
 	if (!mode)
 		return eid;
 
+	he_cap = &mode->he_capab[opmode];
+	eht_cap = &mode->eht_capab[opmode];
 	uhr_cap = &mode->uhr_capab[opmode];
-	if (!uhr_cap->uhr_supported)
+	if (!he_cap->he_supported ||
+	    !eht_cap->eht_supported ||
+	    !uhr_cap->uhr_supported)
 		return eid;
 
 	*pos++ = WLAN_EID_EXTENSION;
@@ -62,6 +72,35 @@ u8 * hostapd_eid_uhr_capab(struct hostapd_data *hapd, u8 *eid,
 	os_memcpy(cap->phy, uhr_cap->phy, sizeof(cap->phy));
 	pos += sizeof(*cap);
 
+	if (opmode == IEEE80211_MODE_AP &&
+	    cap->mac[1] & IEEE80211_UHR_MAC_CAP1_DBE_SUPP) {
+		/*
+		 * Assume that HE implies VHT implies 80 MHz at least,
+		 * DBE doesn't exist on 2.4 GHz and the capability
+		 * shouldn't be set by the driver.
+		 *
+		 * It's also not very relevant if DBE isn't enabled.
+		 */
+		u8 dbe_bw = IEEE80211_UHR_DBE_CAP_MAX_BW_80MHZ;
+
+		if (he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
+				HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
+			dbe_bw = IEEE80211_UHR_DBE_CAP_MAX_BW_160MHZ;
+
+		if (is_6ghz_op_class(hapd->iconf->op_class) &&
+		    eht_cap->phy_cap[EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_IDX] &
+				EHT_PHYCAP_320MHZ_IN_6GHZ_SUPPORT_MASK)
+			dbe_bw = IEEE80211_UHR_DBE_CAP_MAX_BW_320MHZ;
+
+		/*
+		 * No MCS maps or other further DBE capabilities
+		 * since we just use EHT capabilities and advertise
+		 * full EHT capabilities even if operating in a
+		 * lower bandwidth.
+		 */
+		*pos++ = dbe_bw;
+	}
+
 	*length_pos = pos - (eid + 2);
 	return pos;
 }
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 7ec295e5a248..8b32e95e227d 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -3297,12 +3297,21 @@ struct ieee80211_s1g_beacon_compat {
 	le32 tsf_completion;
 } STRUCT_PACKED;
 
+#define IEEE80211_UHR_MAC_CAP1_DBE_SUPP		0x04
+
+#define IEEE80211_UHR_DBE_CAP_MAX_BW_MASK	0x07
+#define IEEE80211_UHR_DBE_CAP_MAX_BW_40MHZ	1
+#define IEEE80211_UHR_DBE_CAP_MAX_BW_80MHZ	2
+#define IEEE80211_UHR_DBE_CAP_MAX_BW_160MHZ	3
+#define IEEE80211_UHR_DBE_CAP_MAX_BW_320MHZ	4
+
 /* UHR Capabilities element format */
 struct ieee80211_uhr_capabilities {
 	/* UHR MAC Capabilities Information */
 	u8 mac[5];
 	/* UHR PHY Capabilities Information */
 	u8 phy[1];
+	/* followed by DBE capabilities on AP */
 } STRUCT_PACKED;
 
 #define UHR_OPER_PARAMS_DPS_ENA               0x0001
-- 
2.53.0




More information about the Hostap mailing list