diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-20 15:53:03 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:39 +0200 |
commit | 18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d (patch) | |
tree | a3020ac5b1f366f2f0920941b589808e435dbcee /freebsd/sys/net80211 | |
parent | Update to FreeBSD head 2017-12-01 (diff) | |
download | rtems-libbsd-18fa92c2dcc6c52e0bf27d214d80f0c25a89b47d.tar.bz2 |
Update to FreeBSD head 2018-02-01
Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.
Update #3472.
Diffstat (limited to 'freebsd/sys/net80211')
-rw-r--r-- | freebsd/sys/net80211/ieee80211_ht.c | 2 | ||||
-rw-r--r-- | freebsd/sys/net80211/ieee80211_node.c | 7 | ||||
-rw-r--r-- | freebsd/sys/net80211/ieee80211_output.c | 143 | ||||
-rw-r--r-- | freebsd/sys/net80211/ieee80211_proto.c | 32 | ||||
-rw-r--r-- | freebsd/sys/net80211/ieee80211_proto.h | 1 | ||||
-rw-r--r-- | freebsd/sys/net80211/ieee80211_scan_sta.c | 2 |
6 files changed, 156 insertions, 31 deletions
diff --git a/freebsd/sys/net80211/ieee80211_ht.c b/freebsd/sys/net80211/ieee80211_ht.c index 21d85fb3..c6a3a200 100644 --- a/freebsd/sys/net80211/ieee80211_ht.c +++ b/freebsd/sys/net80211/ieee80211_ht.c @@ -3356,7 +3356,7 @@ ieee80211_add_htinfo_body(uint8_t *frm, struct ieee80211_node *ni) } /* - * Add 802.11n HT information information element. + * Add 802.11n HT information element. */ uint8_t * ieee80211_add_htinfo(uint8_t *frm, struct ieee80211_node *ni) diff --git a/freebsd/sys/net80211/ieee80211_node.c b/freebsd/sys/net80211/ieee80211_node.c index 023fb128..45d6fa73 100644 --- a/freebsd/sys/net80211/ieee80211_node.c +++ b/freebsd/sys/net80211/ieee80211_node.c @@ -245,7 +245,12 @@ ieee80211_node_setuptxparms(struct ieee80211_node *ni) struct ieee80211vap *vap = ni->ni_vap; enum ieee80211_phymode mode; - if (ni->ni_flags & IEEE80211_NODE_HT) { + if (ni->ni_flags & IEEE80211_NODE_VHT) { + if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) + mode = IEEE80211_MODE_VHT_5GHZ; + else + mode = IEEE80211_MODE_VHT_2GHZ; + } else if (ni->ni_flags & IEEE80211_NODE_HT) { if (IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)) mode = IEEE80211_MODE_11NA; else diff --git a/freebsd/sys/net80211/ieee80211_output.c b/freebsd/sys/net80211/ieee80211_output.c index 51a75af2..a49c8a16 100644 --- a/freebsd/sys/net80211/ieee80211_output.c +++ b/freebsd/sys/net80211/ieee80211_output.c @@ -553,6 +553,59 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni, return (error); } +static int +ieee80211_validate_frame(struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211_frame *wh; + int type; + + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_ack)) + return (EINVAL); + + wh = mtod(m, struct ieee80211_frame *); + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != + IEEE80211_FC0_VERSION_0) + return (EINVAL); + + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + if (type != IEEE80211_FC0_TYPE_DATA) { + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) != + IEEE80211_FC1_DIR_NODS) + return (EINVAL); + + if (type != IEEE80211_FC0_TYPE_MGT && + (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) != 0) + return (EINVAL); + + /* XXX skip other field checks? */ + } + + if ((params && (params->ibp_flags & IEEE80211_BPF_CRYPTO) != 0) || + (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0) { + int subtype; + + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + + /* + * See IEEE Std 802.11-2012, + * 8.2.4.1.9 'Protected Frame field' + */ + /* XXX no support for robust management frames yet. */ + if (!(type == IEEE80211_FC0_TYPE_DATA || + (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_AUTH))) + return (EINVAL); + + wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; + } + + if (m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) + return (EINVAL); + + return (0); +} + /* * 802.11 output routine. This is (currently) used only to * connect bpf write calls to the 802.11 layer for injecting @@ -563,6 +616,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct route *ro) { #define senderr(e) do { error = (e); goto bad;} while (0) + const struct ieee80211_bpf_params *params = NULL; struct ieee80211_node *ni = NULL; struct ieee80211vap *vap; struct ieee80211_frame *wh; @@ -608,14 +662,20 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, senderr(EIO); /* XXX bypass bridge, pfil, carp, etc. */ - if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_ack)) - senderr(EIO); /* XXX */ + /* + * NB: DLT_IEEE802_11_RADIO identifies the parameters are + * present by setting the sa_len field of the sockaddr (yes, + * this is a hack). + * NB: we assume sa_data is suitably aligned to cast. + */ + if (dst->sa_len != 0) + params = (const struct ieee80211_bpf_params *)dst->sa_data; + + error = ieee80211_validate_frame(m, params); + if (error != 0) + senderr(error); + wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) - senderr(EIO); /* XXX */ - if (m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) - senderr(EIO); /* XXX */ /* locate destination node */ switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { @@ -628,7 +688,7 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, ni = ieee80211_find_txnode(vap, wh->i_addr3); break; default: - senderr(EIO); /* XXX */ + senderr(EDOOFUS); } if (ni == NULL) { /* @@ -647,11 +707,18 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, * it marks EAPOL in frames with M_EAPOL. */ m->m_flags &= ~M_80211_TX; + m->m_flags |= M_ENCAP; /* mark encapsulated */ - /* calculate priority so drivers can find the tx queue */ - /* XXX assumes an 802.3 frame */ - if (ieee80211_classify(ni, m)) - senderr(EIO); /* XXX */ + if (IEEE80211_IS_DATA(wh)) { + /* calculate priority so drivers can find the tx queue */ + if (ieee80211_classify(ni, m)) + senderr(EIO); /* XXX */ + + /* NB: ieee80211_encap does not include 802.11 header */ + IEEE80211_NODE_STAT_ADD(ni, tx_bytes, + m->m_pkthdr.len - ieee80211_hdrsize(wh)); + } else + M_WME_SETAC(m, WME_AC_BE); IEEE80211_NODE_STAT(ni, tx_data); if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { @@ -659,20 +726,9 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, m->m_flags |= M_MCAST; } else IEEE80211_NODE_STAT(ni, tx_ucast); - /* NB: ieee80211_encap does not include 802.11 header */ - IEEE80211_NODE_STAT_ADD(ni, tx_bytes, m->m_pkthdr.len); IEEE80211_TX_LOCK(ic); - - /* - * NB: DLT_IEEE802_11_RADIO identifies the parameters are - * present by setting the sa_len field of the sockaddr (yes, - * this is a hack). - * NB: we assume sa_data is suitably aligned to cast. - */ - ret = ieee80211_raw_output(vap, ni, m, - (const struct ieee80211_bpf_params *)(dst->sa_len ? - dst->sa_data : NULL)); + ret = ieee80211_raw_output(vap, ni, m, params); IEEE80211_TX_UNLOCK(ic); return (ret); bad: @@ -1008,13 +1064,44 @@ ieee80211_send_nulldata(struct ieee80211_node *ni) int ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) { - const struct ether_header *eh = mtod(m, struct ether_header *); + const struct ether_header *eh = NULL; + uint16_t ether_type; int v_wme_ac, d_wme_ac, ac; + if (__predict_false(m->m_flags & M_ENCAP)) { + struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *); + struct llc *llc; + int hdrlen, subtype; + + subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; + if (subtype & IEEE80211_FC0_SUBTYPE_NODATA) { + ac = WME_AC_BE; + goto done; + } + + hdrlen = ieee80211_hdrsize(wh); + if (m->m_pkthdr.len < hdrlen + sizeof(*llc)) + return 1; + + llc = (struct llc *)mtodo(m, hdrlen); + if (llc->llc_dsap != LLC_SNAP_LSAP || + llc->llc_ssap != LLC_SNAP_LSAP || + llc->llc_control != LLC_UI || + llc->llc_snap.org_code[0] != 0 || + llc->llc_snap.org_code[1] != 0 || + llc->llc_snap.org_code[2] != 0) + return 1; + + ether_type = llc->llc_snap.ether_type; + } else { + eh = mtod(m, struct ether_header *); + ether_type = eh->ether_type; + } + /* * Always promote PAE/EAPOL frames to high priority. */ - if (eh->ether_type == htons(ETHERTYPE_PAE)) { + if (ether_type == htons(ETHERTYPE_PAE)) { /* NB: mark so others don't need to check header */ m->m_flags |= M_EAPOL; ac = WME_AC_VO; @@ -1049,7 +1136,7 @@ ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) /* XXX m_copydata may be too slow for fast path */ #ifdef INET - if (eh->ether_type == htons(ETHERTYPE_IP)) { + if (eh && eh->ether_type == htons(ETHERTYPE_IP)) { uint8_t tos; /* * IP frame, map the DSCP bits from the TOS field. @@ -1062,7 +1149,7 @@ ieee80211_classify(struct ieee80211_node *ni, struct mbuf *m) } else { #endif /* INET */ #ifdef INET6 - if (eh->ether_type == htons(ETHERTYPE_IPV6)) { + if (eh && eh->ether_type == htons(ETHERTYPE_IPV6)) { uint32_t flow; uint8_t tos; /* diff --git a/freebsd/sys/net80211/ieee80211_proto.c b/freebsd/sys/net80211/ieee80211_proto.c index 73410d70..129e11e2 100644 --- a/freebsd/sys/net80211/ieee80211_proto.c +++ b/freebsd/sys/net80211/ieee80211_proto.c @@ -1310,6 +1310,12 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap) } } +/* + * Fetch the WME parameters for the given VAP. + * + * When net80211 grows p2p, etc support, this may return different + * parameters for each VAP. + */ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *wp) { @@ -1317,6 +1323,12 @@ ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *wp) memcpy(wp, &vap->iv_ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * For NICs which only support one set of WME paramaters (ie, softmac NICs) + * there may be different VAP WME parameters but only one is "active". + * This returns the "NIC" WME parameters for the currently active + * context. + */ void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *wp) { @@ -1324,6 +1336,26 @@ ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *wp) memcpy(wp, &ic->ic_wme.wme_chanParams, sizeof(*wp)); } +/* + * Return whether to use QoS on a given WME queue. + * + * This is intended to be called from the transmit path of softmac drivers + * which are setting NoAck bits in transmit descriptors. + * + * Ideally this would be set in some transmit field before the packet is + * queued to the driver but net80211 isn't quite there yet. + */ +int +ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac) +{ + /* Bounds/sanity check */ + if (ac < 0 || ac >= WME_NUM_AC) + return (0); + + /* Again, there's only one global context for now */ + return (!! vap->iv_ic->ic_wme.wme_chanParams.cap_wmeParams[ac].wmep_noackPolicy); +} + static void parent_updown(void *arg, int npending) { diff --git a/freebsd/sys/net80211/ieee80211_proto.h b/freebsd/sys/net80211/ieee80211_proto.h index 187f7018..28238ce8 100644 --- a/freebsd/sys/net80211/ieee80211_proto.h +++ b/freebsd/sys/net80211/ieee80211_proto.h @@ -298,6 +298,7 @@ void ieee80211_wme_vap_getparams(struct ieee80211vap *vap, struct chanAccParams *); void ieee80211_wme_ic_getparams(struct ieee80211com *ic, struct chanAccParams *); +int ieee80211_wme_vap_ac_is_noack(struct ieee80211vap *vap, int ac); /* * Return the WME TID from a QoS frame. If no TID diff --git a/freebsd/sys/net80211/ieee80211_scan_sta.c b/freebsd/sys/net80211/ieee80211_scan_sta.c index ed069ed8..a7a1fc29 100644 --- a/freebsd/sys/net80211/ieee80211_scan_sta.c +++ b/freebsd/sys/net80211/ieee80211_scan_sta.c @@ -121,7 +121,7 @@ static void sta_flush_table(struct sta_table *); /* * match_bss returns a bitmask describing if an entry is suitable * for use. If non-zero the entry was deemed not suitable and it's - * contents explains why. The following flags are or'd to to this + * contents explains why. The following flags are or'd to this * mask and can be used to figure out why the entry was rejected. */ #define MATCH_CHANNEL 0x00001 /* channel mismatch */ |