Page MenuHomeFreeBSD

D49764.diff
No OneTemporary

D49764.diff

diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -892,7 +892,6 @@
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_tx_ampdu *tap;
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
- ieee80211_seq seqno;
IEEE80211_TX_LOCK_ASSERT(ni->ni_ic);
@@ -975,25 +974,8 @@
/* NB: zero out i_seq field (for s/w encryption etc) */
*(uint16_t *)&wh->i_seq[0] = 0;
- } else {
- if (IEEE80211_HAS_SEQ(type & IEEE80211_FC0_TYPE_MASK,
- type & IEEE80211_FC0_SUBTYPE_MASK))
- /*
- * 802.11-2012 9.3.2.10 - QoS multicast frames
- * come out of a different seqno space.
- */
- if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
- } else {
- seqno = ni->ni_txseqs[tid]++;
- }
- else
- seqno = 0;
-
- *(uint16_t *)&wh->i_seq[0] =
- htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- M_SEQNO_SET(m, seqno);
- }
+ } else
+ ieee80211_output_seqno_assign(ni, tid, m);
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
m->m_flags |= M_MCAST;
@@ -1483,7 +1465,6 @@
struct ieee80211_key *key;
struct llc *llc;
int hdrsize, hdrspace, datalen, addqos, txfrag, is4addr, is_mcast;
- ieee80211_seq seqno;
int meshhdrsize, meshae;
uint8_t *qos;
int is_amsdu = 0;
@@ -1829,22 +1810,8 @@
* and we don't need the TX lock held.
*/
if ((m->m_flags & M_AMPDU_MPDU) == 0) {
- /*
- * 802.11-2012 9.3.2.10 -
- *
- * If this is a multicast frame then we need
- * to ensure that the sequence number comes from
- * a separate seqno space and not the TID space.
- *
- * Otherwise multicast frames may actually cause
- * holes in the TX blockack window space and
- * upset various things.
- */
- if (IEEE80211_IS_MULTICAST(wh->i_addr1))
- seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
- else
- seqno = ni->ni_txseqs[tid]++;
-
+ ieee80211_output_seqno_assign(ni, tid, m);
+ } else {
/*
* NB: don't assign a sequence # to potential
* aggregates; we expect this happens at the
@@ -1857,24 +1824,11 @@
* capability; this may also change when we pull
* aggregation up into net80211
*/
- *(uint16_t *)wh->i_seq =
- htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- M_SEQNO_SET(m, seqno);
- } else {
/* NB: zero out i_seq field (for s/w encryption etc) */
*(uint16_t *)wh->i_seq = 0;
}
} 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);
- M_SEQNO_SET(m, seqno);
-
+ ieee80211_output_seqno_assign(ni, IEEE80211_NONQOS_TID, m);
/*
* XXX TODO: we shouldn't allow EAPOL, etc that would
* be forced to be non-QoS traffic to be A-MSDU encapsulated.
@@ -1975,7 +1929,6 @@
* This implements the fragmentation part of 802.11-2016 10.2.7
* (Fragmentation/defragmentation overview.)
*
- * Fragment the frame according to the specified mtu.
* The size of the 802.11 header (w/o padding) is provided
* so we don't need to recalculate it. We create a new
* mbuf for each fragment and chain it through m_nextpkt;
@@ -3827,8 +3780,6 @@
struct ieee80211com *ic = ni->ni_ic;
int len_changed = 0;
uint16_t capinfo;
- struct ieee80211_frame *wh;
- ieee80211_seq seqno;
IEEE80211_LOCK(ic);
/*
@@ -3896,8 +3847,6 @@
return 1; /* just assume length changed */
}
- 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
@@ -3906,10 +3855,7 @@
* 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);
- M_SEQNO_SET(m, seqno);
+ ieee80211_output_beacon_seqno_assign(ni, m);
/* XXX faster to recalculate entirely or just changes? */
capinfo = ieee80211_getcapinfo(vap, ni->ni_chan);
@@ -4241,3 +4187,96 @@
}
m_freem(m);
}
+
+/**
+ * @brief Assign a sequence number to the given frame.
+ *
+ * Check the frame type and TID and assign a suitable sequence number
+ * from the correct sequence number space.
+ *
+ * It assumes the mbuf has been encapsulated, and has the TID assigned
+ * if it is a QoS frame.
+ *
+ * Note this also clears any existing fragment ID in the header, so it
+ * must be called first before assigning fragment IDs.
+ *
+ * For now this implements parts of 802.11-2012; it doesn't do all of
+ * the needed checks for full compliance (notably QoS-Data NULL frames).
+ *
+ * TODO: update to 802.11-2020 10.3.2.14.2 (Transmitter Requirements)
+ *
+ * @param ni ieee80211_node this frame will be transmitted to
+ * @param arg_tid A temporary check, existing callers may set
+ * this to a TID variable they were using, and this routine
+ * will verify it against what's in the frame and complain if
+ * they don't match. For new callers, use -1.
+ * @param m mbuf to populate the sequence number into
+ */
+void
+ieee80211_output_seqno_assign(struct ieee80211_node *ni, int arg_tid,
+ struct mbuf *m)
+{
+ struct ieee80211_frame *wh;
+ ieee80211_seq seqno;
+ uint8_t tid, type, subtype;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ tid = ieee80211_gettid(wh);
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ /*
+ * Find places where the passed in TID doesn't match gettid()
+ * and log. I'll have to then go and chase those down.
+ *
+ * If the caller knows its already setup the TID in the frame
+ * correctly then it can pass in -1 and this check will be
+ * skipped.
+ */
+ if (arg_tid != -1 && tid != arg_tid)
+ ic_printf(ni->ni_vap->iv_ic,
+ "%s: called; TID mismatch; tid=%u, arg_tid=%d\n",
+ __func__, tid, arg_tid);
+
+ if (IEEE80211_HAS_SEQ(type, subtype)) {
+ /*
+ * 802.11-2012 9.3.2.10 - QoS multicast frames
+ * come out of a different seqno space.
+ */
+ if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+ seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
+ else
+ seqno = ni->ni_txseqs[tid]++;
+ } else
+ seqno = 0;
+
+ /*
+ * Assign the sequence number, clearing out any existing
+ * sequence and fragment numbers.
+ */
+ *(uint16_t *)&wh->i_seq[0] =
+ htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ M_SEQNO_SET(m, seqno);
+}
+
+/**
+ * @brief Assign a sequence number to the given beacon frame.
+ *
+ * TODO: update to 802.11-2020 10.3.2.14.2 (Transmitter Requirements)
+ *
+ * @param ni ieee80211_node this frame will be transmitted to
+ * @param m mbuf to populate the sequence number into
+ */
+void
+ieee80211_output_beacon_seqno_assign(struct ieee80211_node *ni, struct mbuf *m)
+{
+ struct ieee80211_frame *wh;
+ ieee80211_seq seqno;
+
+ wh = mtod(m, struct ieee80211_frame *);
+
+ seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
+ *(uint16_t *)&wh->i_seq[0] =
+ htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ M_SEQNO_SET(m, seqno);
+}
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -123,6 +123,10 @@
const struct ether_header *);
void ieee80211_tx_complete(struct ieee80211_node *,
struct mbuf *, int);
+void ieee80211_output_seqno_assign(struct ieee80211_node *,
+ int, struct mbuf *);
+void ieee80211_output_beacon_seqno_assign(struct ieee80211_node *,
+ struct mbuf *);
/*
* The formation of ProbeResponse frames requires guidance to

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 27, 2:26 AM (10 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30405617
Default Alt Text
D49764.diff (7 KB)

Event Timeline