diff options
Diffstat (limited to 'sys/net80211/ieee80211_output.c')
-rw-r--r-- | sys/net80211/ieee80211_output.c | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index c71f8541085bf..09a9b00668a07 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$"); #endif #include <net80211/ieee80211_wds.h> #include <net80211/ieee80211_mesh.h> +#include <net80211/ieee80211_vht.h> #if defined(INET) || defined(INET6) #include <netinet/in.h> @@ -764,6 +765,16 @@ ieee80211_send_setup( } *(uint16_t *)&wh->i_dur[0] = 0; + /* + * XXX TODO: this is what the TX lock is for. + * Here we're incrementing sequence numbers, and they + * need to be in lock-step with what the driver is doing + * both in TX ordering and crypto encap (IV increment.) + * + * If the driver does seqno itself, then we can skip + * assigning sequence numbers here, and we can avoid + * requiring the TX lock. + */ tap = &ni->ni_tx_ampdu[tid]; if (tid != IEEE80211_NONQOS_TID && IEEE80211_AMPDU_RUNNING(tap)) m->m_flags |= M_AMPDU_MPDU; @@ -1542,6 +1553,11 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, if (is_amsdu) qos[0] |= IEEE80211_QOS_AMSDU; + /* + * XXX TODO TX lock is needed for atomic updates of sequence + * numbers. If the driver does it, then don't do it here; + * and we don't need the TX lock held. + */ if ((m->m_flags & M_AMPDU_MPDU) == 0) { /* * NB: don't assign a sequence # to potential @@ -1561,6 +1577,11 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, M_SEQNO_SET(m, seqno); } } else { + /* + * XXX TODO TX lock is needed for atomic updates of sequence + * numbers. If the driver does it, then don't do it here; + * and we don't need the TX lock held. + */ seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++; *(uint16_t *)wh->i_seq = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); @@ -2065,6 +2086,7 @@ ieee80211_add_qos(uint8_t *frm, const struct ieee80211_node *ni) * Send a probe request frame with the specified ssid * and any optional information element data. */ +/* XXX VHT? */ int ieee80211_send_probereq(struct ieee80211_node *ni, const uint8_t sa[IEEE80211_ADDR_LEN], @@ -2111,6 +2133,7 @@ ieee80211_send_probereq(struct ieee80211_node *ni, * [tlv] RSN (optional) * [tlv] extended supported rates * [tlv] HT cap (optional) + * [tlv] VHT cap (optional) * [tlv] WPA (optional) * [tlv] user-specified ie's */ @@ -2119,7 +2142,8 @@ ieee80211_send_probereq(struct ieee80211_node *ni, 2 + IEEE80211_NWID_LEN + 2 + IEEE80211_RATE_SIZE + sizeof(struct ieee80211_ie_htcap) - + sizeof(struct ieee80211_ie_htinfo) + + sizeof(struct ieee80211_ie_vhtcap) + + sizeof(struct ieee80211_ie_htinfo) /* XXX not needed? */ + sizeof(struct ieee80211_ie_wpa) + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_ie_wpa) @@ -2159,6 +2183,21 @@ ieee80211_send_probereq(struct ieee80211_node *ni, frm = ieee80211_add_htcap_ch(frm, vap, c); } + /* + * XXX TODO: need to figure out what/how to update the + * VHT channel. + */ +#if 0 + (vap->iv_flags_vht & IEEE80211_FVHT_VHT) { + struct ieee80211_channel *c; + + c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, + vap->iv_flags_ht); + c = ieee80211_vht_adjust_channel(ic, c, vap->iv_flags_vht); + frm = ieee80211_add_vhtcap_ch(frm, vap, c); + } +#endif + frm = ieee80211_add_wpa(frm, vap); if (vap->iv_appie_probereq != NULL) frm = add_appie(frm, vap->iv_appie_probereq); @@ -2357,6 +2396,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: + /* XXX VHT? */ /* * asreq frame format * [2] capability information @@ -2368,6 +2408,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) * [4] power capability (optional) * [28] supported channels (optional) * [tlv] HT capabilities + * [tlv] VHT capabilities * [tlv] WME (optional) * [tlv] Vendor OUI HT capabilities (optional) * [tlv] Atheros capabilities (if negotiated) @@ -2385,6 +2426,7 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) + 2 + 26 + sizeof(struct ieee80211_wme_info) + sizeof(struct ieee80211_ie_htcap) + + sizeof(struct ieee80211_ie_vhtcap) + 4 + sizeof(struct ieee80211_ie_htcap) #ifdef IEEE80211_SUPPORT_SUPERG + sizeof(struct ieee80211_ath_ie) @@ -2449,6 +2491,14 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_HTCAP) { frm = ieee80211_add_htcap(frm, ni); } + + if ((vap->iv_flags_vht & IEEE80211_FVHT_VHT) && + IEEE80211_IS_CHAN_VHT(ni->ni_chan) && + ni->ni_ies.vhtcap_ie != NULL && + ni->ni_ies.vhtcap_ie[0] == IEEE80211_ELEMID_VHT_CAP) { + frm = ieee80211_add_vhtcap(frm, ni); + } + frm = ieee80211_add_wpa(frm, vap); if ((ic->ic_flags & IEEE80211_F_WME) && ni->ni_ies.wme_ie != NULL) @@ -2492,6 +2542,8 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) * [tlv] extended supported rates * [tlv] HT capabilities (standard, if STA enabled) * [tlv] HT information (standard, if STA enabled) + * [tlv] VHT capabilities (standard, if STA enabled) + * [tlv] VHT information (standard, if STA enabled) * [tlv] WME (if configured and STA enabled) * [tlv] HT capabilities (vendor OUI, if STA enabled) * [tlv] HT information (vendor OUI, if STA enabled) @@ -2507,6 +2559,8 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) + sizeof(struct ieee80211_ie_htcap) + 4 + sizeof(struct ieee80211_ie_htinfo) + 4 + + sizeof(struct ieee80211_ie_vhtcap) + + sizeof(struct ieee80211_ie_vht_operation) + sizeof(struct ieee80211_wme_param) #ifdef IEEE80211_SUPPORT_SUPERG + sizeof(struct ieee80211_ath_ie) @@ -2545,6 +2599,10 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg) frm = ieee80211_add_htcap_vendor(frm, ni); frm = ieee80211_add_htinfo_vendor(frm, ni); } + if (ni->ni_flags & IEEE80211_NODE_VHT) { + frm = ieee80211_add_vhtcap(frm, ni); + frm = ieee80211_add_vhtinfo(frm, ni); + } #ifdef IEEE80211_SUPPORT_SUPERG if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS)) frm = ieee80211_add_ath(frm, @@ -2600,6 +2658,7 @@ bad: * Space is left to prepend and 802.11 header at the * front but it's left to the caller to fill in. */ +/* XXX VHT? */ struct mbuf * ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy) { @@ -2934,6 +2993,7 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status) } } +/* XXX VHT? */ static void ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, struct ieee80211_node *ni) @@ -2946,6 +3006,10 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, /* * beacon frame format + * + * TODO: update to 802.11-2012; a lot of stuff has changed; + * vendor extensions should be at the end, etc. + * * [8] time stamp * [2] beacon interval * [2] cabability information @@ -2957,11 +3021,34 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, * [tlv] country (optional) * [3] power control (optional) * [5] channel switch announcement (CSA) (optional) + * XXX TODO: Quiet + * XXX TODO: IBSS DFS + * XXX TODO: TPC report * [tlv] extended rate phy (ERP) * [tlv] extended supported rates * [tlv] RSN parameters + * XXX TODO: BSSLOAD + * (XXX EDCA parameter set, QoS capability?) + * XXX TODO: AP channel report + * * [tlv] HT capabilities * [tlv] HT information + * XXX TODO: 20/40 BSS coexistence + * Mesh: + * XXX TODO: Meshid + * XXX TODO: mesh config + * XXX TODO: mesh awake window + * XXX TODO: beacon timing (mesh, etc) + * XXX TODO: MCCAOP Advertisement Overview + * XXX TODO: MCCAOP Advertisement + * XXX TODO: Mesh channel switch parameters + * VHT: + * XXX TODO: VHT capabilities + * XXX TODO: VHT operation + * XXX TODO: VHT transmit power envelope + * XXX TODO: channel switch wrapper element + * XXX TODO: extended BSS load element + * * XXX Vendor-specific OIDs (e.g. Atheros) * [tlv] WPA parameters * [tlv] WME parameters @@ -3055,6 +3142,16 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, bo->bo_htinfo = frm; frm = ieee80211_add_htinfo(frm, ni); } + + if (IEEE80211_IS_CHAN_VHT(ni->ni_chan)) { + frm = ieee80211_add_vhtcap(frm, ni); + bo->bo_vhtinfo = frm; + frm = ieee80211_add_vhtinfo(frm, ni); + /* Transmit power envelope */ + /* Channel switch wrapper element */ + /* Extended bss load element */ + } + frm = ieee80211_add_wpa(frm, vap); if (vap->iv_flags & IEEE80211_F_WME) { bo->bo_wme = frm; @@ -3065,6 +3162,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, frm = ieee80211_add_htcap_vendor(frm, ni); frm = ieee80211_add_htinfo_vendor(frm, ni); } + #ifdef IEEE80211_SUPPORT_SUPERG if (vap->iv_flags & IEEE80211_F_ATHEROS) { bo->bo_ath = frm; @@ -3082,6 +3180,8 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, bo->bo_appie_len = vap->iv_appie_beacon->ie_len; frm = add_appie(frm, vap->iv_appie_beacon); } + + /* XXX TODO: move meshid/meshconf up to before vendor extensions? */ #ifdef IEEE80211_SUPPORT_MESH if (vap->iv_opmode == IEEE80211_M_MBSS) { frm = ieee80211_add_meshid(frm, vap); @@ -3097,6 +3197,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm, /* * Allocate a beacon frame and fillin the appropriate bits. */ +/* XXX VHT? */ struct mbuf * ieee80211_beacon_alloc(struct ieee80211_node *ni) { @@ -3110,6 +3211,9 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni) /* * beacon frame format + * + * Note: This needs updating for 802.11-2012. + * * [8] time stamp * [2] beacon interval * [2] cabability information @@ -3126,6 +3230,8 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni) * [tlv] RSN parameters * [tlv] HT capabilities * [tlv] HT information + * [tlv] VHT capabilities + * [tlv] VHT operation * [tlv] Vendor OUI HT capabilities (optional) * [tlv] Vendor OUI HT information (optional) * XXX Vendor-specific OIDs (e.g. Atheros) @@ -3138,6 +3244,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni) * NB: we allocate the max space required for the TIM bitmap. * XXX how big is this? */ + /* XXX VHT? */ pktlen = 8 /* time stamp */ + sizeof(uint16_t) /* beacon interval */ + sizeof(uint16_t) /* capabilities */ @@ -3157,6 +3264,8 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni) /* XXX conditional? */ + 4+2*sizeof(struct ieee80211_ie_htcap)/* HT caps */ + 4+2*sizeof(struct ieee80211_ie_htinfo)/* HT info */ + + sizeof(struct ieee80211_ie_vhtcap)/* VHT caps */ + + sizeof(struct ieee80211_ie_vht_operation)/* VHT info */ + (vap->iv_caps & IEEE80211_C_WME ? /* WME */ sizeof(struct ieee80211_wme_param) : 0) #ifdef IEEE80211_SUPPORT_SUPERG @@ -3242,6 +3351,15 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) } wh = mtod(m, struct ieee80211_frame *); + + /* + * XXX TODO Strictly speaking this should be incremented with the TX + * lock held so as to serialise access to the non-qos TID sequence + * number space. + * + * If the driver identifies it does its own TX seqno management then + * we can skip this (and still not do the TX seqno.) + */ seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++; *(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); @@ -3347,6 +3465,10 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) timoff = 0; timlen = 1; } + + /* + * TODO: validate this! + */ if (timlen != bo->bo_tim_len) { /* copy up/down trailer */ int adjust = tie->tim_bitmap+timlen @@ -3357,6 +3479,7 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) bo->bo_tim_trailer += adjust; bo->bo_erp += adjust; bo->bo_htinfo += adjust; + bo->bo_vhtinfo += adjust; #ifdef IEEE80211_SUPPORT_SUPERG bo->bo_ath += adjust; #endif @@ -3411,6 +3534,7 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) memmove(&csa[1], csa, bo->bo_csa_trailer_len); bo->bo_erp += sizeof(*csa); bo->bo_htinfo += sizeof(*csa); + bo->bo_vhtinfo += sizeof(*csa); bo->bo_wme += sizeof(*csa); #ifdef IEEE80211_SUPPORT_SUPERG bo->bo_ath += sizeof(*csa); |