git: 20d808f42860 - main - net80211: document the vap / device transmit paths, fragment node references
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 May 2025 04:22:38 UTC
The branch main has been updated by adrian:
URL: https://cgit.FreeBSD.org/src/commit/?id=20d808f428601c5122f8b394068dda04e5174bac
commit 20d808f428601c5122f8b394068dda04e5174bac
Author: Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2025-01-27 05:45:37 +0000
Commit: Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2025-05-07 04:21:17 +0000
net80211: document the vap / device transmit paths, fragment node references
* Document what the VAP and device transmit paths do.
Take care to note down the 802.11 fragment handling and node references.
* Almost none of the drivers (save ath(4), which I fixed a long time ago)
implement 802.11 fragments after the big VAP rework done years
and years ago. A few others announce support (mwl, ral, uath, wpi) but
I haven't validated them. I'll be doing that as part of this work.
* Add some comments in ieee80211_fragment() around how fragment node
references work.
Differential Revision: https://reviews.freebsd.org/D49765
---
sys/net80211/ieee80211_freebsd.c | 48 ++++++++++++++++++++++++++++++++++++++--
sys/net80211/ieee80211_output.c | 31 ++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index d3c8352ab411..6979e601ce41 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -706,7 +706,37 @@ ieee80211_get_toa_params(struct mbuf *m, struct ieee80211_toa_params *p)
}
/*
- * Transmit a frame to the parent interface.
+ * @brief Transmit a frame to the parent interface.
+ *
+ * Transmit an 802.11 or 802.3 frame to the parent interface.
+ *
+ * This is called as part of 802.11 processing to enqueue a frame
+ * from net80211 into the device for transmit.
+ *
+ * If the interface is marked as 802.3 via IEEE80211_C_8023ENCAP
+ * (ie, doing offload), then an 802.3 frame will be sent and the
+ * driver will need to understand what to do.
+ *
+ * If the interface is marked as 802.11 (ie, no offload), then
+ * an encapsulated 802.11 frame will be queued. In the case
+ * of an 802.11 fragmented frame this will be a list of frames
+ * representing the fragments making up the 802.11 frame, linked
+ * via m_nextpkt.
+ *
+ * A fragmented frame list will consist of:
+ * + only the first frame with M_SEQNO_SET() assigned the sequence number;
+ * + only the first frame with the node reference and node in rcvif;
+ * + all frames will have the sequence + fragment number populated in
+ * the 802.11 header.
+ *
+ * The driver must ensure it doesn't try releasing a node reference
+ * for each fragment in the list.
+ *
+ * The provided mbuf/list is consumed both upon success and error.
+ *
+ * @param ic struct ieee80211com device to enqueue frame to
+ * @param m struct mbuf chain / packet list to enqueue
+ * @returns 0 if successful, errno if error.
*/
int
ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
@@ -726,6 +756,8 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
/* XXX number of fragments */
if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+
+ /* Note: there's only one node reference for a fragment list */
ieee80211_free_node(ni);
ieee80211_free_mbuf(m);
}
@@ -733,7 +765,19 @@ ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
}
/*
- * Transmit a frame to the VAP interface.
+ * @brief Transmit an 802.3 frame to the VAP interface.
+ *
+ * This is the entry point for the wifi stack to enqueue 802.3
+ * encapsulated frames for transmit to the given vap/ifnet instance.
+ * This is used in paths where 802.3 frames have been received
+ * or queued, and need to be pushed through the VAP encapsulation
+ * and transmit processing pipeline.
+ *
+ * The provided mbuf/list is consumed both upon success and error.
+ *
+ * @param vap struct ieee80211vap instance to transmit frame to
+ * @param m mbuf to transmit
+ * @returns 0 if OK, errno if error
*/
int
ieee80211_vap_xmitpkt(struct ieee80211vap *vap, struct mbuf *m)
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index e3cd73cd22d6..da7719b16dba 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -1889,6 +1889,10 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni,
*
* If the hardware does fragmentation offload, then don't bother
* doing it here.
+ *
+ * Don't send AMPDU/FF/AMSDU through fragmentation.
+ *
+ * 802.11-2016 10.2.7 (Fragmentation/defragmentation overview)
*/
if (IEEE80211_CONF_FRAG_OFFLOAD(ic))
txfrag = 0;
@@ -1963,6 +1967,33 @@ ieee80211_free_mbuf(struct mbuf *m)
* mbuf for each fragment and chain it through m_nextpkt;
* we might be able to optimize this by reusing the original
* packet's mbufs but that is significantly more complicated.
+ *
+ * A node reference is NOT acquired for each fragment in
+ * the list - the caller is assumed to have taken a node
+ * reference for the whole list. The fragment mbufs do not
+ * have a node pointer.
+ *
+ * Fragments will have the sequence number and fragment numbers
+ * assigned. However, Fragments will NOT have a sequence number
+ * assigned via M_SEQNO_SET.
+ *
+ * This must be called after assigning sequence numbers; it
+ * modifies the i_seq field in the 802.11 header to include
+ * the fragment number.
+ *
+ * @param vap ieee80211vap interface
+ * @param m0 pointer to mbuf list to fragment
+ * @param hdrsize header size to reserver
+ * @param ciphdrsize crypto cipher header size to reserve
+ * @param mtu maximum fragment size
+ *
+ * This implements the fragmentation part of 802.11-2016 10.2.7
+ * (Fragmentation/defragmentation overview.)
+ *
+ * @retval 1 if successful, with the mbuf pointed at by m0
+ * turned into an mbuf list of fragments (with the original
+ * mbuf being truncated.)
+ * @retval 0 if failure, the mbuf needs to be freed by the caller
*/
static int
ieee80211_fragment(struct ieee80211vap *vap, struct mbuf *m0,