Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F149663440
D49764.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D49764.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D49764: net80211: refactor sequence number assignment code
Attached
Detach File
Event Timeline
Log In to Comment