mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-10-14 07:59:07 +08:00
Update to FreeBSD head 2018-02-01
Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4. Update #3472.
This commit is contained in:
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
/*
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user