IEEE80211_PROTO(9)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

✨ NAME ✨

ieee80211_proto(9) β€” 802.11 state machine support. Bestie, welcome to the net80211 state machine era πŸ’–

πŸ¦‹ SYNOPSIS πŸ¦‹

Copy these exactly, okay? Signatures are not a vibe to freestyle.

#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 πŸ’–

Okay so the net80211 layer β€” the one that backs 802.11 device drivers β€” runs a state machine to control how vaps operate. The exact state machine changes with the vap operating mode. Station mode state machines follow the 802.11 MLME states from the protocol spec. Other state machines are simpler and track operational stuff like scanning for a BSS or automatically picking a channel to operate on. When multiple vaps are live, the state machines coordinate things like choosing a channel. The state machine mechanism also binds the net80211 layer to a driver β€” more on that below, iykyk.

πŸŽ€ the states, in order πŸŽ€

Here are the states these machines can be in, bestie:

  • IEEE80211_S_INIT β€” the default/initial state. A vap sitting here should not be holding any dynamic state β€” think entries for associated stations in the node table. The driver must quiesce the hardware; like, there should be no interrupts firing, periodt.
  • IEEE80211_S_SCAN β€” scanning for a BSS or choosing a channel to operate on. Heads up: scanning can also happen in other states (e.g. when background scanning is active). This state gets entered when you’re initially bringing a vap 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). Normally you get here from IEEE80211_S_SCAN after selecting a BSS, but you can also land here from IEEE80211_S_ASSOC or IEEE80211_S_RUN if the authentication handshake fails. Messy, but iconic.
  • IEEE80211_S_ASSOC β€” associating to an access point (in station mode). You reach it from IEEE80211_S_AUTH after successfully authenticating, or from IEEE80211_S_RUN if a DisAssoc frame shows up.
  • IEEE80211_S_CAC β€” doing Channel Availability Check (CAC). You only enter this state when DFS is enabled and the channel selected for operation requires CAC.
  • IEEE80211_S_RUN β€” operational. A vap in this state can transmit data frames, accept requests for stations associating, etc. Beware: data traffic is also gated by whether the associated β€œport” is authorized. When WPA/802.11i/802.1x is operational, authorization may happen separately β€” e.g. in station mode wpa_supplicant(8) must complete 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 may be used; e.g. ic_bss and ic_bsschan are guaranteed to be usable. Yes bestie, guaranteed.
  • IEEE80211_S_CSA β€” a Channel Switch Announcement (CSA) is pending. This state is reached only from IEEE80211_S_RUN β€” either when a CSA is received from an access point (in station mode), or when the local station is preparing 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). You only get here from IEEE80211_S_RUN when power save operation is enabled and the local station is deemed sufficiently idle to enter low power mode. Nap era 🫢

Important: the states are ordered (like, in the order above). e.g. a vap has to be in IEEE80211_S_RUN or β€œgreater” before it can transmit frames. Some net80211 data only makes sense in certain states; e.g. the iv_bsschan that specifies the channel for the operating BSS should never be used except in IEEE80211_S_RUN or greater.

πŸŒ€ STATE CHANGES πŸŒ€

State machine changes usually happen inside net80211, triggered by ioctl(2) requests, received frames, or external events like a beacon miss. To kick off a state machine change on a vap, you use ieee80211_new_state(). You hand it the new state and an optional argument. First the request goes through multi-vap coordination. For example, only one vap at a time can be scanning β€” if multiple vaps ask to change to IEEE80211_S_SCAN, the first one gets to run and the others get deferred until the scan operation completes, at which point the selected channel is adopted. Similarly, net80211 coordinates combos of vaps like an AP and station vap where the station may need to roam to follow the AP it’s associated to (dragging the AP vap along to the new channel). Another important coordination sitch is handling IEEE80211_S_CAC and IEEE80211_S_CSA. No more than one vap can ever be actively changing state at a time. In fact net80211 single-threads the state machine logic in a dedicated taskqueue(9) thread, which is also used to synchronize work like scanning and beacon miss handling.

Once the multi-vap scheduling/coordination is done, the per-vap iv_newstate method is called to actually carry out the state change work. Drivers use this entry to set up private state and then dispatch the call to the net80211 layer using the previously defined method pointer β€” in OOP-speak, they call the β€œsuper method.”

net80211 handles two state changes specially. On the transition to IEEE80211_S_RUN, the IFF_DRV_OACTIVE bit on the vap’s transmit queue is cleared so traffic can flow. On the 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 setup work required by state changes. 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 to an IEEE80211_S_INIT state β€” but a driver should not need it. Control is usually handled by net80211, or, for card eject or vap destroy, the work gets initiated outside the driver.

πŸ‘‘ SEE ALSO πŸ‘‘

🌸 HISTORY 🌸

The state machine concept was part of the original ieee80211 code base that first showed up in NetBSD 1.5.


mwah πŸ’‹ β€” this page is from Debian, dated August 4, 2009, and it’s the IEEE80211_PROTO(9) man page. Stay slay, bestie 🫢

πŸ“¦ where this page comes from