1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
<table class="head">
<tr>
<td class="head-ltitle">IEEE80211_PROTO(9)</td>
<td class="head-vol">Kernel Developer's Manual</td>
<td class="head-rtitle">IEEE80211_PROTO(9)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">ieee80211_proto</code> —
<span class="Nd">802.11 state machine support</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp"><code class="In">#include
<<a class="In">net80211/ieee80211_var.h</a>></code></p>
<p class="Pp">
<br/>
<var class="Ft">void</var>
<br/>
<code class="Fn">ieee80211_start_all</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211com *</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">ieee80211_stop_all</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211com *</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">ieee80211_suspend_all</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211com *</var>);</p>
<p class="Pp"><var class="Ft">void</var>
<br/>
<code class="Fn">ieee80211_resume_all</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211com *</var>);</p>
<p class="Pp"><code class="Dv">enum ieee80211_state</code>;
<br/>
<var class="Ft">int</var>
<br/>
<code class="Fn">ieee80211_new_state</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211vap *</var>, <var class="Fa" style="white-space: nowrap;">enum
ieee80211_state</var>,
<var class="Fa" style="white-space: nowrap;">int</var>);</p>
<p class="Pp">
<br/>
<var class="Ft">void</var>
<br/>
<code class="Fn">ieee80211_wait_for_parent</code>(<var class="Fa" style="white-space: nowrap;">struct
ieee80211com *</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">The <code class="Nm">net80211</code> layer that supports 802.11
device drivers uses a state machine to control operation of vaps. These
state machines vary according to the vap operating mode. Station mode state
machines follow the 802.11 MLME states in the protocol specification. Other
state machines are simpler and reflect operational work such as scanning for
a BSS or automatically selecting a channel to operate on. When multiple vaps
are operational the state machines are used to coordinate operation such as
choosing a channel. The state machine mechanism also serves to bind the
<code class="Nm">net80211</code> layer to a driver; this is described more
below.</p>
<p class="Pp">The following states are defined for state machines:</p>
<dl class="Bl-tag">
<dt id="IEEE80211_S_INIT"><a class="permalink" href="#IEEE80211_S_INIT"><code class="Dv">IEEE80211_S_INIT</code></a></dt>
<dd>Default/initial state. A vap in this state should not hold any dynamic
state (e.g. entries for associated stations in the node table). The driver
must quiesce the hardware; e.g. there should be no interrupts firing.</dd>
<dt id="IEEE80211_S_SCAN"><a class="permalink" href="#IEEE80211_S_SCAN"><code class="Dv">IEEE80211_S_SCAN</code></a></dt>
<dd>Scanning for a BSS or choosing a channel to operate on. Note that scanning
can also take place in other states (e.g. when background scanning is
active); this state is entered when initially bringing a vap to an
operational state or after an event such as a beacon miss (in station
mode).</dd>
<dt id="IEEE80211_S_AUTH"><a class="permalink" href="#IEEE80211_S_AUTH"><code class="Dv">IEEE80211_S_AUTH</code></a></dt>
<dd>Authenticating to an access point (in station mode). This state is
normally reached from <code class="Dv">IEEE80211_S_SCAN</code> after
selecting a BSS, but may also be reached from
<code class="Dv">IEEE80211_S_ASSOC</code> or
<code class="Dv">IEEE80211_S_RUN</code> if the authentication handshake
fails.</dd>
<dt id="IEEE80211_S_ASSOC"><a class="permalink" href="#IEEE80211_S_ASSOC"><code class="Dv">IEEE80211_S_ASSOC</code></a></dt>
<dd>Associating to an access point (in station mode). This state is reached
from <code class="Dv">IEEE80211_S_AUTH</code> after successfully
authenticating or from <code class="Dv">IEEE80211_S_RUN</code> if a
DisAssoc frame is received.</dd>
<dt id="IEEE80211_S_CAC"><a class="permalink" href="#IEEE80211_S_CAC"><code class="Dv">IEEE80211_S_CAC</code></a></dt>
<dd>Doing Channel Availability Check (CAC). This state is entered only when
DFS is enabled and the channel selected for operation requires CAC.</dd>
<dt id="IEEE80211_S_RUN"><a class="permalink" href="#IEEE80211_S_RUN"><code class="Dv">IEEE80211_S_RUN</code></a></dt>
<dd>Operational. In this state a vap can transmit data frames, accept requests
for stations associating, etc. Beware that 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 <a class="Xr">wpa_supplicant(8)</a> 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. <var class="Vt">ic_bss</var> and
<var class="Vt">ic_bsschan</var> are guaranteed to be usable.</dd>
<dt id="IEEE80211_S_CSA"><a class="permalink" href="#IEEE80211_S_CSA"><code class="Dv">IEEE80211_S_CSA</code></a></dt>
<dd>Channel Switch Announcement (CSA) is pending. This state is reached only
from <code class="Dv">IEEE80211_S_RUN</code> when either a CSA is received
from an access point (in station mode) or the local station is preparing
to change channel. In this state traffic may be muted depending on the
Mute setting in the CSA.</dd>
<dt id="IEEE80211_S_SLEEP"><a class="permalink" href="#IEEE80211_S_SLEEP"><code class="Dv">IEEE80211_S_SLEEP</code></a></dt>
<dd>Asleep to save power (in station mode). This state is reached only from
<code class="Dv">IEEE80211_S_RUN</code> when power save operation is
enabled and the local station is deemed sufficiently idle to enter low
power mode.</dd>
</dl>
<p class="Pp">Note that states are ordered (as shown above); e.g. a vap must be
in the <code class="Dv">IEEE80211_S_RUN</code> or “greater”
before it can transmit frames. Certain <code class="Nm">net80211</code> data
are valid only in certain states; e.g. the <var class="Vt">iv_bsschan</var>
that specifies the channel for the operating BSS should never be used except
in <code class="Dv">IEEE80211_S_RUN</code> or greater.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="STATE_CHANGES"><a class="permalink" href="#STATE_CHANGES">STATE
CHANGES</a></h1>
<p class="Pp">State machine changes are typically handled internal to the
<code class="Nm">net80211</code> layer in response to
<a class="Xr">ioctl(2)</a> requests, received frames, or external events
such as a beacon miss. The
<a class="permalink" href="#ieee80211_new_state"><code class="Fn" id="ieee80211_new_state">ieee80211_new_state</code></a>()
function is used to initiate a state machine change on a vap. The new state
and an optional argument are supplied. The request is initially processed to
handle coordination of multiple vaps. For example, only one vap at a time
can be scanning, if multiple vaps request a change to
<code class="Dv">IEEE80211_S_SCAN</code> the first will be permitted to run
and the others will be
<a class="permalink" href="#deferred"><i class="Em" id="deferred">deferred</i></a>
until the scan operation completes at which time the selected channel will
be adopted. Similarly <code class="Nm">net80211</code> handles coordination
of combinations of vaps such as an AP and station vap where the station may
need to roam to follow the AP it is associated to (dragging along the AP vap
to the new channel). Another important coordination is the handling of
<code class="Dv">IEEE80211_S_CAC</code> and
<code class="Dv">IEEE80211_S_CSA</code>. No more than one vap can ever be
actively changing state at a time. In fact <code class="Nm">net80211</code>
single-threads the state machine logic in a dedicated
<a class="Xr">taskqueue(9)</a> thread that is also used to synchronize work
such as scanning and beacon miss handling.</p>
<p class="Pp">After multi-vap scheduling/coordination is done the per-vap
<var class="Vt">iv_newstate</var> method is called to carry out the state
change work. Drivers use this entry to setup private state and then dispatch
the call to the <code class="Nm">net80211</code> layer using the previously
defined method pointer (in OOP-parlance they call the “super
method” ).</p>
<p class="Pp"><code class="Nm">net80211</code> handles two state changes
specially. On transition to <code class="Dv">IEEE80211_S_RUN</code> the
<code class="Dv">IFF_DRV_OACTIVE</code> bit on the vap's transmit queue is
cleared so traffic can flow. On transition to
<code class="Dv">IEEE80211_S_INIT</code> any state in the scan cache
associated with the vap is flushed and any frames pending on the transmit
queue are flushed.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DRIVER_INTEGRATION"><a class="permalink" href="#DRIVER_INTEGRATION">DRIVER
INTEGRATION</a></h1>
<p class="Pp">Drivers are expected to override the
<var class="Vt">iv_newstate</var> method to interpose their own code and
handle setup work required by state changes. Otherwise drivers must call
<a class="permalink" href="#ieee80211_start_all"><code class="Fn" id="ieee80211_start_all">ieee80211_start_all</code></a>()
in response to being marked up through an
<code class="Dv">SIOCSIFFLAGS</code> ioctl request and they should use
<a class="permalink" href="#ieee80211_suspend_all"><code class="Fn" id="ieee80211_suspend_all">ieee80211_suspend_all</code></a>()
and
<a class="permalink" href="#ieee80211_resume_all"><code class="Fn" id="ieee80211_resume_all">ieee80211_resume_all</code></a>()
to implement suspend/resume support.</p>
<p class="Pp" id="ieee80211_stop_all">There is also an
<a class="permalink" href="#ieee80211_stop_all"><code class="Fn">ieee80211_stop_all</code></a>()
call to force all vaps to an <code class="Dv">IEEE80211_S_INIT</code> state
but this should not be needed by a driver; control is usually handled by
<code class="Nm">net80211</code> or, in the case of card eject or vap
destroy, work will be initiated outside the driver.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<p class="Pp"><a class="Xr">ioctl(2)</a>, <a class="Xr">wpa_supplicant(8)</a>,
<a class="Xr">ieee80211(9)</a>, <a class="Xr">ifnet(9)</a>,
<a class="Xr">taskqueue(9)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<p class="Pp">The state machine concept was part of the original
<code class="Nm">ieee80211</code> code base that first appeared in
<span class="Ux">NetBSD 1.5</span>.</p>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">August 4, 2009</td>
<td class="foot-os">FreeBSD 15.0</td>
</tr>
</table>
|