[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