mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
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
This commit is contained in:
1 parent
1ccaef9867
commit
490c53e935
6 files changed
+1355
-1
No files matched your search
@@ -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.)
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
gets ready to receive. Then if there's an ACK, the ACK happens.
|
||||
|
||||
### PLCP header
|
||||
|
||||
Once all of the preamble, SIG/training stuff is done, the transmitter
|
||||
will send a PLCP header with information about the transmitter
|
||||
type and rate (and that's very handwaving it.) net80211 has definitions
|
||||
for the plcp header (ieee80211_plcp_hdr) but it's highly unlikely it will
|
||||
be relevant or available in modern devices.
|
||||
|
||||
### How data is encoded - encoding rates, symbols, guard intervals
|
||||
|
||||
Now, once the transmitter has sent all of that, it will start to send
|
||||
actual data encoded at the desired transmit rate. The data bits
|
||||
that you're transmitting go through a variety of encoding schemes
|
||||
before they're turned into bits that are clocked out at the 802.11
|
||||
physical layer (think "forward error correction" as an example),
|
||||
but they're turned into what are known as "symbols".
|
||||
|
||||
A symbol can be thought of as a group of bits encoded in one specific
|
||||
RF representation. Explaining all the details isn't in scope of this
|
||||
document (and I encourage interested parties to do a quick dive
|
||||
into information theory!) but there are a couple of important higher
|
||||
level concepts to understand here that influence what happens
|
||||
later on in packet delivery.
|
||||
|
||||
For OFDM encoding:
|
||||
|
||||
* Each symbol is preceded by a quiet time called a guard interval, to make
|
||||
sure any reflections don't interfere with the upcoming symbol;
|
||||
* Each symbol is then transmitted for a specific length of time to make sure
|
||||
it's received by everyone inside the desired area (again light = 300m/sec
|
||||
per microsecond);
|
||||
* All symbols for a given 802.11 MPDU are sent at the exact same rate;
|
||||
* This is repeated until all the symbols are transmitted.
|
||||
|
||||
The higher the data rate used, the higher the signal level needs to be
|
||||
and lower the tolerance it has to interference. Forward error correction
|
||||
can only do so much, and the higher throughput rate encodings sacrifice
|
||||
FEC for throughput.
|
||||
|
||||
Once an uncorrectable error occurs and the frame fails CRC, the whole MPDU is
|
||||
dropped by the receiver.
|
||||
|
||||
Part of why A-MPDU is so important for high throughput is that the
|
||||
errors are limited to a single MPDU in the burst of MPDUs. Ie, if
|
||||
the transmitter sends ten MPDUs in a single A-MPDU, and five of them
|
||||
have uncorrectable errors, then five .. well, didn't. This means
|
||||
the receiver can ACK some but not all of the MPDUs, and the transmitter
|
||||
can re-send those with new MPDUs.
|
||||
|
||||
The default guard interval is 800ns. 802.11n allows for negotiating
|
||||
shorter guard interval (400ns) which can be done per device in a BSS.
|
||||
An 800ns guard interval is a little short of 300 metres, and 400ns is
|
||||
a little short of 150 metres - so using short guard interval means
|
||||
you trade increased performance for potential decreased performance
|
||||
if you have reflections or stations more than 150 metres away.
|
||||
|
||||
802.11ax adds support for 1.6us and 3.2us guard intervals for physically
|
||||
larger deployments.
|
||||
|
||||
### MAC layer framing
|
||||
|
||||
The MAC layer handles data that is encapsulated in the given transmit
|
||||
rate that was established in the PHY (PLCP) header. This includes
|
||||
the 802.11 MAC header, CRC trailer, any of the cipher processing that
|
||||
happens in between. In the case of 802.11n, it can encapsulate
|
||||
multiple frames being sent back to back in a single transmission.
|
||||
|
||||
Devices which do partial / no offload will typically produce and
|
||||
consume 802.11 MAC layer frames to the driver and net80211.
|
||||
It's thus important to understand MAC framing and frame types.
|
||||
|
||||
### MPDU versus MSDU
|
||||
|
||||
An MSDU (MAC service data unit) is an individual frame (think "802.2/802.3
|
||||
ethernet") passed from the network stack into net80211.
|
||||
|
||||
An MPDU (MAC protocol data unit) is one or more MSDU frames wrapped by an
|
||||
(ieee80211_frame) header and CRC trailer. It is what is eventually
|
||||
encapsulated inside the PHY framing (preambles, training symbols, PLCP
|
||||
header, etc) and sent over the air.
|
||||
|
||||
Notably an 802.11 MPDU isn't just an IPv4/IPv6 frame with an 802.11
|
||||
header/trailer - it is a full ethernet frame that is being wrapped
|
||||
by 802.11 framing.
|
||||
|
||||
### Tracking airtime with NAV
|
||||
|
||||
802.11 devices have to interoperate in a shared medium. Earlier protocol
|
||||
definitions require one transmitter at a time. Later specification
|
||||
devices (MU-MIMO with 802.11ac, OFDM-A with 802.11ax, etc) introduce the
|
||||
ability for devices to transmit and receive simultaneously.
|
||||
|
||||
The simplest way to track this is with NAV (network access vector.)
|
||||
The NAV implementation in pre-11ax devices is a single counter which
|
||||
counts down to zero. Once it is zero, the air is considered "available"
|
||||
to attempt to check to transmit on. The transmitter will also check
|
||||
whether the air is busy (ie can it detect any signals present) before
|
||||
it transmits - this is called CCA (clear channel access) and is
|
||||
typically implemented in hardware.
|
||||
|
||||
The duration field in (ieee80211_frame) is a microsecond field which
|
||||
covers the whole duration of the frame being transmitted. Receivers
|
||||
that decode the frame - even if it's not destined to them! - will listen
|
||||
to the NAV and add it to their own NAV.
|
||||
|
||||
All 802.11 frames have a duration field.
|
||||
|
||||
### Fragmented frames
|
||||
|
||||
(TBD)
|
||||
|
||||
### Sequence counters and duplication detection
|
||||
|
||||
(TBD)
|
||||
|
||||
### EDCA and QoS
|
||||
|
||||
(TBD)
|
||||
|
||||
### Inter-frame spacing (IFS)
|
||||
|
||||
(TBD)
|
||||
|
||||
## 802.11 frame layout
|
||||
|
||||
An individual 802.11 frame contains frame control (version, type, subtype),
|
||||
duration, addressing, sequence number and optional QoS information.
|
||||
The basic definition is available at (ieee80211_frame) but other definitions
|
||||
are also possible - (ieee80211_qosframe), (ieee80211_frame_addr4),
|
||||
(ieee80211_qosframe_addr4).
|
||||
|
||||
It then has a 4 byte CRC32 trailer appended at the end.
|
||||
|
||||
### Addressing types and traffic direction
|
||||
|
||||
(TBD - 3addr, 4addr, each of the fields, etc)
|
||||
|
||||
### QoS versus non-QoS frames
|
||||
|
||||
(TBD)
|
||||
|
||||
### RTS/CTS exchange and airtime
|
||||
|
||||
(TBD)
|
||||
|
||||
### CTS-to-self / OFDM protection
|
||||
|
||||
CTS to self is a concept introduced in 802.11g. The general idea is that a
|
||||
transmitter can send a CTS to its own MAC address for the duration that it
|
||||
wishes to transmit for. Since the CTS frame is transmitted at a slower
|
||||
legacy rate, it both reserves airtime in any receiver in earshot, and
|
||||
it is understood by older 11b only devices which do not understand 11g.
|
||||
|
||||
This ends up also being useful for 11n, 11ac etc to interoperate with
|
||||
earlier devices, but they typically rely on a normal RTS exchange.
|
||||
|
||||
### Data frames
|
||||
|
||||
(TBD)
|
||||
|
||||
### Management frames
|
||||
|
||||
(TBD)
|
||||
|
||||
### Control frames
|
||||
|
||||
(TBD)
|
||||
|
||||
Notably, control frames do not have a sequence number and so can't be
|
||||
de-duplicated.
|
||||
|
||||
### Action frames
|
||||
|
||||
(TBD)
|
||||
|
||||
## Frame combinations
|
||||
|
||||
There are various ways that 802.11 frames are combined together to improve
|
||||
performance.
|
||||
|
||||
### ACK, Delayed Block-ACK, Immediate Block-ACK
|
||||
|
||||
(TBD)
|
||||
|
||||
### Atheros Fast Frames
|
||||
|
||||
(TBD)
|
||||
|
||||
### A-MSDU
|
||||
|
||||
(TBD)
|
||||
|
||||
### A-MPDU
|
||||
|
||||
(TBD)
|
||||
|
||||
## Security / Encryption
|
||||
|
||||
This is a much larger topic, however it's worth touching on the basics here to
|
||||
understand how frames are redirected into the security/encryption paths in
|
||||
net80211 and what devices may do with said frames.
|
||||
|
||||
### WEP, IV header and keys
|
||||
|
||||
WEP is an obsolete encryption method dating back to the earliest 802.11b
|
||||
specifications. It involves a 4 byte header which includes
|
||||
|
||||
* a 24 bit IV (initialisation vector);
|
||||
* a 2 bit field indication which of four keys to use;
|
||||
* A CRC at the end.
|
||||
|
||||
It's relevant today because later cipher frame formats still use the IV
|
||||
header - they're just extended to include more information. Notably, the
|
||||
four key indexes are typically implemented and used in hardware, and have
|
||||
different meanings depending upon the kind of traffic being handled.
|
||||
|
||||
### WPA/WPA2 management
|
||||
|
||||
This is handled in userland. The 802.11 specification covers everything
|
||||
involved in key exchange and management but it's out of scope for this 802.11
|
||||
overview documentation.
|
||||
|
||||
### CCMP, GCMP, TKIP frames
|
||||
|
||||
These later ciphers still use the WEP header, but they then add extra bytes
|
||||
to it to include the larger sequence number space, other options needed
|
||||
for said ciphers, and a larger trailer for CRC and TKIP MIC.
|
||||
|
||||
### IV duplication / tracking
|
||||
|
||||
net80211 tracks the received IV / sequence number for each station indexed
|
||||
by QoS TID. Anything with an earlier IV is discarded as a stale packet or
|
||||
potential replay attack. See the ni_txseqs[] and ni_rxseqs[] field in
|
||||
(ieee80211_node).
|
||||
|
||||
Note that the 802.11 layer sequence number field will apply /first/. Traffic
|
||||
which the 802.11 input layer thinks is old or retransmits will be discarded
|
||||
before handed to the net80211 crypto routines.
|
||||
|
||||
### Unicast vs Group Keys
|
||||
|
||||
WEP has four global keys which are shared between all devices wishing to
|
||||
communicate. The keys are provided in the WEP header.
|
||||
|
||||
However for later ciphers the four key indexes start taking on new meanings.
|
||||
Notably key index 0 is the "unicast key" which handles traffic for a given
|
||||
station and is unique for that station, and keys 2 and 3 are used for
|
||||
group keys - shared keys for broadcast traffic that all stations need to be
|
||||
able to decrypt.
|
||||
|
||||
(key 1 is also used for unicast station traffic for seamless station key
|
||||
updating, but net80211 currently doesn't support this extension/feature.)
|
||||
|
||||
There's also upcoming work for encrypted management traffic and encrypted
|
||||
beacons which reuse the key indexes for their traffic, but then don't treat
|
||||
them as "global keys" - they start being treated as "global keys but only
|
||||
for this traffic type."
|
||||
|
||||
It's important to understand the difference between global keys (WEP) versus
|
||||
group and unicast keys (everything else) when looking through the net80211
|
||||
data and encryption handling paths.
|
||||
|
||||
## 802.11 Operating Modes
|
||||
|
||||
(TBD)
|
||||
|
||||
### Station
|
||||
|
||||
(TBD)
|
||||
|
||||
### Access Point
|
||||
|
||||
(TBD)
|
||||
|
||||
### IBSS / Ad-Hoc
|
||||
|
||||
(TBD)
|
||||
|
||||
### Mesh / 802.11s
|
||||
|
||||
(TBD)
|
||||
@@ -0,0 +1,139 @@
|
||||
# net80211
|
||||
|
||||
This is the 802.11 wireless stack for FreeBSD.
|
||||
|
||||
## Introduction
|
||||
|
||||
The net80211 subsystem implements the 802.11 protocol and support infrastructure.
|
||||
It supports a variety of device types, 802.11 protocols, operating modes and
|
||||
security extensions.
|
||||
|
||||
net80211 handles the 802.11 state machine, interface management, node management,
|
||||
virtual interfaces, packet encapsulation and de-encapsulation and basic
|
||||
security key management.
|
||||
|
||||
The userland ioctl() API provides control mechanisms for the above and is how
|
||||
management tooling (ifconfig, libifconfig) and management services (hostapd,
|
||||
wpa_supplicant) interfaces with the net80211 stack.
|
||||
|
||||
The security state machine and key management (802.1x, WPA, etc) are handled
|
||||
by management services.
|
||||
|
||||
Drivers can implement as much or as little of the 802.11 infrastructure as
|
||||
needed. net80211 support drivers from full-offload (ie, supplying ethernet
|
||||
encapsulated/de-encapsulated frames with management control via driver
|
||||
methods) down to fully software controlled devices (ie, the hardware
|
||||
is minimal and all 802.11 packet handling, state machine, reordering, security,
|
||||
etc is handled by net80211.)
|
||||
|
||||
## Overview
|
||||
|
||||
net80211 consists of a few top level design modules:
|
||||
|
||||
* The 802.11 device representation and functions (ieee80211com), used
|
||||
in conjunction with an 802.11 device driver to represent the physical device.
|
||||
|
||||
* The 802.11 virtual interface representation and functions (ieee80211vap),
|
||||
used to represent instances of virtual interfaces.
|
||||
|
||||
* A representation of 802.11 stations/nodes (ieee80211_node), which
|
||||
keep the state of each 802.11 station/node that the stack knows about.
|
||||
|
||||
* Encryption handling (ieee80211_crypto), handling 802.11 frame encryption,
|
||||
decryption and session/state tracking.
|
||||
|
||||
* Regulatory domain (ieee80211_regdomain), which implements the 802.11
|
||||
regulatory domains, allowed frequencies, operating modes and transmit power.
|
||||
|
||||
* Radar detection (ieee80211_dfs.c), tracking the state of radar detection and
|
||||
interoperability in the 5GHz frequency range.
|
||||
|
||||
* Transmit rate control (ieee80211_ratectl.c) implements software and
|
||||
firmware based rate control for devices that don't implement full rate control
|
||||
offload.
|
||||
|
||||
* Power save support (ieee82011_power.c) implements various power saving
|
||||
mode features and support for devices which do not fully implement offloaded
|
||||
power management.
|
||||
|
||||
* Operating system specific interfaces (ieee80211_freebsd.c) which implement
|
||||
the bulk of the operating system specific glue (logging, memory allocation,
|
||||
network interfaces, etc.)
|
||||
|
||||
* The configuration interface (ieee80211_ioctl.c) which implements the ioctl
|
||||
API used by userland to configure and monitor the state of the 802.11 stack
|
||||
and devices.
|
||||
|
||||
In addition, each operating mode (adhoc, station, AP, WDS, mesh) have their own
|
||||
modules that implement the state machines and functionality required for 802.11.
|
||||
|
||||
## Portability
|
||||
|
||||
Although net80211 attempts to keep most OS specific components in a single file
|
||||
(ieee80211_freebsd.c), it is not currently perfect.
|
||||
|
||||
Notably:
|
||||
|
||||
* There are still plenty of FreeBSD-isms located throughout the source code,
|
||||
including BSD specific includes, network APIs, etc.
|
||||
|
||||
* The interface and networking model is still very BSD, including using the
|
||||
system implementation of mbufs.
|
||||
|
||||
When developing for net80211 please keep in mind that other operating systems
|
||||
(such as DragonflyBSD) and third parties do leverage this codebase.
|
||||
Try to keep all FreeBSD specific components in ieee80211_freebsd.[ch].
|
||||
|
||||
## Protocol Overview
|
||||
|
||||
A basic protocol overview is available at (@ref md_net80211_PROTOCOL).
|
||||
|
||||
The most comprehensive overview is the 802.11 protocol document itself,
|
||||
but it is very large and implementations do not always correspond 1:1
|
||||
with the protocol definitions.
|
||||
|
||||
## Functional Overview
|
||||
|
||||
(TODO)
|
||||
|
||||
* Module layout
|
||||
* Logging
|
||||
* Debugging - (@ref md_net80211_DEBUG)
|
||||
* Top-level device layout (ieee80211com)
|
||||
* Data / Control Path Overview (@ref md_net80211_DATAPATH_TRANSMIT), (@ref md_net80211_DATAPATH_RECEIVE)
|
||||
* Deferred work
|
||||
* Regulatory
|
||||
* Virtual interfaces
|
||||
* Operating Modes
|
||||
* Nodes
|
||||
* Node tables, node table iteration
|
||||
* Device and VAP states
|
||||
* Node states
|
||||
* Operating modes
|
||||
* Cipher management
|
||||
* Radar detection
|
||||
* ioctl interface
|
||||
* ACL support
|
||||
* Scanning, Scan Modules
|
||||
* Power Management
|
||||
* Transmit Path
|
||||
* Receive Path
|
||||
* A-MSDU Fast Frames
|
||||
* A-MPDU
|
||||
* Radiotap
|
||||
* Monitor Mode
|
||||
|
||||
## Driver Overview
|
||||
|
||||
(TODO)
|
||||
|
||||
* Introduction
|
||||
* Driver Structure
|
||||
* Setup and Attach
|
||||
* Virtual Interfaces
|
||||
* Control Path
|
||||
* Data Path
|
||||
* VAP state
|
||||
* Device State
|
||||
* Suspend and Resume
|
||||
|
||||
@@ -9,7 +9,8 @@ EXTRACT_ALL = YES # for undocumented src, no warnings enabled
|
||||
#--------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = $(DOXYGEN_SRC_PATH)/net80211/ $(NOTREVIEWED)
|
||||
INPUT = $(DOXYGEN_SRC_PATH)/net80211/
|
||||
USE_MDFILE_AS_MAINPAGE = $(DOXYGEN_SRC_PATH)/net80211/README.md
|
||||
|
||||
GENERATE_TAGFILE = net80211/net80211.tag
|
||||
|
||||
|
||||
Reference in new issue
Block a user