IEEE80211_PROTO(9)
π ieee80211_proto β 802.11 state machine support π
okay bestie, welcome to IEEE80211_PROTO(9), straight out of the Kernel Developer's Manual π«Ά this one is the 802.11 state machine page and it's lowkey the blueprint for how net80211 drivers behave, so grab a snack and let's get into it β¨
πΈ SYNOPSIS πΈ
#include <net80211/ieee80211_var.h>
void
ieee80211_start_all(struct ieee80211com *);
void
ieee80211_stop_all(struct ieee80211com *);
void
ieee80211_suspend_all(struct ieee80211com *);
void
ieee80211_resume_all(struct ieee80211com *);
enum ieee80211_state;
int
ieee80211_new_state(struct ieee80211vap *, enum ieee80211_state, int);
void
ieee80211_wait_for_parent(struct ieee80211com *);
β¨ DESCRIPTION β¨
so the net80211 layer that backs 802.11 device drivers runs a whole state machine to control how vaps operate. and no, it's not one single machine β these state machines change depending on what mode the vap is in. station mode state machines follow the 802.11 MLME states from the protocol spec, very by-the-book π . the other state machines are simpler and just reflect whatever operational work is happening, like scanning for a BSS or auto-picking a channel to run on. when you've got multiple vaps live at once, the state machines coordinate stuff like channel selection. and plot twist β the state machine mechanism is also what binds the net80211 layer to a driver, which we get into below π
these are the states defined for the state machines:
IEEE80211_S_INITβ the default/initial state. a vap sitting here should not be holding onto any dynamic state (think entries for associated stations in the node table, that kind of thing). the driver has to quiesce the hardware, meaning no interrupts should be firing. silence. periodt π€«IEEE80211_S_SCANβ scanning for a BSS, or choosing a channel to operate on. ngl scanning can also happen in other states (like when background scanning is active), but this state is what you enter when you're initially bringing a vap up to an operational state, or after an event like a beacon miss (in station mode).IEEE80211_S_AUTHβ authenticating to an access point (in station mode). you normally get here fromIEEE80211_S_SCANafter selecting a BSS, but you can also arrive fromIEEE80211_S_ASSOCorIEEE80211_S_RUNif the authentication handshake fails πIEEE80211_S_ASSOCβ associating to an access point (in station mode). you reach this fromIEEE80211_S_AUTHafter a successful auth, or fromIEEE80211_S_RUNif a DisAssoc frame shows up uninvited.IEEE80211_S_CACβ doing Channel Availability Check (CAC). this state only ever gets entered when DFS is enabled and the channel picked for operation requires CAC. very exclusive, very conditional β¨IEEE80211_S_RUNβ operational, the main character state π here a vap can transmit data frames, accept requests for stations associating, all of it. β οΈ but beware: data traffic is also gated by whether the associated "port" is authorized. when WPA/802.11i/802.1x is operational, authorization can happen separately β like in station mode,wpa_supplicant(8)has to finish the handshakes and plumb the necessary keys before a port is authorized. in this state a BSS is operational and associated state is valid and usable; for exampleic_bssandic_bsschanare guaranteed to be usable. iconic.IEEE80211_S_CSAβ a Channel Switch Announcement (CSA) is pending. this one is only reached fromIEEE80211_S_RUN, either when a CSA is received from an access point (station mode) or when the local station is getting ready to change channel. in this state traffic may be muted depending on the Mute setting in the CSA πIEEE80211_S_SLEEPβ asleep to save power (in station mode). only reached fromIEEE80211_S_RUN, and only when power save operation is enabled and the local station is deemed sufficiently idle to drop into low power mode π΄
heads up bestie: the states are ordered, exactly as listed above. so a vap has to be inIEEE80211_S_RUNor "greater" before it can transmit frames. and some net80211 data is only valid in certain states β for exampleiv_bsschan, which specifies the channel for the operating BSS, should never be used except inIEEE80211_S_RUNor greater. don't do it. i'm serious π
π¦ STATE CHANGES π¦
state machine changes are typically handled internally by the net80211 layer, reacting to ioctl(2) requests, received frames, or external events like a beacon miss. the ieee80211_new_state() function is what you call to kick off a state machine change on a vap β you hand it the new state plus an optional argument.
the request first gets processed to coordinate across multiple vaps. for example, only one vap at a time can be scanning: if several vaps ask to move to IEEE80211_S_SCAN, the first one gets to run and the rest get deferred until the scan operation finishes, at which point the selected channel gets adopted. same energy with combinations of vaps, like an AP plus a station vap, where the station might need to roam to follow the AP it's associated to β dragging the AP vap along to the new channel π§³. another important coordination is how IEEE80211_S_CAC and IEEE80211_S_CSA get handled. and fr fr: no more than one vap can ever be actively changing state at a time. in fact net80211 single-threads the state machine logic into a dedicated taskqueue(9) thread, which is also used to synchronize work like scanning and beacon miss handling. one thread, zero chaos, we love to see it π
once the multi-vap scheduling/coordination is done, the per-vap iv_newstate method is called to actually do the state change work. drivers use this entry to set up private state and then dispatch the call back to the net80211 layer using the previously defined method pointer β in OOP-parlance, they call the "super method" π¦Έ
net80211 handles two state changes specially:
- on transition to
IEEE80211_S_RUN, theIFF_DRV_OACTIVEbit on the vap's transmit queue is cleared so traffic can flow π - on transition to
IEEE80211_S_INIT, any state in the scan cache associated with the vap is flushed, and any frames pending on the transmit queue are flushed too π§Ή
π DRIVER INTEGRATION π
drivers are expected to override the iv_newstate method so they can interpose their own code and handle the setup work that state changes require. other than that, drivers must call ieee80211_start_all() in response to being marked up through an SIOCSIFFLAGS ioctl request, and they should use ieee80211_suspend_all() and ieee80211_resume_all() to implement suspend/resume support.
there's also an ieee80211_stop_all() call that forces all vaps into an IEEE80211_S_INIT state β but a driver shouldn't need it. control is usually handled by net80211, or in the case of card eject or vap destroy, work gets initiated outside the driver. so like, not your problem, bestie π
π SEE ALSO π
β HISTORY β
the state machine concept was part of the original ieee80211 code base that first appeared in NetBSD 1.5. a true OG π«Ά
and that's the whole page, bestie π this one came from the Debian crew, dated August 4, 2009 β shoutout to the kernel devs, they ate and left no crumbs πβ¨
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 2009 Sam Leffler, Errno Consulting
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms