The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=dcd47304acb1f1713a27f407a153e2bb54c574ba
commit dcd47304acb1f1713a27f407a153e2bb54c574ba Author: Adrian Chadd <adr...@freebsd.org> AuthorDate: 2025-06-04 21:48:23 +0000 Commit: Adrian Chadd <adr...@freebsd.org> CommitDate: 2025-07-08 19:37:03 +0000 net80211: update ieee80211_output_seqno_assign() to 802.11-2020 Update ieee80211_output_seqno_assign() to support the transmitter sequence number assignment outlined in 802.11-2020 10.3.2.14.2 (Transmitter Requirements). Notably this correctly assigns the QoS NULL frames a seqno outside of the TID seqno space. Leave stub comments for the currently supported sequence number decisions. Add two new functions to access and increment the sequence number space, which will ensure that things wrap correctly. This should simplify drivers needing to constantly invent their own methods of fetching and incrementing the sequence number space. Differential Revision: https://reviews.freebsd.org/D50691 Reviewed by: bz --- sys/net80211/ieee80211_node.c | 30 ++++++++++++++++++++++++++++ sys/net80211/ieee80211_node.h | 6 ++++++ sys/net80211/ieee80211_output.c | 44 ++++++++++++++++++++++++++--------------- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index ad17af6778a1..a201d1b278f0 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -3137,6 +3137,36 @@ ieee80211_getsignal(struct ieee80211vap *vap, int8_t *rssi, int8_t *noise) *rssi = ieee80211_getrssi(vap); } +/** + * @brief Increment the given TID TX sequence, return the current one. + * + * @param ni ieee80211_node to operate on + * @param tid TID, or IEEE80211_NONQOS_TID + * @returns sequence number, from 0 .. 4095 inclusive, post increments + */ +ieee80211_seq ieee80211_tx_seqno_fetch_incr(struct ieee80211_node *ni, + uint8_t tid) +{ + ieee80211_seq seq; + + seq = ni->ni_txseqs[tid]; + ni->ni_txseqs[tid] = (ni->ni_txseqs[tid] + 1) % IEEE80211_SEQ_RANGE; + return (seq); +} + +/** + * @brief Return the current sequence number for the given TID + * + * @param ni ieee80211_node to operate on + * @param tid TID, or IEEE80211_NONQOS_TID + * @returns sequence number, from 0 .. 4095 inclusive + */ +ieee80211_seq ieee80211_tx_seqno_fetch(const struct ieee80211_node *ni, + uint8_t tid) +{ + return (ni->ni_txseqs[tid]); +} + /** * @brief return a dot11rate / ratecode representing the current transmit rate * diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index c83eee04a8dc..ef25fa0d7fdd 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -531,6 +531,12 @@ void ieee80211_node_leave(struct ieee80211_node *); int8_t ieee80211_getrssi(struct ieee80211vap *); void ieee80211_getsignal(struct ieee80211vap *, int8_t *, int8_t *); +/* TX sequence space related routines */ +ieee80211_seq ieee80211_tx_seqno_fetch_incr(struct ieee80211_node *, + uint8_t); +ieee80211_seq ieee80211_tx_seqno_fetch(const struct ieee80211_node *, + uint8_t); + /* * Node transmit rate specific manipulation. * diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index a4151f807882..afe83ea0805c 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -4195,17 +4195,15 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status) * Check the frame type and TID and assign a suitable sequence number * from the correct sequence number space. * + * This implements the components of 802.11-2020 10.3.2.14.2 + * (Transmitter Requirements) that net80211 currently supports. + * * 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 @@ -4239,16 +4237,30 @@ ieee80211_output_seqno_assign(struct ieee80211_node *ni, int arg_tid, "%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 + + /* 802.11-2020 10.3.2.14.2 (Transmitter Requirements) sections */ + + /* SNS7 - unicast PV1 management frame */ + + /* SNS6 - unicast PV1 data frame */ + + /* SNS5 - QoS NULL frames */ + if (IEEE80211_QOS_HAS_SEQ(wh) && IEEE80211_IS_QOS_NULL(wh)) + seqno = ieee80211_tx_seqno_fetch_incr(ni, IEEE80211_NONQOS_TID); + + /* SNS4 - QMF STA transmitting a QMF */ + + /* SNS3 - QoS STA; Time Priority Management frame */ + + /* SNS2 - unicast QoS STA, data frame, excluding SNS5 */ + else if (IEEE80211_QOS_HAS_SEQ(wh) && + !IEEE80211_IS_MULTICAST(wh->i_addr1)) + seqno = ieee80211_tx_seqno_fetch_incr(ni, tid); + + /* SNS1 - Baseline (everything else) */ + else if (IEEE80211_HAS_SEQ(type, subtype)) + seqno = ieee80211_tx_seqno_fetch_incr(ni, IEEE80211_NONQOS_TID); + else seqno = 0; /* @@ -4276,7 +4288,7 @@ ieee80211_output_beacon_seqno_assign(struct ieee80211_node *ni, struct mbuf *m) wh = mtod(m, struct ieee80211_frame *); - seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++; + seqno = ieee80211_tx_seqno_fetch_incr(ni, IEEE80211_NONQOS_TID); *(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT); M_SEQNO_SET(m, seqno);