Author: adrian
Date: Tue Jun 16 00:27:32 2020
New Revision: 362210
URL: https://svnweb.freebsd.org/changeset/base/362210

Log:
  [net80211] Add initial U-APSD negotiation support.
  
  U-APSD (unscheduled automatic power save delivery) is a power save method
  that's a bit better than legacy PS-POLL - stations can mark frames with
  an extra flag that tells the AP to leak out more frames after it sends
  its own frames rather than needing to send a PS-POLL to get another frame
  from the AP.
  
  Now, this code just handles the negotiation bits; it doesn't actually
  implement U-APSD.  That's up to drivers, and nothing in the tree yet
  implements this.  I /may/ implement this for ath(4) if I eventually care
  enough but right now I plan on just implementing it for firmware offload
  based NICs that handle this in the NIC.
  
  I'll commit the ifconfig bit after this and I may have some follow-up
  commits as this gets used more by me in local testing.
  
  This should be a glorious no-op for everyone else.  If things change
  for anyone that isn't fixed by a complete recompile then please reach out
  to me.

Modified:
  head/sys/net80211/_ieee80211.h
  head/sys/net80211/ieee80211.c
  head/sys/net80211/ieee80211_hostap.c
  head/sys/net80211/ieee80211_ioctl.c
  head/sys/net80211/ieee80211_ioctl.h
  head/sys/net80211/ieee80211_node.h
  head/sys/net80211/ieee80211_output.c
  head/sys/net80211/ieee80211_proto.c
  head/sys/net80211/ieee80211_sta.c
  head/sys/net80211/ieee80211_sta.h
  head/sys/net80211/ieee80211_var.h

Modified: head/sys/net80211/_ieee80211.h
==============================================================================
--- head/sys/net80211/_ieee80211.h      Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/_ieee80211.h      Tue Jun 16 00:27:32 2020        
(r362210)
@@ -488,6 +488,7 @@ struct ieee80211_mimo_info {
 #define        IEEE80211_C_MBSS        0x00040000      /* CAPABILITY: MBSS 
available */
 #define        IEEE80211_C_SWSLEEP     0x00080000      /* CAPABILITY: do sleep 
here */
 #define        IEEE80211_C_SWAMSDUTX   0x00100000      /* CAPABILITY: software 
A-MSDU TX */
+#define        IEEE80211_C_UAPSD       0x00200000      /* CAPABILITY: U-APSD */
 /* 0x7c0000 available */
 #define        IEEE80211_C_WPA1        0x00800000      /* CAPABILITY: WPA1 
avail */
 #define        IEEE80211_C_WPA2        0x01000000      /* CAPABILITY: WPA2 
avail */

Modified: head/sys/net80211/ieee80211.c
==============================================================================
--- head/sys/net80211/ieee80211.c       Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211.c       Tue Jun 16 00:27:32 2020        
(r362210)
@@ -616,6 +616,12 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ie
        if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
            (vap->iv_caps & IEEE80211_C_DFS))
                vap->iv_flags_ext |= IEEE80211_FEXT_DFS;
+       /* NB: only flip on U-APSD for hostap/sta for now */
+       if ((vap->iv_opmode == IEEE80211_M_STA)
+           || (vap->iv_opmode == IEEE80211_M_HOSTAP)) {
+               if (vap->iv_caps & IEEE80211_C_UAPSD)
+                       vap->iv_flags_ext |= IEEE80211_FEXT_UAPSD;
+       }
 
        vap->iv_des_chan = IEEE80211_CHAN_ANYC;         /* any channel is ok */
        vap->iv_bmissthreshold = IEEE80211_HWBMISS_DEFAULT;

Modified: head/sys/net80211/ieee80211_hostap.c
==============================================================================
--- head/sys/net80211/ieee80211_hostap.c        Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_hostap.c        Tue Jun 16 00:27:32 2020        
(r362210)
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
 #endif
 #include <net80211/ieee80211_wds.h>
 #include <net80211/ieee80211_vht.h>
+#include <net80211/ieee80211_sta.h> /* for parse_wmeie */
 
 #define        IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
 
@@ -2253,8 +2254,18 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbu
                                 * Mark node as capable of QoS.
                                 */
                                ni->ni_flags |= IEEE80211_NODE_QOS;
+                               if (ieee80211_parse_wmeie(wme, wh, ni) > 0) {
+                                       if (ni->ni_uapsd != 0)
+                                               ni->ni_flags |=
+                                                   IEEE80211_NODE_UAPSD;
+                                       else
+                                               ni->ni_flags &=
+                                                   ~IEEE80211_NODE_UAPSD;
+                               }
                        } else
-                               ni->ni_flags &= ~IEEE80211_NODE_QOS;
+                               ni->ni_flags &=
+                                   ~(IEEE80211_NODE_QOS |
+                                     IEEE80211_NODE_UAPSD);
 #ifdef IEEE80211_SUPPORT_SUPERG
                        if (ath != NULL) {
                                setie(ath_ie, ath - sfrm);
@@ -2268,6 +2279,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbu
 #undef setie
                } else {
                        ni->ni_flags &= ~IEEE80211_NODE_QOS;
+                       ni->ni_flags &= ~IEEE80211_NODE_UAPSD;
                        ni->ni_ath_flags = 0;
                }
                ieee80211_node_join(ni, resp);

Modified: head/sys/net80211/ieee80211_ioctl.c
==============================================================================
--- head/sys/net80211/ieee80211_ioctl.c Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_ioctl.c Tue Jun 16 00:27:32 2020        
(r362210)
@@ -1145,6 +1145,11 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_l
                if (vap->iv_flags_ht & IEEE80211_FHT_LDPC_RX)
                        ireq->i_val |= 2;
                break;
+       case IEEE80211_IOC_UAPSD:
+               ireq->i_val = 0;
+               if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD)
+                       ireq->i_val = 1;
+               break;
 
        /* VHT */
        case IEEE80211_IOC_VHTCONF:
@@ -3461,6 +3466,16 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_l
                /* NB: reset only if we're operating on an 11n channel */
                if (isvapht(vap))
                        error = ERESTART;
+               break;
+       case IEEE80211_IOC_UAPSD:
+               if ((vap->iv_caps & IEEE80211_C_UAPSD) == 0)
+                       return EOPNOTSUPP;
+               if (ireq->i_val == 0)
+                       vap->iv_flags_ext &= ~IEEE80211_FEXT_UAPSD;
+               else if (ireq->i_val == 1)
+                       vap->iv_flags_ext |= IEEE80211_FEXT_UAPSD;
+               else
+                       return EINVAL;
                break;
 
        /* VHT */

Modified: head/sys/net80211/ieee80211_ioctl.h
==============================================================================
--- head/sys/net80211/ieee80211_ioctl.h Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_ioctl.h Tue Jun 16 00:27:32 2020        
(r362210)
@@ -710,6 +710,8 @@ struct ieee80211req {
 #define        IEEE80211_IOC_GREENFIELD        112     /* Greenfield (on, off) 
*/
 #define        IEEE80211_IOC_STBC              113     /* STBC Tx/RX (on, off) 
*/
 #define        IEEE80211_IOC_LDPC              114     /* LDPC Tx/RX (on, off) 
*/
+#define        IEEE80211_IOC_UAPSD             115     /* UAPSD (on, off) */
+#define        IEEE80211_IOC_UAPSD_INFO        116     /* UAPSD (SP, per-AC 
enable) */
 
 /* VHT */
 #define        IEEE80211_IOC_VHTCONF           130     /* VHT config (off, on; 
widths) */

Modified: head/sys/net80211/ieee80211_node.h
==============================================================================
--- head/sys/net80211/ieee80211_node.h  Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_node.h  Tue Jun 16 00:27:32 2020        
(r362210)
@@ -146,6 +146,7 @@ struct ieee80211_node {
 #define        IEEE80211_NODE_AMSDU_TX 0x080000        /* AMSDU tx enabled */
 #define        IEEE80211_NODE_VHT      0x100000        /* VHT enabled */
 #define        IEEE80211_NODE_LDPC     0x200000        /* LDPC enabled */
+#define        IEEE80211_NODE_UAPSD    0x400000        /* U-APSD power save 
enabled */
        uint16_t                ni_associd;     /* association ID */
        uint16_t                ni_vlan;        /* vlan tag */
        uint16_t                ni_txpower;     /* current transmit power */
@@ -255,6 +256,9 @@ struct ieee80211_node {
        /* quiet time IE state for the given node */
        uint32_t                ni_quiet_ie_set;        /* Quiet time IE was 
seen */
        struct                  ieee80211_quiet_ie ni_quiet_ie; /* last seen 
quiet IE */
+
+       /* U-APSD */
+       uint8_t                 ni_uapsd;       /* U-APSD per-node flags 
matching WMM STA QoS Info field */
 
        uint64_t                ni_spare[3];
 };

Modified: head/sys/net80211/ieee80211_output.c
==============================================================================
--- head/sys/net80211/ieee80211_output.c        Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_output.c        Tue Jun 16 00:27:32 2020        
(r362210)
@@ -2156,26 +2156,48 @@ add_ie(uint8_t *frm, const uint8_t *ie)
  * Add a WME information element to a frame.
  */
 uint8_t *
-ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme)
+ieee80211_add_wme_info(uint8_t *frm, struct ieee80211_wme_state *wme,
+    struct ieee80211_node *ni)
 {
-       static const struct ieee80211_wme_info info = {
-               .wme_id         = IEEE80211_ELEMID_VENDOR,
-               .wme_len        = sizeof(struct ieee80211_wme_info) - 2,
-               .wme_oui        = { WME_OUI_BYTES },
-               .wme_type       = WME_OUI_TYPE,
-               .wme_subtype    = WME_INFO_OUI_SUBTYPE,
-               .wme_version    = WME_VERSION,
-               .wme_info       = 0,
-       };
-       memcpy(frm, &info, sizeof(info));
-       return frm + sizeof(info); 
+       static const uint8_t oui[4] = { WME_OUI_BYTES, WME_OUI_TYPE };
+       struct ieee80211vap *vap = ni->ni_vap;
+
+       *frm++ = IEEE80211_ELEMID_VENDOR;
+       *frm++ = sizeof(struct ieee80211_wme_info) - 2;
+       memcpy(frm, oui, sizeof(oui));
+       frm += sizeof(oui);
+       *frm++ = WME_INFO_OUI_SUBTYPE;
+       *frm++ = WME_VERSION;
+
+       /* QoS info field depends upon operating mode */
+       switch (vap->iv_opmode) {
+       case IEEE80211_M_HOSTAP:
+               *frm = wme->wme_bssChanParams.cap_info;
+               if (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD)
+                       *frm |= WME_CAPINFO_UAPSD_EN;
+               frm++;
+               break;
+       case IEEE80211_M_STA:
+               /*
+                * NB: UAPSD drivers must set this up in their
+                * VAP creation method.
+                */
+               *frm++ = vap->iv_uapsdinfo;
+               break;
+       default:
+               *frm++ = 0;
+               break;
+       }
+
+       return frm;
 }
 
 /*
  * Add a WME parameters element to a frame.
  */
 static uint8_t *
-ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme)
+ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme,
+    int uapsd_enable)
 {
 #define        SM(_v, _f)      (((_v) << _f##_S) & _f)
 #define        ADDSHORT(frm, v) do {   \
@@ -2195,8 +2217,12 @@ ieee80211_add_wme_param(uint8_t *frm, struct ieee80211
 
        memcpy(frm, &param, sizeof(param));
        frm += __offsetof(struct ieee80211_wme_info, wme_info);
-       *frm++ = wme->wme_bssChanParams.cap_info;       /* AC info */
+       *frm = wme->wme_bssChanParams.cap_info; /* AC info */
+       if (uapsd_enable)
+               *frm |= WME_CAPINFO_UAPSD_EN;
+       frm++;
        *frm++ = 0;                                     /* reserved field */
+       /* XXX TODO - U-APSD bits - SP, flags below */
        for (i = 0; i < WME_NUM_AC; i++) {
                const struct wmeParams *ac =
                       &wme->wme_bssChanParams.cap_wmeParams[i];
@@ -2789,7 +2815,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int typ
                frm = ieee80211_add_wpa(frm, vap);
                if ((ic->ic_flags & IEEE80211_F_WME) &&
                    ni->ni_ies.wme_ie != NULL)
-                       frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
+                       frm = ieee80211_add_wme_info(frm, &ic->ic_wme, ni);
 
                /*
                 * Same deal - only send HT info if we're on an 11n
@@ -2881,7 +2907,8 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int typ
                }
                if ((vap->iv_flags & IEEE80211_F_WME) &&
                    ni->ni_ies.wme_ie != NULL)
-                       frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
+                       frm = ieee80211_add_wme_param(frm, &ic->ic_wme,
+                           !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD));
                if ((ni->ni_flags & HTFLAGS) == HTFLAGS) {
                        frm = ieee80211_add_htcap_vendor(frm, ni);
                        frm = ieee80211_add_htinfo_vendor(frm, ni);
@@ -3092,7 +3119,8 @@ ieee80211_alloc_proberesp(struct ieee80211_node *bss, 
        }
        frm = ieee80211_add_wpa(frm, vap);
        if (vap->iv_flags & IEEE80211_F_WME)
-               frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
+               frm = ieee80211_add_wme_param(frm, &ic->ic_wme,
+                   !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD));
        if (IEEE80211_IS_CHAN_HT(bss->ni_chan) &&
            (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT) &&
            legacy != IEEE80211_SEND_LEGACY_11B) {
@@ -3490,7 +3518,8 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *fr
        frm = ieee80211_add_wpa(frm, vap);
        if (vap->iv_flags & IEEE80211_F_WME) {
                bo->bo_wme = frm;
-               frm = ieee80211_add_wme_param(frm, &ic->ic_wme);
+               frm = ieee80211_add_wme_param(frm, &ic->ic_wme,
+                   !! (vap->iv_flags_ext & IEEE80211_FEXT_UAPSD));
        }
        if (IEEE80211_IS_CHAN_HT(ni->ni_chan) &&
            (vap->iv_flags_ht & IEEE80211_FHT_HTCOMPAT)) {
@@ -3782,7 +3811,8 @@ ieee80211_beacon_update(struct ieee80211_node *ni, str
                                        wme->wme_hipri_switch_hysteresis;
                }
                if (isset(bo->bo_flags, IEEE80211_BEACON_WME)) {
-                       (void) ieee80211_add_wme_param(bo->bo_wme, wme);
+                       (void) ieee80211_add_wme_param(bo->bo_wme, wme,
+                         vap->iv_flags_ext & IEEE80211_FEXT_UAPSD);
                        clrbit(bo->bo_flags, IEEE80211_BEACON_WME);
                }
        }

Modified: head/sys/net80211/ieee80211_proto.c
==============================================================================
--- head/sys/net80211/ieee80211_proto.c Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_proto.c Tue Jun 16 00:27:32 2020        
(r362210)
@@ -1147,8 +1147,11 @@ ieee80211_wme_initparams_locked(struct ieee80211vap *v
         * field and updates hardware when said field changes.
         * Otherwise the hardware is programmed with defaults, not what
         * the beacon actually announces.
+        *
+        * Note that we can't ever have 0xff as an actual value;
+        * the only valid values are 0..15.
         */
-       wme->wme_wmeChanParams.cap_info = 0;
+       wme->wme_wmeChanParams.cap_info = 0xfe;
 
        /*
         * Select mode; we can be called early in which case we

Modified: head/sys/net80211/ieee80211_sta.c
==============================================================================
--- head/sys/net80211/ieee80211_sta.c   Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_sta.c   Tue Jun 16 00:27:32 2020        
(r362210)
@@ -1129,25 +1129,56 @@ bad:
                    IEEE80211_SCAN_FAIL_STATUS);
 }
 
+/*
+ * Parse the WME IE for QoS and U-APSD information.
+ *
+ * Returns -1 if the IE isn't found, 1 if it's found.
+ */
 int
+ieee80211_parse_wmeie(uint8_t *frm, const struct ieee80211_frame *wh,
+    struct ieee80211_node *ni)
+{
+       u_int len = frm[1];
+
+       ni->ni_uapsd = 0;
+
+       if (len < sizeof(struct ieee80211_wme_param)-2) {
+               IEEE80211_DISCARD_IE(ni->ni_vap,
+                   IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,
+                   wh, "WME", "too short, len %u", len);
+               return -1;
+       }
+
+       ni->ni_uapsd = frm[WME_CAPINFO_IE_OFFSET];
+
+       IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_POWER | IEEE80211_MSG_ASSOC,
+           ni, "U-APSD settings from STA: 0x%02x", ni->ni_uapsd);
+
+       return 1;
+}
+
+int
 ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm,
-       const struct ieee80211_frame *wh)
+       const struct ieee80211_frame *wh, uint8_t *qosinfo)
 {
 #define        MS(_v, _f)      (((_v) & _f) >> _f##_S)
        struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;
-       u_int len = frm[1], qosinfo;
+       u_int len = frm[1], qosinfo_count;
        int i;
 
+       *qosinfo = 0;
+
        if (len < sizeof(struct ieee80211_wme_param)-2) {
                IEEE80211_DISCARD_IE(vap,
                    IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,
                    wh, "WME", "too short, len %u", len);
                return -1;
        }
-       qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)];
-       qosinfo &= WME_QOSINFO_COUNT;
+       *qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)];
+       qosinfo_count = *qosinfo & WME_QOSINFO_COUNT;
+
        /* XXX do proper check for wraparound */
-       if (qosinfo == wme->wme_wmeChanParams.cap_info)
+       if (qosinfo_count == wme->wme_wmeChanParams.cap_info)
                return 0;
        frm += __offsetof(struct ieee80211_wme_param, params_acParams);
        for (i = 0; i < WME_NUM_AC; i++) {
@@ -1159,9 +1190,18 @@ ieee80211_parse_wmeparams(struct ieee80211vap *vap, ui
                wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN);
                wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX);
                wmep->wmep_txopLimit = le16dec(frm+2);
+               IEEE80211_DPRINTF(vap, IEEE80211_MSG_WME,
+                   "%s: WME: %d: acm=%d aifsn=%d logcwmin=%d logcwmax=%d 
txopLimit=%d\n",
+                   __func__,
+                   i,
+                   wmep->wmep_acm,
+                   wmep->wmep_aifsn,
+                   wmep->wmep_logcwmin,
+                   wmep->wmep_logcwmax,
+                   wmep->wmep_txopLimit);
                frm += 4;
        }
-       wme->wme_wmeChanParams.cap_info = qosinfo;
+       wme->wme_wmeChanParams.cap_info = qosinfo_count;
        return 1;
 #undef MS
 }
@@ -1350,11 +1390,12 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
        struct ieee80211com *ic = ni->ni_ic;
        struct ieee80211_channel *rxchan = ic->ic_curchan;
        struct ieee80211_frame *wh;
+       int ht_state_change = 0, do_ht = 0;
        uint8_t *frm, *efrm;
        uint8_t *rates, *xrates, *wme, *htcap, *htinfo;
        uint8_t *vhtcap, *vhtopmode;
        uint8_t rate;
-       int ht_state_change = 0, do_ht = 0;
+       uint8_t qosinfo;
 
        wh = mtod(m0, struct ieee80211_frame *);
        frm = (uint8_t *)&wh[1];
@@ -1443,9 +1484,18 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
                                /* XXX statistic */
                        }
                        if (scan.wme != NULL &&
-                           (ni->ni_flags & IEEE80211_NODE_QOS) &&
-                           ieee80211_parse_wmeparams(vap, scan.wme, wh) > 0)
-                               ieee80211_wme_updateparams(vap);
+                           (ni->ni_flags & IEEE80211_NODE_QOS)) {
+                               int _retval;
+                               if ((_retval = ieee80211_parse_wmeparams(vap,
+                                   scan.wme, wh, &qosinfo)) >= 0) {
+                                       if (qosinfo & WME_CAPINFO_UAPSD_EN)
+                                               ni->ni_flags |=
+                                                   IEEE80211_NODE_UAPSD;
+                                       if (_retval > 0)
+                                               ieee80211_wme_updateparams(vap);
+                               }
+                       } else
+                               ni->ni_flags &= ~IEEE80211_NODE_UAPSD;
 #ifdef IEEE80211_SUPPORT_SUPERG
                        if (scan.ath != NULL)
                                ieee80211_parse_athparams(ni, scan.ath, wh);
@@ -1782,7 +1832,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *
                if (ni->ni_jointime == 0)
                        ni->ni_jointime = time_uptime;
                if (wme != NULL &&
-                   ieee80211_parse_wmeparams(vap, wme, wh) >= 0) {
+                   ieee80211_parse_wmeparams(vap, wme, wh, &qosinfo) >= 0) {
                        ni->ni_flags |= IEEE80211_NODE_QOS;
                        ieee80211_wme_updateparams(vap);
                } else

Modified: head/sys/net80211/ieee80211_sta.h
==============================================================================
--- head/sys/net80211/ieee80211_sta.h   Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_sta.h   Tue Jun 16 00:27:32 2020        
(r362210)
@@ -40,5 +40,12 @@ void ieee80211_sta_vattach(struct ieee80211vap *);
  * Used by the adhoc/mesh/tdma paths.
  */
 extern int ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm,
-           const struct ieee80211_frame *wh);
+           const struct ieee80211_frame *wh, uint8_t *qosinfo);
+
+/*
+ * Used in the hostap path.
+ */
+extern int ieee80211_parse_wmeie(uint8_t *frm,
+           const struct ieee80211_frame *wh, struct ieee80211_node *ni);
+
 #endif /* !_NET80211_IEEE80211_STA_H_ */

Modified: head/sys/net80211/ieee80211_var.h
==============================================================================
--- head/sys/net80211/ieee80211_var.h   Mon Jun 15 22:43:46 2020        
(r362209)
+++ head/sys/net80211/ieee80211_var.h   Tue Jun 16 00:27:32 2020        
(r362210)
@@ -581,6 +581,9 @@ struct ieee80211vap {
        void                    (*iv_updateslot)(struct ieee80211vap *);
        struct task             iv_slot_task;   /* deferred slot time update */
 
+       /* per-vap U-APSD state */
+       uint8_t                 iv_uapsdinfo;   /* sta mode QoS Info flags */
+
        uint64_t                iv_spare[6];
 };
 MALLOC_DECLARE(M_80211_VAP);
@@ -662,6 +665,7 @@ MALLOC_DECLARE(M_80211_VAP);
 #define        IEEE80211_FEXT_FRAG_OFFLOAD     0x00200000      /* CONF: 
hardware does 802.11 fragmentation + assignment */
 #define        IEEE80211_FEXT_VHT      0x00400000      /* CONF: VHT support */
 #define        IEEE80211_FEXT_QUIET_IE 0x00800000      /* STATUS: quiet IE in 
a beacon has been added */
+#define        IEEE80211_FEXT_UAPSD    0x01000000      /* CONF: enable U-APSD 
*/
 
 #define        IEEE80211_FEXT_BITS \
        "\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to