Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 May 2026 01:33:11 +0000
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 490c53e9353f - main - net80211: add initial README.md and PROTOCOL.md
Message-ID:  <6a13a6d7.4361b.5c217572@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=490c53e9353feb129fe0acb8d9ba8fa52db24e2c

commit 490c53e9353feb129fe0acb8d9ba8fa52db24e2c
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2026-04-26 23:32:35 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2026-05-25 01:32:33 +0000

    net80211: add initial README.md and PROTOCOL.md
    
    * Add top level README.md, linking to in progress and todo items
    * Add an 802.11 protocol overview, with todo items - this is designed
      to provide a basic introduction to 802.11 for people wishing to work
      on net80211 and drivers.
    * DEBUG.md - cover the debug API
    * DATAPATH_TRANSMIT.md - transmit datapath
    * DATAPATH_RECEIVE.md - receive datapath
    * PROTOCOL.md - a high level (for values of "high") overview of
      the 802.11 protocol and where it intersects with net80211
    
    Differential Revision: https://reviews.freebsd.org/D56760
---
 sys/net80211/DATAPATH_RECEIVE.md         | 160 +++++++++
 sys/net80211/DATAPATH_TRANSMIT.md        | 390 +++++++++++++++++++++
 sys/net80211/DEBUG.md                    | 101 ++++++
 sys/net80211/PROTOCOL.md                 | 563 +++++++++++++++++++++++++++++++
 sys/net80211/README.md                   | 139 ++++++++
 tools/kerneldoc/subsys/Doxyfile-net80211 |   3 +-
 6 files changed, 1355 insertions(+), 1 deletion(-)

diff --git a/sys/net80211/DATAPATH_RECEIVE.md b/sys/net80211/DATAPATH_RECEIVE.md
new file mode 100644
index 000000000000..a930aba0c3da
--- /dev/null
+++ b/sys/net80211/DATAPATH_RECEIVE.md
@@ -0,0 +1,160 @@
+# net80211 Datapath - Receive
+
+## Overview
+
+This document provides an overview for receive data paths in
+net80211, between the interface to the operating system, through net80211 and
+into the driver.
+
+The details about underlying implementations (eg how A-MPDU RX aggregation
+is handled) will be covered in dedicated documents.
+
+## Concurrency Notes
+
+The transmit path(s), receive path and control / ioctl paths all run
+in parallel and can be scheduled on multiple concurrently running
+kernel threads.  It's important to keep this in mind.
+
+## Receive Path
+
+### Concurrency
+
+There must only be one packet receive path into net80211.  The net80211 stack
+has not yet been fully validated to ensure that state changes all occur under
+sufficient locking.
+
+### Data Path
+
+The receive path is split into three broad categories:
+
+ * The normal 802.11/802.3 packet receive path from drivers;
+ * The input path for reinjected frames (eg WDS, 802.11s, BPF);
+ * Various side channels for offloaded non-data path (eg explicitly
+   scan results, management frames, etc.)
+
+#### Data Path - Initial Input
+
+The driver receive path begins in ieee80211_input.c . The four
+entry points are:
+
+ * ieee80211_input() / ieee80211_input_mimo() and
+ * ieee80211_input_all() / ieee80211_input_mimo_all().
+
+The first two are called when the destination MAC address is a known
+(struct ieee80211_node) node.  These are passed up to the
+VAP via a call to ni->ni_vap->iv_input().
+
+The second two are called when the destination MAC address is NOT
+a known node.  In this instance, the frames are treated as broadcast
+and routed to each VAP BSS node via a call to ieee80211_input_mimo().
+
+Each VAP vap->iv_input() method handles the behavioural specific
+needs of the interface.
+
+#### Data Path - VAP type / behaviour
+
+Each VAP type will do roughly the same thing - for example see
+sta_input() in ieee80211_sta.c .
+
+ * Check the frame size and protocol ID;
+ * Check if the frame has been decrypted in hardware;
+ * Grab A-MPDU session frames and put them in the reorder queue;
+ * Handle control frames sent to the node, or general scan frames;
+ * Get the frame QoS information / TID information if present;
+ * If appropriate, check the 802.11 receive sequence number;
+ * Break the handling up into data, management and control;
+ * Reinject into a radiotap/BPF session via a call to
+   ieee80211_radiotap_rx().
+
+The data paths will typically do the following:
+
+ * Do decryption if needed;
+ * Do 802.11 decap if needed;
+ * Enforce security requirements if needed;
+ * Eventually deliver the frame up to the higher level network
+   stack via a call to ieee80211_deliver_data() which will
+   strip away any last bits of 802.11 / net80211,
+   call ieee80211_vap_deliver_data(), which will call the
+   network stack input interface.
+
+The control and management paths will call vap->iv_recv_mgmt()
+and vap->iv_recv_ctl() which implement the per VAP type behaviours.
+These will include participating in driving the scan engine,
+the per-node state machines and the VAP state machine.
+
+#### Reinjected Path
+
+#### Side Channels
+
+Drivers may need a specific side channel for management/control
+frames, MAC layer events (eg A-MPDU aggregation session state);
+some power state communication, scan information and other
+things that would normally show up as 802.11 frames.
+
+These will be covered in more detail in other documents.
+
+### Receive Status and Parameters
+
+Received 802.11 / 802.3 frames can come with a variety of information
+that isn't strictly the data payload.  These include receive timestamps
+(at beginning or end of frame), receive noise floor / signal strength,
+channel / frequency, channel width, received rate, aggregation frame
+boundaries, decryption state, etc.
+
+The original paths - ieee80211_input() and ieee80211_input_all() -
+took a noise floor and rssi parameter.  Later drivers provide
+information about all of the above by attaching a (struct ieee80211_rx_stats)
+to the receive mbuf via a call to ieee80211_add_rx_params() bafore
+calling ieee80211_input_mimo() and ieee80211_input_mimo_all() .
+
+Existing drivers should be migrated to the mimo versions of these
+APIs and the existing API should eventually be deprecated and
+replace the mimo versions.
+
+All new drivers must use the ieee80211_input_mimo() and
+ieee80211_input_mimo_all() API calls.
+
+### Driver Receive Path Requirements
+
+The driver receive path has a few top level requirements:
+
+ * Driver / stack locks must not be held during receive.  This means that
+   drivers should dequeue their frames first into a local list, release
+   whatever locks are needed and then pass the frames up to net80211.
+
+ * Drivers are responsible for doing the node lookup before
+   calling ieee80211_input() / ieee80211_input_mimo() or
+   calling ieee80211_input_all() / ieee80211_input_mimo_all().
+
+ * Drivers are also responsible for creating and attaching the
+   ieee80211_rx_stats information via a call to ieee80211_add_rx_params().
+
+ * Drivers are responsible for tagging a frame as a potential
+   A_MPDU by tagging the received mbuf with the M_AMPDU flag.
+   They should do this by just tagging all mbufs to a node
+   with ni->ni_flags & IEEE80211_NODE_HT set w/ the M_AMPDU flag.
+   This is a holdover from the 802.11n code which enforces that
+   only potential AMPDU frames can be added to an A-MPDU receive
+   aggregation session and may be relaxed / removed in the future.
+
+### Driver Receive Path Methods
+
+Drivers can hook into the receive path processing in a variety of ways.
+There are a number of vap methods that a driver can hook into
+processing.  The details will be covered in the driver document.
+
+These include:
+
+ * vap->iv_input - the driver can replace the iv_input method
+   with its own method to first handle frames before they are passed
+   to the VAP type receive path.
+ * vap->iv_recv_mgmt - the driver can hook here to handle
+   management frames before the VAP type management receive path.
+ * vap->iv_recv_ctl - the driver can hook here to handle
+   control frames before the VAP type control receive path.
+ * vap->iv_bmiss - the driver can hook here to be informed of
+   beacon miss frames.
+
+These may be called at any time and overlapping with others (eg
+the beacon miss event - which may be triggered by a timer -
+can be called in parallel with the various receive path methods.)
diff --git a/sys/net80211/DATAPATH_TRANSMIT.md b/sys/net80211/DATAPATH_TRANSMIT.md
new file mode 100644
index 000000000000..b3122129d938
--- /dev/null
+++ b/sys/net80211/DATAPATH_TRANSMIT.md
@@ -0,0 +1,390 @@
+# net80211 Datapath - Transmit
+
+## Overview
+
+This document provides an overview for the transmit data path in
+net80211, between the interface to the operating system, through net80211 and
+into the driver.
+
+The details about underlying implementations (eg how A-MPDU RX aggregation
+is handled) will be covered in dedicated documents.
+
+## Concurrency Notes
+
+The transmit path(s), receive path and control / ioctl paths all run
+in parallel and can be scheduled on multiple concurrently running
+kernel threads.  It's important to keep this in mind.
+
+## Transmit Path
+
+There are two paths from the operating system layer into the net80211 transmit
+path - the normal data path and the BPF / radiotap raw frame path.
+
+It is important to note that both paths have no serialisation between
+them, and multiple sending paths in the OS can and will queue frames
+simultaneously across multiple concurrently executing threads/CPUs.
+Please keep this in mind when reading the transmit handling and
+how it interacts with 802.11 sequence numbering and encryption IV.
+
+### Data Path - net80211
+
+This is configured at the ifnet setup in ieee80211_vap_setup() -
+the output path is ieee80211_vap_transmit().  This input path
+takes 802.3 ethernet frames with no attached metadata (such as
+rate control, transmit power, etc) - it is left up to the stack.
+
+This hands the packet off to ieee80211_start_pkt() which will
+perform the initial 802.11 destination lookup, query the node
+state (eg whether it's in power save) and the VAP state (eg
+is the vap itself in power state, or in a non-RUN state)
+and drop or queue the frame appropriately.
+
+It is then handed over to ieee80211_vap_pkt_send_dest() with
+a destination ieee80211_node reference.
+
+ieee80211_vap_pkt_send_dest() performs the bulk of the
+net80211 transmit handling.  Packets will be queued here if the
+destination node is in a power saving mode.
+
+This includes:
+
+ * Firstly - checking if the packet needs to be queued for
+   power saving operation and will pass it via ieee80211_pwrsave()
+   if needed;
+ * QoS classification via a call to ieee80211_classify();
+ * BPF TX tap via a call to BPF_MTAP();
+ * handling 802.11 encapsulation via ieee80211_encap() if required;
+ * A-MPDU TX decisions, AMSDU and Atheros Fast-Frames decisions.
+
+At this point the packet has been 802.11 encapsulated if required,
+marked as needing encryption if required, and has been optionally
+fragmented into a list of 802.11 fragments.
+
+Finally, the packet / fragment packet chain is sent up to the driver via a call
+to ieee80211_parent_xmitpkt().   The driver is expected to queue the
+packet / fragment list or discard the packet / fragment list.  The specific
+format of the mbuf chain and how ieee80211_node references are kept
+is documented in ieee80211_parent_xmitpkt().
+
+#### Notes on transmit path serialisation
+
+Note that by default the IEEE80211_TX_LOCK() is held across the call to
+ieee80211_encap() and ieee80211_parent_xmitpkt().  Drivers can register
+that they properly handle 802.11 sequence number offloading via
+IEEE80211_FEXT_SEQNO_OFFLOAD.  The lock is to ensure that packets
+queued to the driver layer are added to the driver transmit queue
+in the same order that they are 802.11 encapsulated - which sets the
+802.11 sequence number.  Drivers which set IEEE80211_FEXT_SEQNO_OFFLOAD
+indicate that they will assign the sequence number themselves - likely
+at the same time that the transmit encryption IV number is assigned,
+or simply offloaded in firmware - and thus this lock is not
+required.
+
+### Data path - Driver
+
+The call ieee80211_parent_xmit() will call the driver ic->ic_transmit()
+method.  At this point the driver can choose to queue / send the frame
+(and take ownership of it), or return an error, and return it back
+to net80211.  Currently net80211 will just free the mbuf and node reference
+and return, but drivers should not assume that.
+
+The mbuf passed in will be either a single 802.11/802.3 frame in an mbuf,
+or a list of 802.11 fragments chained by m->m_nextpkt.  If the driver
+has not set IEEE80211_FEXT_SEQNO_OFFLOAD then the packet will have
+a sequence number assigned which the driver can fetch via M_SEQNO_GET().
+The mbuf also holds an ieee80211_node reference.
+
+(Note that fragments do not have sequence numbers assigned nor node
+references.)
+
+The driver needs to do a few things with this frame.  Notably if it's
+an 802.3 offload device, it will be handed an 802.3 frame with no
+802.11 information.  In that case, the driver just needs to queue
+it for send to the hardware/firmware.
+
+For devices which accept 802.11 frames, a few things are needed:
+
+ * It needs to queue them for send, in the order they're given.
+ * If there are any reasons the frames need to be buffered in the
+   driver - eg node power state, asynchronous node/key/state updates -
+   then they'll be buffered here until needed.
+ * It needs to do any local hardware/firmware setup - rate control,
+   transmit configuration, destination queue decisions, etc.
+ * Hardware/firmware typically has some way to mark a frame as a type
+   (control, data, management), whether RTS/CTS is needed, 
+ * If IEEE80211_FEXT_SEQNO_OFFLOAD is set in the driver, it may need to
+   allocate 802.11 sequence numbers via a call to ieee80211_output_seqno_assign().
+ * If the frame is part of an MPDU (m->m_flags & M_AMPDU_MPDU) then
+   the frame may need to be handled differently.  (For example rtwn(4)
+   leaves sequence number assignment up to the firmware when A-MPDU is
+   enabled.)
+ * If the mbuf is marked as needing encryption (IEEE80211_FC1_PROTECTED
+   is set in the 802.11 header) then the frame needs to be encrypted
+   with the current encryption state via a call to ieee80211_crypto_encap().
+ * Finally, the frame is queued to the hardware/firmware.
+
+Again it is critical that the 802.11 sequence number and encryption be
+called together in the same order.  This is typically done by the TX work
+being done in a lock, or all frames being pushed into a single software
+TX queue.
+
+### Data path vs control path and the need to buffer frames
+
+net80211 currently treats encryption key programming, VAP state
+and other updates as synchronous calls.  For example, the
+transmit path will call the driver to add a node, then
+set the encryption keys and then queue a frame to be transmitted.
+
+For devices which are programmed directly with no queued operations
+(such as the ath(4) devices) the encryption key and node programming
+is immediate.  However, for many other devices - firmware and
+USB are two examples - these operations are asynchronous.
+And these code paths tend to be in the transmit paths from
+upper layers that may have locks held, so sleeping is not an option.
+
+So for now this needs to be implemented in the driver itself.
+It will need to maintain a per-node queue of transmit frames;
+it will need to track asynchronous node creation/updates and
+encryption key updates and buffer transmit frames for a node
+until the node add/update and encryption key add/update is
+completed.
+
+### Transmit Completion Notifications
+
+The net80211 stack may request a completion notification
+to be called when a transmit frame has completed.
+This will be done via a call to ieee80211_add_callback().
+It is used in various parts of the net80211 stack to
+drive the MAC state machines - for example, being notified
+once an BAR (Block-ACK request) frame has completed so
+the retry timer can be cancelled.
+
+This requires that mbufs that are transmitted with a requested
+completion callback be checked and handled appropriately.
+This is covered in the next section.
+
+### Completing and freeing transmit path mbufs
+
+There are two paths to freeing mbufs - ieee80211_free_mbuf() and
+ieee80211_tx_complete().
+
+#### Before transmit - ieee80211_free_mbuf()
+
+ieee80211_free_mbuf() is used in drivers and net80211 to free
+a list of mbufs as part of the transmit path setup so it can
+properly account for and free an 802.11 MPDU / 802.3 frame,
+or a list of mbufs representing 802.11 fragments.  It doesn't
+handle the ieee80211_node reference as at the early stage
+of transmit there is a single ieee80211_node reference
+covering all of the fragments being passed to the driver
+for transmit.
+
+If you're not supporting 802.11 fragment transmit (and you have
+to register your driver with the IEEE80211_C_TXFRAG capability
+to even support this) then you can ignore all of the above
+and just not call ieee80211_free_mbuf() for now.
+
+This must not be used for receive mbufs.  Yes, this is not
+well named and should likely just be renamed.
+
+#### After transmit queueing / attempts - ieee80211_tx_complete().
+
+In the general case of an transmit mbuf being completed (either
+successfully or unsuccessfully) net80211 provides a call
+to handle everything - ieee80211_tx_complete().  This takes
+the relevant destination node (struct ieee80211_node),
+the mbuf, and a status indiciating success or failure.
+
+A call to ieee80211_tx_complete() handles a variety of
+common functions:
+
+ * It increments the ifnet counters as appropriate;
+ * If the frame has a TX completion notification callback attached
+   it will process said callback;
+ * If a node is supplied then the node reference is freed
+
+In the past some drivers implemented the mbuf TX callback
+handling themselves, resulting in some drivers supporting
+callback and some drivers not supporting callbacks. The goal
+here is to implement a single way for completions to be
+handled.
+
+Note that some hardware / firmware do not support per-frame
+completion / status notification.  For example, USB devices
+tend to not send individual notifications for frames - you
+may be able to request it for specific frames, but the
+status notifications are expensive.  In these cases, drivers
+may just call ieee80211_tx_complete() with a status based
+on whether the frame was queued to the USB endpoint successfully
+or not.
+
+#### Atheros Fast Frames / 802.11n A-MSDU transmit
+
+(Note this is purposely short - a larger write-up for this will be
+done on a separate page.)
+
+The transmit path above will call ieee80211_ff_check() and
+ieee80211_amsdu_check() to see if the given node/frame should be
+queued for an Atheros Fast Frames MPDU or an A-MSDU.
+
+If the frame should be queued it will be queued locally and NULL
+will be returned; if there's already a frame queued it may be
+paired with a queued frame and both returned as a single mbuf / MPDU
+to send.
+
+As far as the driver is concerned, it will be handed a single
+802.11 MPDU to send.
+
+#### 802.11n A-MPDU transmit
+
+net80211 implements the A-MPDU negotiation and block-ack request/response
+handling.  However currently the driver must implement A-MPDU packet
+queuing, buffering, submission and retransmission.
+
+There are some methods that the driver can override to control the
+A-MPDU transmit negotiation flow (ic->ic_addba_request, ic->ic_addba_response,
+ic->ic_addba_response_timeout, ic->ic_addba_stop) and the Block-Ack
+response completion or error/timeout (ic->ic_bar_response).
+
+#### Driver queue completion
+
+Currently there are two things a driver should do when its own queues
+are (mostly) empty:
+
+ * When the transmit queue is empty or mostly empty, call ieee80211_ff_flush()
+   to flush out any pending A-MSDU / Atheros Fast Frames to be transmitted;
+ * When the receive queue is being handled, call ieee80211_ff_age_all() to
+   flush out any frames that are older than a provided time interval.
+
+These calls ensure that any queued frames in Fast Frames / A-MSDU queue
+don't stay in there permanently.
+
+### Non data frame transmission (management, control, action, beacon, etc)
+
+Non data frames are sent via ieee80211_raw_output().  The main exception to
+this is beacon frames, which are separately initialised and pulled from
+net80211 into the driver by the driver specific beacon handling routines.
+
+Raw frames differ from data frames in a couple of ways:
+
+ * Transmit parameters are typically sent from userland or the caller
+   (struct ieee80211_bpf_params \*), and
+ * The input path into the driver is via ic->ic_raw_xmit(), not ic->ic_transmit().
+
+The driver can combine the data and non-data paths into a single path.
+The main reason for keeping these separate is to cleanly support drivers
+and firmware which allow 802.3 frames to be sent and received, but still
+need a side channel to send and receive management frames for various other
+functions.
+
+The raw frame output path is used by:
+
+ * The BPF output path - ieee80211_output() ;
+ * The management frame output path - ieee80211_mgmt_output() ;
+ * The NULL data output path - ieee80211_send_nulldata() ;
+ * Sending probe requests - ieee80211_send_probereq() ;
+ * Sending probe responses - ieee80211_send_proberesp() ;
+ * Sending 802.11n BAR frames - ieee80211_send_bar() ;
+ * .. and anywhere where the individual protocol (eg 802.11s) wishes to send raw
+   non-data frames.
+
+This path is not REALLY designed for high speed data - for example,
+it should work for basic packet injection, but it does not pass through
+the normal functions for encryption, power save, TX aggregation and other
+data specific operations.  It expects to be handed a raw, already encapsulated
+802.11 frame.
+
+Note this is not an 802.11 MPDU - this is an 802.11 frame.  For example,
+non-data frames may not have sequence numbers.  NULL data frames have a sequence
+number but that sequence number must be 0.
+
+Once the driver ic->ic_raw_xmit() call is made, the driver can handle the
+802.11 frame in any way it sees fit.  Again, it can't assume it's an 802.11
+data frame.
+
+### BPF path
+
+Control frames are injected from userland and net80211 via a raw transmit path,
+separate from the data path.  This dates back to the earliest Orinoco/WaveLAN
+cards, where the earlier firmware only allowed 802.3 frames to be sent/received,
+but later firmware introduced raw packet transmit to allow wpa_supplicant
+operation.
+
+Packet injection begins via the BPF/radiotap input path.  The code in
+ieee80211_radiotap.c attaches a BPF operator to the VAP during the
+call to ieee80211_radiotap_vattach().
+
+Raw frames start in BPF and are queued via bpf_ieee80211_write(), which will
+send the frame into the driver via a call to the VAP ifp->if_output() and then
+if provided, a copy of the feedback mbuf via the VAP ifp->if_input().
+
+The ifp->if_output() method by default is ieee80211_output().  The driver
+can override this.  This takes care of validating that it is an 802.11
+frame, extracts the (struct ieee80211_bpf_params \*) header from the
+destination sockaddr passed in via BPF, finds the relevant
+struct ieee80211_node \*) tx node, grabs a reference, some further sanity
+checks and then calls ieee80211_raw_output().  The rest of the raw output
+path is the same as net80211 sourced raw frames.
+
+### Power Save Management
+
+By default, net80211 will track legacy power-save state between IBSS nodes
+and STA <-> AP nodes (ie, full node buffering via the power management bit
+in the 802.11 header; TIM/ATIM bitmaps in beacons, NULL data frames to wake up)
+and PS-POLL frames being sent by stations to request individual frames.
+
+The transmit path will pass frames destined to asleep stations to the power
+save queue via a call to ieee80211_pwrsave().
+
+There are a number of VAP methods for the driver to tie into if it needs to be
+informed about this state (vap->iv_set_tim, vap->iv_recv_pspoll, vap->iv_node_ps).
+These allow the driver to keep its own internal state in sync with net80211
+and allows it to better maintain its own transmit queue state.
+
+See the ath(4) driver for a comprehensive example of how these methods are used
+to correctly transmit and buffer frames from an AP to STA device without packet
+loss.
+
+### Transmit path encryption
+
+The net80211 stack needs to handle a variety of transmit encryption schemes
+based on all the combinations that driver and firmware interfaces may require.
+
+In general, the transmit encryption is done in two phases:
+
+ * In ieee80211_encap(), the transmit key is chosen via a call
+   to ieee80211_crypto_getucastkey() or ieee80211_crypto_getmcastkey() - the
+   key index is added to the 802.11 header and space is reserved between
+   the 802.11 header/payload and at the end for the encryption key data to be
+   added;
+ * Then when the driver transmits the frame, it calls ieee80211_crypto_encap()
+   to actually do the encryption.
+
+Some hardware will completely offload encryption, so although the key choice
+is made, various driver configuration options are set to inform net80211 not
+to add all the padding.  Others will offload encryption but require the
+space to be provided in the frame for the hardware/firmware to add the
+encryption information into.
+
+### What is IEEE80211_F_DATAPAD ?
+
+This is actually to support hardware such as the Atheros 802.11abgn chips,
+which have a 4 byte alignment requirement between the 802.11 header and
+the data payload (including the encryption parts.)
+
+Yes, it likely should be a more generic option.
+
+### Future work
+
+  * It would be nice to more formally define and enforce what drivers should be
+    doing with mbufs during the whole transmit lifecycle of an mbuf.
+  * Perhaps add a function or two for the drivers to use to
+    query whether a given mbuf has a TX notification attached (rather
+    than drivers querying M_TXCB) so they can individually
+    register for explicit notifications so they can provide more
+    accurate completion information.
+  * The fast frames age / flush routines should really be expanded to
+    be required functionality in net80211 drivers rather than optional
+    when IEEE80211_SUPPORT_SUPERG is enabled, so further software transmit
+    queue management is possible in net80211.
+
diff --git a/sys/net80211/DEBUG.md b/sys/net80211/DEBUG.md
new file mode 100644
index 000000000000..2231a0992fe6
--- /dev/null
+++ b/sys/net80211/DEBUG.md
@@ -0,0 +1,101 @@
+# Debugging in net80211
+
+This document describes how debugging is implemented in net80211.
+
+## Overview
+
+net80211 has run-time configurable debugging available. It is configured
+per-VAP.  It is implemented as a bitmask which can be controlled via a
+sysctl at runtime.
+
+Debugging is compiled in when IEEE80211_DEBUG is defined.
+
+There is currently no global debugging API available; top-level net80211
+code is typically using printf() or some wrapper around it (eg
+net80211_printf).
+
+The debug API is defined in (ieee80211_var.h).  This includes the
+debug field definitions and exported debugging API.  The actual implementation
+of the debugging routines is currently in (ieee80211_input.c) - see
+(ieee80211_note) for an example.
+
+The bitmap of available debugging sections is in (ieee80211_var.h), prefixed
+with IEEE80211_MSG .  See (IEEE80211_MSG_DEBUG) for an example.
+
+## Usage
+
+Calls to the debugging APIs should not include a terminating '\n' character.
+This will be added by the debug call.
+
+The simplest example is a call to IEEE80211_DPRINTF().  This takes a vap
+pointer, which debug option to log to, then the format string and optional
+arguments.  For example:
+
+```
+IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N, "%s: called!", __func__);
+```
+
+The debug flags can be combined together using bitwise OR so they are
+emitted if one or more debug options are set, for example:
+
+```
+IEEE80211_DPRINTF(vap, IEEE80211_MSG_11N | IEEE80211_MSG_ASSOC,
+    "%s: called!", __func__);
+```
+
+There are a number of different debugging calls that are designed to be
+used in different contexts.  Although they all currently end up printing
+to the same debug output, keeping them separate allows for future
+behavioural changes whilst minimising rototilling the whole codebase (eg
+allowing non-DPRINTF to turn into event tracing.)
+
+ * Straight up debugging should be done through IEEE80211_DPRINTF() .
+ * Debugging that's related to a specific ieee80211_node (eg a state
+   change for a specific node) should be done via a call to IEEE80211_NOTE() .
+ * Debugging that's related to a specific ethernet MAC address (eg
+   scan results) should be done via a call to IEEE80211_NOTE_MAC() .
+ * Debugging that should include a frame header should be done via
+   a call to IEEE80211_NOTE_FRAME().  Note this takes a (struct ieee80211_frame \*)
+   pointer.
+ * Debugging involving discarding frames (eg invalid frames) should be
+   done via a call to IEEE80211_DISCARD() .
+ * Debugging involving discarding frames due to an invalid / bad IE should
+   be done via a call to IEEE80211_DISCARD_IE().
+ * Debugging involving discarding frames due to a MAC address (eg ACL failure)
+   should be done via a call to IEEE80211_DISCARD_MAC().
+
+## Usage Notes
+
+ * It is required that the debugging be compiled in/out purely by defining or not
+   defining IEEE80211_DEBUG.  This can often trip up unused variable warnings
+   when debugging is disabled, so just double-check both configurations.
+
+ * It is important to ensure calls to the debugging (and any other logging API)
+   do not change any state/variables.  For example, do not call a function that
+   updates some counter or some state variable inside a call to IEEE80211_DPRINTF().
+   It won't be called at best and it will just be compiled out entirely at worst.
+
+## Configuration
+
+ * The 'vap->iv_debug' field is controlled by the OS specific module.
+ * In FreeBSD (ieee80211_freebsd.c) it is assigned a sysctl (net.wlan.X.debug)
+   during (ieee80211_sysctl_vattach).
+ * FreeBSD ships the wlandebug(8) tool to query and set this at runtime.
+
+## Implementation Details
+
+* The debug API goes out of its way to do the debug flag check before evaluating
+  function parameters and potentially assembling the logging output. See
+  (IEEE80211_DPRINTF) for an example.
+
+## Future work
+
+ * Top-level net80211 debugging APIs and control would be nice (for things
+   that are not specific to a VAP.)
+ * Drivers end up having to implement their own debugging API; it may be nice
+   to provide drivers a net80211 API to do their own driver specific logging.
+ * The debug macros should likely be refactored out to a new header file,
+   separate from ieee80211_var.h, so they can be more easily referenced.
+ * The debug fields should likely be refactored out into a new separate header
+   file that is designed to be consumed both by the kernel and by userland
+   utilities wishing to query/set the debug bitmask.
diff --git a/sys/net80211/PROTOCOL.md b/sys/net80211/PROTOCOL.md
new file mode 100644
index 000000000000..6d7c128bfc89
--- /dev/null
+++ b/sys/net80211/PROTOCOL.md
@@ -0,0 +1,563 @@
+# 802.11 protocol overview
+
+This is a quick overview of the 802.11 protocol and where it intersects with
+net80211.  It is not intended as a comprehensive deep dive into all of 802.11.
+
+TODO: link to appropriate sections in 802.11-2016 / 802.11-2020 depending upon
+which PDF is freely available.
+
+## 802.11 overview
+
+The 802.11 protocol / specification is a very large document which covers
+everything from the raw signals going out over the air up to how devices
+need to behave in different operating modes.
+
+The IEEE specification documents and amendments describe what devices should
+and must do in order to interoperate.  It's important to note that the
+intersection of "what the standard says" and "what devices do" is not always
+fully aligned.  The 802.11 specification has evolved over twenty-five years
+and for the most part this allows interoperability between the original 802.11b
+hardware and modern multi-band 802.11ax devices.
+
+It's also important to note that 802.11 is not just limited to the IEEE
+specifications.  802.11 devices are almost exclusively RF devices (if you
+read the specification you may find the old infrared / IR protocol definition!)
+and so need to operate inside of the radio regulatory rules defined by each
+country.  These define a wide variety of RF environmental behaviours
+including frequencies can be used, when devices can transmit, what transmit
+power is allowed, interoperability with other devices (802.11 and non-802.11)
+and radar interoperability.  For the purposes of this document these will
+be called "regulatory concerns" and will be covered elsewhere.
+
+The 802.11 specification breaks things up into a handful of top level areas:
+
+ * the PHY layer - how the device interfaces with the RF environment and
+   encodes/decodes RF transmissions into data streams.
+ * the MAC layer - defines how data is packetized into individual data frames,
+   exchanged with the upper layer (ethernet/bridge), deciding when and what
+   to transmit via the PHY layer.
+ * MLME - (MAC layer management entities) - defines all of the state methods
+   and transitions that underpin the 802.11 MAC state machine.
+ * Security - the cipher and key management components.
+ * PHY specifications - the specific implementations of PHYs - 2GHz DSSS
+   (spread spectrum), 2GHZ CCK, OFDM, ERP, 802.11n / HT, 802.11ac / VHT, etc.
+
+Most 802.11 implementations do not implement a 1:1 definition of each of these
+layers - notably implementing every single MLME state would be a huge amount
+of work.
+
+## 802.11 revisions
+
+There have been many revisions of the 802.11 specification. The specifications
+can be found online at https://www.ieee802.org/11/.
+
+The latest specification being implemented in net80211 is 802.11-2020, however
+net80211 is far from completely compliant.  Generally new code which implements
+802.11 features / protocol handling should identify the specification and
+section which it is referencing.
+
+## 802.11 protocol and frame definitions
+
+net80211 keeps most 802.11 frame and protocol definitions in a single location
+(ieee80211.h).
+This contains descriptions of the 802.11 frame and field definitions, ranging
+from the lowest definition of the frame itself up through frame types/subtypes,
+individual field definitions, information elements, action frames, and
+anything else that can be found in the 802.11 specifications.
+
+The PHY definitions can be found in (ieee80211_phy.c) and (ieee80211_phy.h).
+Notably those include the frame timing information useful for rate control
+and frame duration calculations.
+
+## 802.11 Revisions
+
+(TBD)
+
+### Legacy 802.11
+
+The earliest 802.11 devices implement 1Mbit/s and 2Mbit/s direct spread spectrum
+frames.  These include the earliest Wavelan devices.  These are grandfathered
+into 802.11b.  The PHY specification can be found in 802.11-2020 Section 15.)
+
+### 802.11b
+
+802.11b devices implement Section 15 (1Mbit/2Mbit) PHYs as well as the high
+rate DSSS specification (802.11-2020 Section 16) to provide 5.5Mbit and 11Mbit
+CCK rates.  They interoperate with legacy 802.11 devices by using compatible
+PHY encodings and will limit their performance if said legacy devices are
+detected.
+
+### 802.11a
+
+802.11a devices implement OFDM rates from 6Mbit/s to 54Mbit/s on the 5GHz
+band.  Among other features, it also defines 5MHz and 10MHz wide channel
+behaviour.  This is covered in the OFDM PHY specification (802.11-2020
+Section 17.)
+
+### 802.11g
+
+802.11g devices implement OFDM rates from 802.11a, the CCK rates from 802.11b
+and the DSSS rates from legacy 802.11.  These are covered in the ERP
+specification (802.11-2020 Section 18.) There are some MAC extensions for
+negotiating 802.11b / 802.11g interoperability and these are documented
+throughout the MAC specification.  This also specifies support for 5MHz and
+10MHz wide channels.
+
+### 802.11n (HT)
+
+802.11n introduced a variety of high throughput rates and feature support
+(hence why it's called HT - high throughput).  It introduces higher density
+OFDM rate encodings, 20 and 40MHz wide channels with interoperability for
+earlier devices, packet aggregation via A-MPDU and A-MSDU, MIMO (multiple input,
+multiple output spatial streams), some initial beamforming support, power
+saving extensions and more.
+
+The physical layer support is covered in the HT PHY specification (802.11-2020
+Section 19.)  The rest of the MAC extensions are documented throughout the
+rest of the specification.
+
+### 802.11ac (VHT)
+
+802.11ac extends the 802.11n specification (hence why it's VHT - Very
+High Throughput) and boosts performance by adding higher density OFDM QAM
+encoding (256-QAM), wider channels (80MHz, 160MHz), split 80+80MHz channel
+support, much larger A-MSDU / A-MPDU frame sizes, support for MU-MIMO
+(multi-user MIMO) allowing APs to transmit to multiple STAs at the same time
+and various other extensions.
+
+It builds on top of the 802.11n MAC and PHY specification, so a lot of
+802.11n feature and MAC negotiation happens as part of 802.11ac negotiation.
+
+The PHY layer is covered in the VHT PHY Specification (802.11-2020 Section
+21.)  Again, the rest of the MAC extensions are documented throughout the
+rest of the specification.
+
+### Greenfield versus backwards compatibility
+
+The various protocols supported by 802.11 build on top of earlier protocols.
+So typically you're not building a single implementation for each protocol -
+for example, you can't handle 802.11ac support without implementing a large
+amount of 802.11n support.
+
+(As a side note, the 802.11 frame has a protocol version field, and
+that actually changed in 802.11ah (900MHz and longer distance bands) -
+which changes a lot of what the fields do.  No, net80211 currently does not
+support 802.11ah and will drop frames whose 802.11 protocol ID is not
+supported.)
+
+At the PHY layer, later model hardware can transmit data encodings which
+earlier model hardware just won't recognise.  All they'll see is an increase
+in RF power on the channel at best and signals that will confuse the
+RX decoder / cause hardware issues at worst.)
+
+So each of the PHY specifications will lay out a few things:
+
+ * How frames should be encoded in the air in a way that earlier
+   hardware can decode them enough to know it's not for them;
+ * How devices can identify that earlier protocol devices are around and
+   change the configuration (eg STA changing its own configuration,
+   AP changing the configuration of the network it controls, etc)
+   to provide backwards compatibility.
+
+These come at a performance cost.  For example, an 802.11g AP which
+supports 802.11b and 802.11 devices needs to notice that an 802.11b
+device wishes to associate, and when it sees this, change some of
+its configuration (notably "long preamble" so 802.11b devices can
+decode frames that are being transmitted, whether destined to it or not.)
+
+Various devices allow backwards compatbility to be configured.
+For example, an 802.11n AP may be configured to deny non-802.11n clients.
+This may improve performance but then earlier clients can't connect.
+
+In 802.11n deployments this was known as a "greenfield deployment".
+This typically disables any and all pre-11n interoperability at both
+a MAC and PHY layer.  net80211 has some flags for this to specifically
+inform devices that they can configure the hardware for such a setup.
+Not all drivers implement it however, and in a lot of cases they will
+still handle pre-11n framing, even if the net80211 code will deny
+association.
+
+There are other components to backwards compatibility which are worth
+keeping in mind when reading through the 802.11 specification and
+net80211 stack / driver code.  These include:
+
+ * short/long preamble - (vap_update_preamble)
+ * short/long slot time configuration - (vap_update_slot)
+ * 802.11g protection mode (vap_update_erp_protmode) -
+   whether to use CTS-to-self around each transmission
+ * 802.11n protection mode (vap_update_ht_protmode) -
+   whether to use RTS/CTS around each transmission
+ * 802.11n 20/40MHz BSS operation (whether an 802.11n AP sees other APs that
+   overlap its frequency range and need to reconfigure how to protect
+   transmissions)
+
+## How 802.11 (very briefly) works over the air
+
+This is a very brief and not at all comprehensive overview of how 802.11
+works over the air.  The goal of this section is to provide enough background
+information to help de-mystify reading the net80211 stack and wireless
+driver source.
+
+### Why there's timing requirements in the first place
+
+Each of the PHY sections in the 802.11 specification describe what
+the PHY needs to do in order to transmit and receive data. It's not
+anywhere as easy as "toggle some bits on a wire".
+
+An important thing to understand is that hardware isn't immediate.
+All the state machines in your 802.11 devices take non-zero time
+to make decisions about when to transmit, when to receive, locking
+onto a signal, deciding it can be decoded, getting reset for the next
+frame, etc.
+
+So a lot of what you'll see in 802.11 negotiation and feature support
+is linked to the underlying hardware implementations and limitations
+of the time.  For example the 802.11b specification defines the slot time
+as 20uS, but the 802.11g specification lowers it to 9uS.  The "slot time"
+value defines the unit of time used for contention management / backoff, and
+it's defined partly by what the speed of light dictates (ie how big
+of a physical area you want to be able to "hear" in determining if the
+area is busy) and how quickly the hardware can guarantee to respond.
+It dropped to 9uS because hardware got better, but to interoperate
+with older devices without starting to transmit before they're
+ready to react, 802.11g devices will fall back to 20uS slot time when
+they detect an 802.11b device.
+
+This carries through everywhere in odd places that you're not necessarily
+aware of.  For example, the 802.11n A-MPDU definition includes negotiated
+padding between frames and limits encryption ciphers (typically CCMP or
+GCMP.)  This is due to hardware support - the MAC may be able to support
+much less padding when no encryption is used, but setting up / resetting
+the encryption / decryption blocks may take more time and thus larger
+A-MPDU padding values are negotiated.
+
+### Wait, the speed of light?
+
+Yes.  The speed of light is roughly 300 metres for each microsecond of
+travel time.
+
+### Preambles, SIGs, PLCP, sending actual data and waiting / slot times
+
+There are a few things that are worth understanding at a high level.
+
+ * The first thing that a device needs to do is determine
+   whether the air is busy or free.  There'll be some hardware
+   to determine the signal level versus noise floor and provide
+   a signal to the transmit hardware that the air is free,
+   and to the receiver that it may want to try start decoding
+   something.
+
+ * The receiver needs to get in synchronisation with the transmitter.
+   This is a one way operation - the transmitter needs to transmit
+   enough of a signal that the receiver can "lock onto" and get itself
+   ready for further data.  This is called the "preamble" - it's
+   typically a low bitrate repeating pattern of data that gives
+   the receiver hardware time to lock onto, figure out the signal
+   level and be ready for the next phase.
+
+ * Note that the receiver may pick up the preamble at any point in its
+   transmission so it can't guarantee it will see exactly "x" bits of some
+   repeating pattern.
+
+ * Then there's other bits and pieces - eg look for L-SIG, HT-SIG
+   in the PHY documentation - which is used to further synchronise
+   what's about to happen.
+
+ * Finally it will start transmitting the PHY framing bits needed to
+   identify what the upcoming transmit rate and configuration is
+   (all the stuff leading up to the PLCP header, then the PLCP header.)
+
+Things get more complicated with MIMO, MU-MIMO, 802.11ax OFDM-A, etc but
+don't worry about those for now - they build on top of all of these
+ideas.
+
+Once the data is transmitted, there's some quiet time between frames
+before the receiver can ACK (and then a period of time where an ACK
+is expected.)  The transmitter needs to finish transmitting, then
+reset its internal state back to idle to be ready to receive - and
+there's the pesky speed of light speed of 300m per microsecond -
+so there's some MAC (interframe spacing) and PHY (slot time) enforcing
+quiet so everyone has a chance to receive the frame and the reciver
*** 442 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a13a6d7.4361b.5c217572>