On 12/12/15(Sat) 11:34, Stefan Sperling wrote: > Some APs will not negotiate 11n (aka HT) if the vendor-specific WME > (Wireless Multimedia Extensions) info element is missing in probe > and association requests. WME info essentially tells the other end > that we're QoS capable, which is a requirement for 11n (e.g. A-MPDUs > are sent in QoS data frames). > The 802.11-2012 standard defines other ways of indicating QoS support > which we already use. WME is not part of this standard but I'm adding > it for interoperability. FreeBSD and Linux send a WME info element, too. > Since this is an ugly vendor-specific element I decided to use magic > numbers instead of IEEE80211_ defines. I have no document explaining > what these numbers really mean, and Linux and FreeBSD use different > terminology. I put the names FreeBSD uses in comments. > > Also, fix bugs where the wrong flag was checked to determine whether > 11n-related elements should be included in management frames. > If 11n mode is enabled (F_HTON flag) we can always include 11n related > elements in management frames we send out, regardless of whether the > other STAs or APs support 11n. > The NODE_HT flag is only set once HT has been negotiated with a peer, > i.e. after exchanging assoc request and response with the AP. > Checking this flag earlier, e.g. in ieee80211_get_assoc_resp(), is wrong.
ok mpi@ > Index: net80211/ieee80211_output.c > =================================================================== > RCS file: /cvs/src/sys/net80211/ieee80211_output.c,v > retrieving revision 1.101 > diff -u -p -r1.101 ieee80211_output.c > --- net80211/ieee80211_output.c 24 Nov 2015 12:32:53 -0000 1.101 > +++ net80211/ieee80211_output.c 12 Dec 2015 10:12:58 -0000 > @@ -94,6 +94,7 @@ struct mbuf *ieee80211_get_addba_resp(st > struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t); > struct mbuf *ieee80211_get_delba(struct ieee80211com *, > struct ieee80211_node *, u_int8_t, u_int8_t, u_int16_t); > +uint8_t *ieee80211_add_wme_info(uint8_t *, struct ieee80211com *); > #endif > struct mbuf *ieee80211_get_sa_query(struct ieee80211com *, > struct ieee80211_node *, u_int8_t); > @@ -831,6 +832,26 @@ ieee80211_add_qos_capability(u_int8_t *f > return frm; > } > > +#ifndef IEEE80211_NO_HT > +/* > + * Add a Wifi-Alliance WME (aka WMM) info element to a frame. > + * WME is a requirement for Wifi-Alliance compliance and some > + * 11n APs will not negotiate HT if this element is missing. > + */ > +uint8_t * > +ieee80211_add_wme_info(uint8_t *frm, struct ieee80211com *ic) > +{ > + *frm++ = IEEE80211_ELEMID_VENDOR; > + *frm++ = 7; > + memcpy(frm, MICROSOFT_OUI, 3); frm += 3; > + *frm++ = 2; /* OUI type */ > + *frm++ = 0; /* OUI subtype */ > + *frm++ = 1; /* version */ > + *frm++ = 0; /* info */ > + > + return frm; > +} > +#endif > /* > * Add an RSN element to a frame (see 802.11-2012 8.4.2.27) > */ > @@ -1097,7 +1118,7 @@ ieee80211_get_probe_req(struct ieee80211 > 2 + min(rs->rs_nrates, IEEE80211_RATE_SIZE) + > ((rs->rs_nrates > IEEE80211_RATE_SIZE) ? > 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) + > - ((ni->ni_flags & IEEE80211_NODE_HT) ? 28 : 0)); > + ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0)); > if (m == NULL) > return NULL; > > @@ -1107,8 +1128,10 @@ ieee80211_get_probe_req(struct ieee80211 > if (rs->rs_nrates > IEEE80211_RATE_SIZE) > frm = ieee80211_add_xrates(frm, rs); > #ifndef IEEE80211_NO_HT > - if (ni->ni_flags & IEEE80211_NODE_HT) > + if (ic->ic_flags & IEEE80211_F_HTON) { > frm = ieee80211_add_htcaps(frm, ic); > + frm = ieee80211_add_wme_info(frm, ic); > + } > #endif > > m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); > @@ -1278,7 +1301,7 @@ ieee80211_get_assoc_req(struct ieee80211 > (((ic->ic_flags & IEEE80211_F_RSNON) && > (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) ? > 2 + IEEE80211_WPAIE_MAXLEN : 0) + > - ((ni->ni_flags & IEEE80211_NODE_HT) ? 28 : 0)); > + ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 9 : 0)); > if (m == NULL) > return NULL; > > @@ -1310,8 +1333,10 @@ ieee80211_get_assoc_req(struct ieee80211 > (ni->ni_rsnprotos & IEEE80211_PROTO_WPA)) > frm = ieee80211_add_wpa(frm, ic, ni); > #ifndef IEEE80211_NO_HT > - if (ni->ni_flags & IEEE80211_NODE_HT) > + if (ic->ic_flags & IEEE80211_F_HTON) { > frm = ieee80211_add_htcaps(frm, ic); > + frm = ieee80211_add_wme_info(frm, ic); > + } > #endif > > m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *); > @@ -1347,7 +1372,7 @@ ieee80211_get_assoc_resp(struct ieee8021 > 2 + rs->rs_nrates - IEEE80211_RATE_SIZE : 0) + > ((ni->ni_flags & IEEE80211_NODE_QOS) ? 2 + 18 : 0) + > ((status == IEEE80211_STATUS_TRY_AGAIN_LATER) ? 2 + 7 : 0) + > - ((ni->ni_flags & IEEE80211_NODE_HT) ? 28 + 24 : 0)); > + ((ic->ic_flags & IEEE80211_F_HTON) ? 28 + 24 : 0)); > if (m == NULL) > return NULL; > > @@ -1370,7 +1395,7 @@ ieee80211_get_assoc_resp(struct ieee8021 > frm = ieee80211_add_tie(frm, 3, 1000 /* XXX */); > } > #ifndef IEEE80211_NO_HT > - if (ni->ni_flags & IEEE80211_NODE_HT) { > + if (ic->ic_flags & IEEE80211_F_HTON) { > frm = ieee80211_add_htcaps(frm, ic); > frm = ieee80211_add_htop(frm, ic); > } > >