[PATCH v2 5/7] initial UHR support

Raja Mani raja.mani at oss.qualcomm.com
Thu Mar 19 02:17:05 PDT 2026



On 3/17/2026 10:05 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg at intel.com>
> 
> Add initial UHR support, based on a very "superficial"
> reading of D1.3 (it's incomplete and not well-specified
> in quite a few places.)
> 
> Reviewed-by: Benjamin Berg <benjamin.berg at intel.com>
> Signed-off-by: Johannes Berg <johannes.berg at intel.com>
> ---
>   hostapd/Android.mk                |   6 ++
>   hostapd/Makefile                  |   6 ++
>   hostapd/config_file.c             |   8 ++
>   hostapd/hostapd.conf              |  13 +++
>   src/ap/ap_config.h                |   6 ++
>   src/ap/ap_drv_ops.c               |   4 +
>   src/ap/ap_drv_ops.h               |   2 +
>   src/ap/beacon.c                   |  42 +++++++++
>   src/ap/ctrl_iface_ap.c            |  16 ++++
>   src/ap/hostapd.h                  |   6 ++
>   src/ap/ieee802_11.c               |  53 ++++++++++-
>   src/ap/ieee802_11.h               |  13 +++
>   src/ap/ieee802_11_uhr.c           | 145 ++++++++++++++++++++++++++++++
>   src/ap/sta_info.c                 |  10 ++-
>   src/ap/sta_info.h                 |  65 +++++++-------
>   src/common/ieee802_11_common.c    |  16 ++++
>   src/common/ieee802_11_common.h    |   4 +
>   src/common/ieee802_11_defs.h      |  36 ++++++++
>   src/drivers/driver.h              |  28 ++++++
>   src/drivers/driver_common.c       |   6 ++
>   wpa_supplicant/Android.mk         |   3 +
>   wpa_supplicant/Makefile           |   7 ++
>   wpa_supplicant/config.c           |   1 +
>   wpa_supplicant/config_file.c      |   1 +
>   wpa_supplicant/config_ssid.h      |   8 ++
>   wpa_supplicant/ctrl_iface.c       |   8 +-
>   wpa_supplicant/events.c           |  13 +++
>   wpa_supplicant/sme.c              |   1 +
>   wpa_supplicant/wpa_cli.c          |   1 +
>   wpa_supplicant/wpa_supplicant.c   |  17 +++-
>   wpa_supplicant/wpa_supplicant_i.h |   4 +
>   31 files changed, 508 insertions(+), 41 deletions(-)
>   create mode 100644 src/ap/ieee802_11_uhr.c
> 

[..]

> @@ -6345,7 +6396,7 @@ static void handle_assoc(struct hostapd_data *hapd,
>   			hostapd_logger(hapd, mgmt->sa,
>   				       HOSTAPD_MODULE_IEEE80211,
>   				       HOSTAPD_LEVEL_INFO,
> -				       "Station tried to associate before authentication (aid=%d flags=0x%x)",
> +				       "Station tried to associate before authentication (aid=%d flags=0x%llx)",
>   				       sta ? sta->aid : -1,
>   				       sta ? sta->flags : 0);
>   			send_deauth(hapd, mgmt->sa,
> diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h
> index 991377c1c483..82c471e92725 100644
> --- a/src/ap/ieee802_11.h
> +++ b/src/ap/ieee802_11.h
> @@ -328,4 +328,17 @@ void hostapd_link_reconf_resp_tx_status(struct hostapd_data *hapd,
>   size_t hostapd_eid_eht_ml_tid_to_link_map_len(struct hostapd_data *hapd);
>   u8 * hostapd_eid_eht_ml_tid_to_link_map(struct hostapd_data *hapd, u8 *eid);
>   
> +size_t hostapd_eid_uhr_capab_len(struct hostapd_data *hapd,
> +				 enum ieee80211_op_mode opmode);
> +u8 * hostapd_eid_uhr_capab(struct hostapd_data *hapd, u8 *eid,
> +			   enum ieee80211_op_mode opmode);
> +u8 * hostapd_eid_uhr_operation(struct hostapd_data *hapd, u8 *eid, bool beacon);
> +u16 copy_sta_uhr_capab(struct hostapd_data *hapd, struct sta_info *sta,
> +		       enum ieee80211_op_mode opmode,
> +		       const u8 *uhr_capab, size_t uhr_capab_len);
> +void hostapd_get_uhr_capab(struct hostapd_data *hapd,
> +			   const struct ieee80211_uhr_capabilities *src,
> +			   struct ieee80211_uhr_capabilities *dest,
> +			   size_t len);
> +
>   #endif /* IEEE802_11_H */
> diff --git a/src/ap/ieee802_11_uhr.c b/src/ap/ieee802_11_uhr.c
> new file mode 100644
> index 000000000000..d7b00746bd93
> --- /dev/null
> +++ b/src/ap/ieee802_11_uhr.c
> @@ -0,0 +1,145 @@
> +/*
> + * hostapd / IEEE 802.11bn UHR
> + * Copyright (C) 2025 Intel Corporation
> + *
> + * This software may be distributed under the terms of the BSD license.
> + * See README for more details.
> + */
> +
> +#include "utils/includes.h"
> +#include "utils/common.h"
> +#include "common/ocv.h"
> +#include "common/wpa_ctrl.h"
> +#include "crypto/crypto.h"
> +#include "crypto/dh_groups.h"
> +#include "hostapd.h"
> +#include "sta_info.h"
> +#include "ap_drv_ops.h"
> +#include "wpa_auth.h"
> +#include "ieee802_11.h"
> +
> +
> +size_t hostapd_eid_uhr_capab_len(struct hostapd_data *hapd,
> +				 enum ieee80211_op_mode opmode)
> +{
> +	struct hostapd_hw_modes *mode;
> +	struct uhr_capabilities *uhr_cap;
> +
> +	mode = hapd->iface->current_mode;
> +	if (!mode)
> +		return 0;
> +
> +	uhr_cap = &mode->uhr_capab[opmode];
> +	if (!uhr_cap->uhr_supported)
> +		return 0;
> +
> +	return 6;

I hope, 6 bytes refers to mac(5 bytes) + phy(1 bytes). Don't we have
to include addtional 3 byte here (or) in the caller to accomodate header
(eid (1 byte), len(1 byte), ext eid(1 byte) ?

> +}
> +
> +
> +u8 * hostapd_eid_uhr_capab(struct hostapd_data *hapd, u8 *eid,
> +			   enum ieee80211_op_mode opmode)
> +{
> +	struct hostapd_hw_modes *mode;
> +	struct uhr_capabilities *uhr_cap;
> +	struct ieee80211_uhr_capabilities *cap;
> +	u8 *pos = eid, *length_pos;
> +
> +	mode = hapd->iface->current_mode;
> +	if (!mode)
> +		return eid;
> +
> +	uhr_cap = &mode->uhr_capab[opmode];
> +	if (!uhr_cap->uhr_supported)
> +		return eid;
> +
> +	*pos++ = WLAN_EID_EXTENSION;
> +	length_pos = pos++;
> +	*pos++ = WLAN_EID_EXT_UHR_CAPABILITIES;
> +
> +	cap = (struct ieee80211_uhr_capabilities *) pos;
> +	os_memcpy(cap->mac, uhr_cap->mac, sizeof(cap->mac));
> +	os_memcpy(cap->phy, uhr_cap->phy, sizeof(cap->phy));
> +	pos += sizeof(*cap);
> +
> +	*length_pos = pos - (eid + 2);
> +	return pos;
> +}
> +
> +
> +u8 * hostapd_eid_uhr_operation(struct hostapd_data *hapd, u8 *eid, bool beacon)
> +{
> +	struct ieee80211_uhr_operation *oper;
> +	u8 *pos = eid;
> +
> +	if (!hapd->iface->current_mode)
> +		return eid;
> +
> +	*pos++ = WLAN_EID_EXTENSION;
> +	*pos++ = 1 + sizeof(*oper);
> +	*pos++ = WLAN_EID_EXT_UHR_OPERATION;
> +
> +	oper = (void *) pos;

Any specific reason for using 'void *' conversion instead of 'struct
ieee80211_uhr_operation *' ?

> +	oper->oper_params = 0;
> +
> +	/* TODO: Fill in appropriate UHR-MCS max Nss information */
> +	oper->basic_uhr_mcs_nss_set[0] = 0x11;
> +	oper->basic_uhr_mcs_nss_set[1] = 0x00;
> +	oper->basic_uhr_mcs_nss_set[2] = 0x00;
> +	oper->basic_uhr_mcs_nss_set[3] = 0x00;
> +
> +	return pos + sizeof(*oper);
> +}
> +
> +
> +static bool ieee80211_invalid_uhr_cap_size(enum hostapd_hw_mode mode,
> +					   const u8 *uhr_cap, size_t len)
> +{
> +	return len < sizeof(struct ieee80211_uhr_capabilities);
> +}
> +
> +

[..]

> diff --git a/src/drivers/driver.h b/src/drivers/driver.h
> index cefc73942ea6..d437dc7d58c5 100644
> --- a/src/drivers/driver.h
> +++ b/src/drivers/driver.h
> @@ -216,6 +216,13 @@ struct eht_capabilities {
>   	u8 ppet[EHT_PPE_THRESH_CAPAB_LEN];
>   };
>   
> +/* struct uhr_capabilities - IEEE 802.11bn UHR capabilities */
> +struct uhr_capabilities {
> +	bool uhr_supported;
> +	u8 mac[5];
> +	u8 phy[1];
> +};
> +
>   #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0)
>   #define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1)
>   #define HOSTAPD_MODE_FLAG_HE_INFO_KNOWN BIT(2)
> @@ -326,6 +333,11 @@ struct hostapd_hw_modes {
>   	 * eht_capab - EHT (IEEE 802.11be) capabilities
>   	 */
>   	struct eht_capabilities eht_capab[IEEE80211_MODE_NUM];
> +
> +	/**
> +	 * uhr_capab - UHR (IEEE 802.11bb) capabilities

s/802.11bb/802.11bn

> +	 */
> +	struct uhr_capabilities uhr_capab[IEEE80211_MODE_NUM];
>   };
>   
>   
> @@ -1403,6 +1415,11 @@ struct wpa_driver_associate_params {
>   	 */
>   	int disable_eht;
>   
> +	/**
> +	 * disable_uhr - Disable UHR for this connection
> +	 */
> +	int disable_uhr;
> +
>   	/*
>   	 * mld_params - MLD association parameters
>   	 */
> @@ -1928,6 +1945,12 @@ struct wpa_driver_ap_params {
>   	 * sae_password - SAE password for SAE offload
>   	 */
>   	const char *sae_password;
> +
> +	/**
> +	 * uhr_oper - Full UHR operation (beacon only has abridged data),
> +	 * includes the extended element header
> +	 */
> +	u8 *uhr_oper;
>   };
>   
>   struct wpa_driver_mesh_bss_params {



More information about the Hostap mailing list