[RFC PATCH] initial UHR support

Johannes Berg johannes at sipsolutions.net
Mon Sep 29 03:44:48 PDT 2025


Couple of comments about this:

On Fri, 2025-09-26 at 00:51 +0200, Johannes Berg wrote:
> 
> +u8 * hostapd_eid_uhr_operation(struct hostapd_data *hapd, u8 *eid, bool beacon)
> +{

I reserved the 'beacon' parameter here even if it doesn't do anything,
because in beacons not all the information is included (only the enabled
bits, e.g. for NPCA, not the exact information.)

> +	/* 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;

Also, I'm not sure this should even _exist_, but it's there in D1.0,
though apparently undefined, for now. My matching client implementation
in mac80211 will right now ignore it.

>  /* STA flags */
> -#define WLAN_STA_AUTH BIT(0)
> 
> +#define WLAN_STA_AUTH BIT_ULL(0)

This all was needed for cases such as

	sta->flags &= ~WLAN_STA_AUTH;

because otherwise the ~ is calculated in 32-bits only and the top bits
would be lost.

> -	u32 flags; /* Bitfield of WLAN_STA_* */
> +	unsigned long long flags; /* Bitfield of WLAN_STA_* */

I did ULL here instead of u64 for printing, but we can also cast during
printing I guess.

> +++ b/src/common/ieee802_11_common.c
> @@ -420,6 +420,14 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen,
>  		elems->pasn_encrypted_data = pos;
>  		elems->pasn_encrypted_data_len = elen;
>  		break;
> +	case WLAN_EID_EXT_UHR_CAPABILITIES:
> +		elems->uhr_capabilities = pos;
> +		elems->uhr_capabilities_len = elen;
> +		break;
> +	case WLAN_EID_EXT_UHR_OPERATION:
> +		elems->uhr_operation = pos;
> +		elems->uhr_operation_len = elen;
> +		break;
>  	default:
>  		if (show_errors) {
>  			wpa_printf(MSG_MSGDUMP,

I did wonder if there should be (length) validation here?

> +#define BSS_MEMBERSHIP_SELECTOR_UHR_PHY 120

This was erroneously listed as 122 in D1.0 (I guess someone just took
EHT and did +1 for the numbers ;-) ), but of course we count down here
so HE=122, EHT=121 and probably UHR=120.

> +/* UHR Capabilities element format */
> +struct ieee80211_uhr_capabilities {
> +	/* UHR MAC Capabilities Information */
> +	u8 mac[5];
> +	/* UHR PHY Capabilities Information */
> +	u8 phy[1];
> +} STRUCT_PACKED;

There already is and will be some variable stuff here, so this
definitely needs changing.

> +++ b/src/drivers/driver_common.c
> @@ -204,6 +204,13 @@ bool he_supported(const struct hostapd_hw_modes *hw_mode,
>  }
>  
>  
> +bool uhr_supported(const struct hostapd_hw_modes *hw_mode,
> +		   enum ieee80211_op_mode op_mode)
> +{
> +	return hw_mode->uhr_capab[op_mode].uhr_supported;
> +}

I deliberately didn't include the "old driver" workaround here that EHT
has and I guess copied from older - I figure new drivers for UHR should
have the right info.

> +++ b/tests/hwsim/vm/inside.sh
> @@ -109,7 +109,7 @@ ip link set lo up
>  # create logs mountpoint and mount the logshare
>  mkdir /tmp/logs
>  if grep -q rootfstype=hostfs /proc/cmdline; then
> -    mount -t hostfs none /tmp/logs -o $LOGDIR
> +    mount -t hostfs none /tmp/logs -o hostfs=$LOGDIR

Ouch, that shouldn't have been here - I needed to fix that for newer
'mount' binaries, unfortunately the new mount API etc. broke the old
command line. We might have to detect that somehow, because I think this
will break on _old_ kernels.

> +++ b/wpa_supplicant/ctrl_iface.c
> @@ -2370,12 +2370,14 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
>  
>  		if (wpa_s->connection_set &&
>  		    (wpa_s->connection_ht || wpa_s->connection_vht ||
> -		     wpa_s->connection_he || wpa_s->connection_eht)) {
> +		     wpa_s->connection_he || wpa_s->connection_eht ||
> +		     wpa_s->connection_uhr)) {
>  			ret = os_snprintf(pos, end - pos,
>  					  "wifi_generation=%u\n",
> +					  wpa_s->connection_uhr ? 8 :
>  					  wpa_s->connection_eht ? 7 :
> -					  (wpa_s->connection_he ? 6 :
> -					   (wpa_s->connection_vht ? 5 : 4)));
> +					  wpa_s->connection_he ? 6 :
> +					  wpa_s->connection_vht ? 5 : 4);

I removed parentheses because that seemed like it'd get messy, and given
operator precedence (ternary is really low on the list) they weren't
needed anyway.

> +++ b/wpa_supplicant/sme.c
> @@ -2571,6 +2571,7 @@ mscs_fail:
>  	wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
>  #endif /* CONFIG_HE_OVERRIDES */
>  	wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
> +	wpa_supplicant_apply_uhr_overrides(wpa_s, ssid, &params);

Wasn't sure if there should be an ifdef - wasn't for EHT.

johannes



More information about the Hostap mailing list