From: Peter Hessler Subject: Re: sys/ieee80211: support of uAPSD; sys/iwx: enable uAPSD when supported by AP To: tech@openbsd.org Date: Wed, 25 Mar 2026 20:20:10 +0100 On 2026 Mar 25 (Wed) at 01:50:37 +0100 (+0100), Kirill A. Korinsky wrote: :On Fri, 20 Mar 2026 15:40:03 +0100, :Kirill A. Korinsky wrote: :> :> tech@, :> :> here two diff in one where I implemented support of uAPSD and enabled it :> for iwx driver. When AP is misbehaving, uAPSD is disabled till the :> reconnect, and I don't keep per AP state like linux for simplicity. :> :> Tested on uAPSD enabled and disabled networks on :> :> iwx0 at pci0 dev 20 function 3 "Intel Wi-Fi 6 AX201" rev 0x00, msix :> iwx0: hw rev 0x350, fw 77.30b1cbd8.0, address 98:8d:46:21:2b:6d :> :> with unifi nano AP with enabled roaming with firmware 6.7.41.15623 :> : :here updated version of the diff. Changes: : :1. Fixed a copy and paste typo with IEEE80211 AC_XX bits :2. Never use uAPSD when firmware doesn't announce support it. : :Ok? : This version works for me on AX211, OK iwx0 at pci0 dev 20 function 3 "Intel Wi-Fi 6 AX211" rev 0x01, msix iwx0: hw rev 0x370, fw 77.f92b5fed.0, pnvm 285b3568, address XXX AP: TP-Link AX3000 Gigabit Wi-Fi 6 Router : :Index: sys/dev/pci/if_iwx.c :=================================================================== :RCS file: /home/cvs/src/sys/dev/pci/if_iwx.c,v :diff -u -p -r1.223 if_iwx.c :--- sys/dev/pci/if_iwx.c 14 Mar 2026 15:37:44 -0000 1.223 :+++ sys/dev/pci/if_iwx.c 25 Mar 2026 00:33:11 -0000 :@@ -6551,6 +6551,56 @@ iwx_update_beacon_abort(struct iwx_softc : return iwx_beacon_filter_send_cmd(sc, &cmd); : } : :+static uint8_t :+iwx_uapsd_qndp_tid(struct ieee80211com *ic, uint8_t acs) :+{ :+ if ((acs & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) && :+ !ic->ic_edca_ac[EDCA_AC_VO].ac_acm) :+ return 6; :+ if ((acs & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) && :+ !ic->ic_edca_ac[EDCA_AC_VI].ac_acm) :+ return 5; :+ if ((acs & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) && :+ !ic->ic_edca_ac[EDCA_AC_BE].ac_acm) :+ return 0; :+ if ((acs & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) && :+ !ic->ic_edca_ac[EDCA_AC_BK].ac_acm) :+ return 1; :+ return 0; :+} :+ :+static uint8_t :+iwx_uapsd_acs(struct ieee80211_node *ni) :+{ :+ uint8_t acs = 0; :+ :+ if (ni->ni_uapsd_ac & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) :+ acs |= 1 << IWX_AC_VO; :+ if (ni->ni_uapsd_ac & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) :+ acs |= 1 << IWX_AC_VI; :+ if (ni->ni_uapsd_ac & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) :+ acs |= 1 << IWX_AC_BE; :+ if (ni->ni_uapsd_ac & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) :+ acs |= 1 << IWX_AC_BK; :+ :+ return acs | (acs << IWX_AC_NUM); :+} :+ :+static uint8_t :+iwx_uapsd_sp_length(struct ieee80211_node *ni) :+{ :+ switch (ni->ni_uapsd_maxsp & IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) { :+ case IEEE80211_WMM_IE_STA_QOSINFO_SP_2: :+ return 2; :+ case IEEE80211_WMM_IE_STA_QOSINFO_SP_4: :+ return 4; :+ case IEEE80211_WMM_IE_STA_QOSINFO_SP_6: :+ return 6; :+ default: :+ return 128; :+ } :+} :+ : int : iwx_set_pslevel(struct iwx_softc *sc, int dtim, int level, int async) : { :@@ -6612,6 +6662,23 @@ iwx_set_pslevel(struct iwx_softc *sc, in : IWX_POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); : mcmd.rx_data_timeout = htole32(pmgt->rxtimeout * 1024); : mcmd.tx_data_timeout = htole32(pmgt->txtimeout * 1024); :+ if (ni->ni_uapsd && :+ (sc->sc_capaflags & IWX_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) { :+ mcmd.flags |= :+ htole16(IWX_POWER_FLAGS_ADVANCE_PM_ENA_MSK); :+ mcmd.flags |= :+ htole16(IWX_POWER_FLAGS_UAPSD_MISBEHAVING_ENA_MSK); :+ mcmd.rx_data_timeout_uapsd = :+ htole32(IWX_UAPSD_PS_RX_DATA_TIMEOUT); :+ mcmd.tx_data_timeout_uapsd = :+ htole32(IWX_UAPSD_PS_TX_DATA_TIMEOUT); :+ mcmd.qndp_tid = iwx_uapsd_qndp_tid(ic, ni->ni_uapsd_ac); :+ mcmd.uapsd_ac_flags = :+ ni->ni_uapsd_ac & :+ IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK; :+ mcmd.uapsd_max_sp = ni->ni_uapsd_maxsp & :+ IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK; :+ } : if (skip_dtim != 0) { : mcmd.flags |= htole16(IWX_POWER_FLAGS_SKIP_OVER_DTIM_MSK); : mcmd.skip_dtim_periods = skip_dtim + 1; :@@ -6770,6 +6837,12 @@ iwx_add_sta_cmd(struct iwx_softc *sc, st : break; : } : } :+ if (in->in_ni.ni_uapsd && :+ (sc->sc_capaflags & IWX_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) { :+ add_sta_cmd.modify_mask |= IWX_STA_MODIFY_UAPSD_ACS; :+ add_sta_cmd.uapsd_acs = iwx_uapsd_acs(&in->in_ni); :+ add_sta_cmd.sp_length = iwx_uapsd_sp_length(&in->in_ni); :+ } : : status = IWX_ADD_STA_SUCCESS; : err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA, sizeof(add_sta_cmd), :@@ -6976,6 +7049,12 @@ iwx_mld_add_sta_cmd(struct iwx_softc *sc : : if (in->in_ni.ni_flags & IEEE80211_NODE_MFP) : sta_cmd.mfp = htole32(1); :+ if (in->in_ni.ni_uapsd && :+ (sc->sc_capaflags & IWX_UCODE_TLV_FLAGS_UAPSD_SUPPORT)) { :+ sta_cmd.sp_length = :+ htole32(iwx_uapsd_sp_length(&in->in_ni)); :+ sta_cmd.uapsd_acs = htole32(iwx_uapsd_acs(&in->in_ni)); :+ } : : return iwx_send_cmd_pdu(sc, : IWX_WIDE_ID(IWX_MAC_CONF_GROUP, IWX_STA_CONFIG_CMD), :@@ -10977,6 +11056,32 @@ iwx_rx_pkt(struct iwx_softc *sc, struct : break; : } : :+ case IWX_PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION: { :+ struct ieee80211com *ic = &sc->sc_ic; :+ struct ifnet *ifp = &ic->ic_if; :+ struct ieee80211_node *ni = ic->ic_bss; :+ struct iwx_uapsd_misbehaving_ap_notif *notif; :+ :+ SYNC_RESP_STRUCT(notif, pkt); :+ :+ if (ni == NULL || !ni->ni_uapsd) :+ break; :+ :+ if (ifp->if_flags & IFF_DEBUG) :+ printf("%s: firmware reported uAPSD " :+ "misbehaving AP on sta %u, disabling " :+ "uAPSD\n", ifp->if_xname, :+ le32toh(notif->sta_id)); :+ :+ ni->ni_uapsd = 0; :+ ni->ni_uapsd_ac = 0; :+ ni->ni_uapsd_maxsp = 0; :+ :+ if (ic->ic_flags & IEEE80211_F_PMGTON) :+ (void)iwx_set_pslevel(sc, 0, 3, 1); :+ break; :+ } :+ : case IWX_WIDE_ID(IWX_MAC_CONF_GROUP, : IWX_SESSION_PROTECTION_NOTIF): { : struct iwx_session_prot_notif *notif; :@@ -12367,6 +12472,9 @@ iwx_attach(struct device *parent, struct : IEEE80211_C_SHPREAMBLE | /* short preamble supported */ : IEEE80211_C_MFP; /* management frame protection */ : ic->ic_flags |= IEEE80211_F_PMGTON; :+ ic->ic_uapsd_ac = IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | :+ IEEE80211_WMM_IE_STA_QOSINFO_AC_VO; :+ ic->ic_uapsd_maxsp = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL; : : ic->ic_htcaps = IEEE80211_HTCAP_SGI20 | IEEE80211_HTCAP_SGI40; : ic->ic_htcaps |= IEEE80211_HTCAP_CBW20_40; :Index: sys/dev/pci/if_iwxreg.h :=================================================================== :RCS file: /home/cvs/src/sys/dev/pci/if_iwxreg.h,v :diff -u -p -r1.73 if_iwxreg.h :--- sys/dev/pci/if_iwxreg.h 13 Mar 2026 11:11:02 -0000 1.73 :+++ sys/dev/pci/if_iwxreg.h 25 Mar 2026 00:25:41 -0000 :@@ -5472,6 +5472,8 @@ struct iwx_mac_power_cmd { : : #define IWX_DEFAULT_PS_TX_DATA_TIMEOUT (100 * 1000) : #define IWX_DEFAULT_PS_RX_DATA_TIMEOUT (100 * 1000) :+#define IWX_UAPSD_PS_TX_DATA_TIMEOUT (50 * 1000) :+#define IWX_UAPSD_PS_RX_DATA_TIMEOUT (50 * 1000) : : #define IWX_NDTIMRANGES 3 : #define IWX_NPOWERLEVELS 6 :@@ -8311,6 +8313,7 @@ struct iwx_umac_scan_iter_complete_notif : * @IWX_STA_MODIFY_QUEUE_REMOVAL: this command removes a queue : * @IWX_STA_MODIFY_TID_DISABLE_TX: this command modifies %tid_disable_tx : * @IWX_STA_MODIFY_TX_RATE: unused :+ * @IWX_STA_MODIFY_UAPSD_ACS: this command modifies %uapsd_acs : * @IWX_STA_MODIFY_ADD_BA_TID: this command modifies %add_immediate_ba_tid : * @IWX_STA_MODIFY_REMOVE_BA_TID: this command modifies %remove_immediate_ba_tid : * @IWX_STA_MODIFY_SLEEPING_STA_TX_COUNT: this command modifies %sleep_tx_count :@@ -8320,6 +8323,7 @@ struct iwx_umac_scan_iter_complete_notif : #define IWX_STA_MODIFY_QUEUE_REMOVAL (1 << 0) : #define IWX_STA_MODIFY_TID_DISABLE_TX (1 << 1) : #define IWX_STA_MODIFY_TX_RATE (1 << 2) :+#define IWX_STA_MODIFY_UAPSD_ACS IWX_STA_MODIFY_TX_RATE : #define IWX_STA_MODIFY_ADD_BA_TID (1 << 3) : #define IWX_STA_MODIFY_REMOVE_BA_TID (1 << 4) : #define IWX_STA_MODIFY_SLEEPING_STA_TX_COUNT (1 << 5) :Index: sys/net80211/ieee80211.h :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211.h,v :diff -u -p -r1.65 ieee80211.h :--- sys/net80211/ieee80211.h 19 Mar 2026 16:50:32 -0000 1.65 :+++ sys/net80211/ieee80211.h 25 Mar 2026 00:25:34 -0000 :@@ -193,6 +193,20 @@ struct ieee80211_htframe_addr4 { /* 11n : #define IEEE80211_QOS_EOSP 0x0010 : #define IEEE80211_QOS_TID 0x000f : :+#define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD 0x80 :+ :+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VO 0x01 :+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_VI 0x02 :+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BK 0x04 :+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_BE 0x08 :+#define IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK 0x0f :+ :+#define IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL 0x00 :+#define IEEE80211_WMM_IE_STA_QOSINFO_SP_2 0x20 :+#define IEEE80211_WMM_IE_STA_QOSINFO_SP_4 0x40 :+#define IEEE80211_WMM_IE_STA_QOSINFO_SP_6 0x60 :+#define IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK 0x60 :+ : /* : * Control frames. : */ :Index: sys/net80211/ieee80211_input.c :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211_input.c,v :diff -u -p -r1.260 ieee80211_input.c :--- sys/net80211/ieee80211_input.c 19 Mar 2026 16:50:32 -0000 1.260 :+++ sys/net80211/ieee80211_input.c 25 Mar 2026 00:25:41 -0000 :@@ -87,6 +87,7 @@ int ieee80211_parse_edca_params_body(str : const u_int8_t *); : int ieee80211_parse_edca_params(struct ieee80211com *, const u_int8_t *); : int ieee80211_parse_wmm_params(struct ieee80211com *, const u_int8_t *); :+int ieee80211_parse_wmm_qosinfo(const u_int8_t *, u_int8_t *); : enum ieee80211_cipher ieee80211_parse_rsn_cipher(const u_int8_t *); : enum ieee80211_akm ieee80211_parse_rsn_akm(const u_int8_t *); : int ieee80211_parse_rsn_body(struct ieee80211com *, const u_int8_t *, :@@ -1387,6 +1388,30 @@ ieee80211_parse_wmm_params(struct ieee80 : return ieee80211_parse_edca_params_body(ic, frm + 8); : } : :+int :+ieee80211_parse_wmm_qosinfo(const u_int8_t *frm, u_int8_t *qosinfo) :+{ :+ if (frm[1] < 7) :+ return IEEE80211_REASON_IE_INVALID; :+ :+ *qosinfo = frm[8]; :+ return 0; :+} :+ :+void :+ieee80211_setup_uapsd(struct ieee80211com *ic, struct ieee80211_node *ni, :+ int peer_uapsd) :+{ :+ ni->ni_uapsd = !!peer_uapsd; :+ if (ni->ni_uapsd && (ni->ni_flags & IEEE80211_NODE_QOS)) { :+ ni->ni_uapsd_ac = ic->ic_uapsd_ac; :+ ni->ni_uapsd_maxsp = ic->ic_uapsd_maxsp; :+ } else { :+ ni->ni_uapsd_ac = 0; :+ ni->ni_uapsd_maxsp = 0; :+ } :+} :+ : enum ieee80211_cipher : ieee80211_parse_rsn_cipher(const u_int8_t selector[4]) : { :@@ -1627,7 +1652,8 @@ ieee80211_recv_probe_resp(struct ieee802 : const u_int8_t *tstamp, *ssid, *rates, *xrates, *edcaie, *wmmie, *tim; : const u_int8_t *rsnie, *wpaie, *htcaps, *htop, *vhtcaps, *vhtop, *hecaps, *heop; : u_int16_t capinfo, bintval; :- u_int8_t chan, bchan, erp; :+ u_int8_t chan, bchan, erp, wmm_qosinfo; :+ int has_wmm_qosinfo = 0; : int is_new; : : /* :@@ -1845,6 +1871,9 @@ ieee80211_recv_probe_resp(struct ieee802 : ni->ni_dtimcount = tim[2]; : ni->ni_dtimperiod = tim[3]; : } :+ if (wmmie != NULL && :+ ieee80211_parse_wmm_qosinfo(wmmie, &wmm_qosinfo) == 0) :+ has_wmm_qosinfo = 1; : : /* : * When operating in station mode, check for state updates :@@ -1955,11 +1984,18 @@ ieee80211_recv_probe_resp(struct ieee802 : else : ni->ni_flags &= ~IEEE80211_NODE_QOS; : } :+ ieee80211_setup_uapsd(ic, ni, has_wmm_qosinfo && :+ (wmm_qosinfo & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)); : : if (ic->ic_state == IEEE80211_S_SCAN || : (ic->ic_flags & IEEE80211_F_BGSCAN)) { : struct ieee80211_rsnparams rsn, wpa; : :+ if (edcaie != NULL || wmmie != NULL) :+ ni->ni_flags |= IEEE80211_NODE_QOS; :+ else :+ ni->ni_flags &= ~IEEE80211_NODE_QOS; :+ : ni->ni_rsnprotos = IEEE80211_PROTO_NONE; : ni->ni_supported_rsnprotos = IEEE80211_PROTO_NONE; : ni->ni_rsnakms = 0; :@@ -1980,6 +2016,9 @@ ieee80211_recv_probe_resp(struct ieee802 : ni->ni_supported_rsnakms |= wpa.rsn_akms; : } : :+ ieee80211_setup_uapsd(ic, ni, has_wmm_qosinfo && :+ (wmm_qosinfo & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)); :+ : /* : * If the AP advertises both WPA and RSN IEs (WPA1+WPA2), : * we only use the highest protocol version we support. :@@ -2608,7 +2647,8 @@ ieee80211_recv_assoc_resp(struct ieee802 : const u_int8_t *rates, *xrates, *edcaie, *wmmie, *htcaps, *htop; : const u_int8_t *vhtcaps, *vhtop, *hecaps, *heop; : u_int16_t capinfo, status, associd; :- u_int8_t rate; :+ u_int8_t rate, wmm_qosinfo; :+ int has_wmm_qosinfo = 0; : : if (ic->ic_opmode != IEEE80211_M_STA || : ic->ic_state != IEEE80211_S_ASSOC) { :@@ -2696,6 +2736,9 @@ ieee80211_recv_assoc_resp(struct ieee802 : } : frm += 2 + frm[1]; : } :+ if (wmmie != NULL && :+ ieee80211_parse_wmm_qosinfo(wmmie, &wmm_qosinfo) == 0) :+ has_wmm_qosinfo = 1; : /* supported rates element is mandatory */ : if (rates == NULL || rates[1] > IEEE80211_RATE_MAXSIZE) { : DPRINTF(("invalid supported rates element\n")); :@@ -2724,6 +2767,8 @@ ieee80211_recv_assoc_resp(struct ieee802 : else /* for Reassociation */ : ni->ni_flags &= ~IEEE80211_NODE_QOS; : } :+ ieee80211_setup_uapsd(ic, ni, has_wmm_qosinfo && :+ (wmm_qosinfo & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD)); : if (htcaps) : ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]); : if (htop) :Index: sys/net80211/ieee80211_node.h :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211_node.h,v :diff -u -p -r1.99 ieee80211_node.h :--- sys/net80211/ieee80211_node.h 19 Mar 2026 16:50:32 -0000 1.99 :+++ sys/net80211/ieee80211_node.h 25 Mar 2026 00:25:42 -0000 :@@ -306,6 +306,9 @@ struct ieee80211_node { : /* power saving mode */ : u_int8_t ni_pwrsave; : struct mbuf_queue ni_savedq; /* packets queued for pspoll */ :+ u_int8_t ni_uapsd; :+ u_int8_t ni_uapsd_ac; :+ u_int8_t ni_uapsd_maxsp; : : /* RSN */ : struct timeout ni_eapol_to; :Index: sys/net80211/ieee80211_output.c :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211_output.c,v :diff -u -p -r1.147 ieee80211_output.c :--- sys/net80211/ieee80211_output.c 19 Mar 2026 16:50:32 -0000 1.147 :+++ sys/net80211/ieee80211_output.c 24 Mar 2026 23:47:29 -0000 :@@ -985,6 +985,13 @@ ieee80211_add_erp(u_int8_t *frm, struct : } : #endif /* IEEE80211_STA_ONLY */ : :+uint8_t :+ieee80211_uapsd_qosinfo(struct ieee80211com *ic) :+{ :+ return (ic->ic_uapsd_ac & IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) | :+ (ic->ic_uapsd_maxsp & IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK); :+} :+ : /* : * Add a QoS Capability element to a frame (see 7.3.2.35). : */ :@@ -993,7 +1000,7 @@ ieee80211_add_qos_capability(u_int8_t *f : { : *frm++ = IEEE80211_ELEMID_QOS_CAP; : *frm++ = 1; :- *frm++ = 0; /* QoS Info */ :+ *frm++ = ieee80211_uapsd_qosinfo(ic); : return frm; : } : :@@ -1011,7 +1018,7 @@ ieee80211_add_wme_info(uint8_t *frm, str : *frm++ = 2; /* OUI type */ : *frm++ = 0; /* OUI subtype */ : *frm++ = 1; /* version */ :- *frm++ = 0; /* info */ :+ *frm++ = ieee80211_uapsd_qosinfo(ic); : : return frm; : } :@@ -1585,7 +1592,7 @@ ieee80211_get_assoc_req(struct ieee80211 : struct mbuf *m; : u_int8_t *frm; : u_int16_t capinfo; :- int addvht = 0; :+ int addvht = 0, addwme; : u_int hecapslen = 0; : : if ((ic->ic_flags & IEEE80211_F_VHTON) && ni->ni_chan != NULL && :@@ -1601,6 +1608,9 @@ ieee80211_get_assoc_req(struct ieee80211 : IEEE80211_HE_MCS_NSS_SIZE(ic->ic_he_phy_cap[0]); : } : :+ addwme = (ni->ni_flags & IEEE80211_NODE_QOS) || :+ (ic->ic_flags & IEEE80211_F_HTON); :+ : m = ieee80211_getmgmt(M_DONTWAIT, MT_DATA, : 2 + 2 + : ((type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) ? :@@ -1616,7 +1626,8 @@ ieee80211_get_assoc_req(struct ieee80211 : (((ic->ic_flags & IEEE80211_F_RSNON) && : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ? : 2 + IEEE80211_WPAIE_MAXLEN : 0) + :- ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0) + :+ ((ic->ic_flags & IEEE80211_F_HTON) ? 28 : 0) + :+ (addwme ? 9 : 0) + : (addvht ? 14 : 0) + : hecapslen); : if (m == NULL) :@@ -1649,10 +1660,10 @@ ieee80211_get_assoc_req(struct ieee80211 : if ((ic->ic_flags & IEEE80211_F_RSNON) && : (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) : frm = ieee80211_add_wpa(frm, ic, ni); :- if (ic->ic_flags & IEEE80211_F_HTON) { :+ if (ic->ic_flags & IEEE80211_F_HTON) : frm = ieee80211_add_htcaps(frm, ic); :+ if (addwme) : frm = ieee80211_add_wme_info(frm, ic); :- } : if (addvht) : frm = ieee80211_add_vhtcaps(frm, ic); : if (hecapslen) :Index: sys/net80211/ieee80211_proto.c :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211_proto.c,v :diff -u -p -r1.112 ieee80211_proto.c :--- sys/net80211/ieee80211_proto.c 19 Mar 2026 16:50:32 -0000 1.112 :+++ sys/net80211/ieee80211_proto.c 24 Mar 2026 23:47:29 -0000 :@@ -1376,7 +1376,7 @@ justcleanup: : else : printf(" start %u%sMb", : rate / 2, (rate & 1) ? ".5" : ""); :- printf(" %s preamble %s slot time%s%s%s\n", :+ printf(" %s preamble %s slot time%s%s%s%s\n", : (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? : "short" : "long", : (ic->ic_flags & IEEE80211_F_SHSLOT) ? :@@ -1386,7 +1386,12 @@ justcleanup: : (ni->ni_flags & IEEE80211_NODE_HT) ? : " HT enabled" : "", : (ni->ni_flags & IEEE80211_NODE_VHT) ? :- " VHT enabled" : ""); :+ " VHT enabled" : "", :+ ic->ic_uapsd_ac != 0 ? :+ (ni->ni_uapsd ? :+ " uAPSD enabled" : :+ " uAPSD disabled") : :+ ""); : } : if (!(ic->ic_flags & IEEE80211_F_RSNON)) { : /* :Index: sys/net80211/ieee80211_var.h :=================================================================== :RCS file: /home/cvs/src/sys/net80211/ieee80211_var.h,v :diff -u -p -r1.114 ieee80211_var.h :--- sys/net80211/ieee80211_var.h 19 Mar 2026 16:50:32 -0000 1.114 :+++ sys/net80211/ieee80211_var.h 24 Mar 2026 23:47:29 -0000 :@@ -344,6 +344,8 @@ struct ieee80211com { : u_int ic_edca_txop_count[EDCA_NUM_AC]; : struct timeval ic_edca_txop_time[EDCA_NUM_AC]; : u_int16_t ic_tid_noack; :+ u_int8_t ic_uapsd_ac; :+ u_int8_t ic_uapsd_maxsp; : u_int8_t ic_globalcnt[EAPOL_KEY_NONCE_LEN]; : u_int8_t ic_nonce[EAPOL_KEY_NONCE_LEN]; : u_int8_t ic_psk[IEEE80211_PMK_LEN]; : : : :-- :wbr, Kirill : -- New crypt. See /usr/news/crypt.