summaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net80211/ieee80211_output.c')
-rw-r--r--sys/net80211/ieee80211_output.c126
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);