Переглянути джерело

[802.11] Add support for 802.11 devices with software MAC layer

This is required for all modern 802.11 devices, and allows drivers
to be written for them with minimally more effort than is required
for a wired NIC.

Signed-off-by: Michael Brown <mcb30@etherboot.org>
Modified-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
Joshua Oreman 15 роки тому
джерело
коміт
ce64398f87

+ 1
- 1
src/Makefile Переглянути файл

@@ -55,7 +55,7 @@ SRCDIRS		:=
55 55
 SRCDIRS		+= libgcc
56 56
 SRCDIRS		+= core
57 57
 SRCDIRS		+= proto
58
-SRCDIRS		+= net net/tcp net/udp net/infiniband
58
+SRCDIRS		+= net net/tcp net/udp net/infiniband net/80211
59 59
 SRCDIRS		+= image
60 60
 SRCDIRS		+= drivers/bus
61 61
 SRCDIRS		+= drivers/net

+ 1
- 0
src/include/gpxe/errfile.h Переглянути файл

@@ -148,6 +148,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
148 148
 #define ERRFILE_ib_pathrec		( ERRFILE_NET | 0x001c0000 )
149 149
 #define ERRFILE_ib_mcast		( ERRFILE_NET | 0x001d0000 )
150 150
 #define ERRFILE_ib_cm			( ERRFILE_NET | 0x001e0000 )
151
+#define ERRFILE_net80211		( ERRFILE_NET | 0x001f0000 )
151 152
 
152 153
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
153 154
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

+ 1174
- 0
src/include/gpxe/ieee80211.h
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 983
- 0
src/include/gpxe/net80211.h Переглянути файл

@@ -0,0 +1,983 @@
1
+#ifndef _GPXE_NET80211_H
2
+#define _GPXE_NET80211_H
3
+
4
+#include <gpxe/process.h>
5
+#include <gpxe/ieee80211.h>
6
+#include <gpxe/iobuf.h>
7
+#include <gpxe/netdevice.h>
8
+#include <gpxe/rc80211.h>
9
+
10
+/** @file
11
+ *
12
+ * The gPXE 802.11 MAC layer.
13
+ */
14
+
15
+/*
16
+ * Major things NOT YET supported:
17
+ * - any type of security
18
+ * - 802.11n
19
+ *
20
+ * Major things that probably will NEVER be supported, barring a
21
+ * compelling use case and/or corporate sponsorship:
22
+ * - QoS
23
+ * - 802.1X authentication ("WPA Enterprise")
24
+ * - Contention-free periods
25
+ * - "ad-hoc" networks (IBSS), monitor mode, host AP mode
26
+ * - hidden networks on the 5GHz band due to regulatory issues
27
+ * - spectrum management on the 5GHz band (TPC and DFS), as required
28
+ *   in some non-US regulatory domains
29
+ * - Clause 14 PHYs (Frequency-Hopping Spread Spectrum on 2.4GHz)
30
+ *   and Clause 16 PHYs (infrared) - I'm not aware of any real-world
31
+ *   use of these.
32
+ */
33
+
34
+FILE_LICENCE ( GPL2_OR_LATER );
35
+
36
+/* All 802.11 devices are handled using a generic "802.11 device"
37
+   net_device, with a link in its `priv' field to a net80211_device
38
+   which we use to handle 802.11-specific details. */
39
+
40
+
41
+/** @defgroup net80211_band RF bands on which an 802.11 device can transmit */
42
+/** @{ */
43
+
44
+/** The 2.4 GHz ISM band, unlicensed in most countries */
45
+#define NET80211_BAND_2GHZ	(1 << 0)
46
+/** The band from 4.9 GHz to 5.7 GHz, which tends to be more restricted */
47
+#define NET80211_BAND_5GHZ	(1 << 1)
48
+
49
+/** @} */
50
+
51
+
52
+/** @defgroup net80211_mode 802.11 operation modes supported by hardware */
53
+/** @{ */
54
+
55
+/** 802.11a: 54 Mbps operation using OFDM signaling on the 5GHz band */
56
+#define NET80211_MODE_A		(1 << 0)
57
+
58
+/** 802.11b: 1-11 Mbps operation using DSSS/CCK signaling on the 2.4GHz band */
59
+#define NET80211_MODE_B		(1 << 1)
60
+
61
+/** 802.11g: 54 Mbps operation using ERP/OFDM signaling on the 2.4GHz band */
62
+#define NET80211_MODE_G		(1 << 2)
63
+
64
+/** 802.11n: High-rate operation using MIMO technology on 2.4GHz or 5GHz */
65
+#define NET80211_MODE_N		(1 << 3)
66
+
67
+/** @} */
68
+
69
+
70
+/** @defgroup net80211_cfg Constants for the net80211 config callback */
71
+/** @{ */
72
+
73
+/** Channel choice (@c dev->channel) or regulatory parameters have changed */
74
+#define NET80211_CFG_CHANNEL	(1 << 0)
75
+
76
+/** Requested transmission rate (@c dev->rate) has changed */
77
+#define NET80211_CFG_RATE	(1 << 1)
78
+
79
+/** Association has been established with a new BSS (@c dev->bssid) */
80
+#define NET80211_CFG_ASSOC	(1 << 2)
81
+
82
+/** Low-level link parameters (short preamble, protection, etc) have changed */
83
+#define NET80211_CFG_PHY_PARAMS	(1 << 3)
84
+
85
+/** @} */
86
+
87
+
88
+/** An 802.11 security handshaking protocol */
89
+enum net80211_security_proto {
90
+	/** No security handshaking
91
+	 *
92
+	 * This might be used with an open network or with WEP, as
93
+	 * WEP does not have a cryptographic handshaking phase.
94
+	 */
95
+	NET80211_SECPROT_NONE = 0,
96
+
97
+	/** Pre-shared key handshaking
98
+	 *
99
+	 * This implements the "WPA Personal" handshake. 802.1X
100
+	 * authentication is not performed -- the user supplies a
101
+	 * pre-shared key directly -- but there is a 4-way handshake
102
+	 * between client and AP to verify that both have the same key
103
+	 * without revealing the contents of that key.
104
+	 */
105
+	NET80211_SECPROT_PSK = 1,
106
+
107
+	/** Full EAP 802.1X handshaking
108
+	 *
109
+	 * This implements the "WPA Enterprise" handshake, connecting
110
+	 * to an 802.1X authentication server to provide credentials
111
+	 * and receive a pairwise master key (PMK), which is then used
112
+	 * in the same 4-way handshake as the PSK method.
113
+	 */
114
+	NET80211_SECPROT_EAP = 2,
115
+};
116
+
117
+
118
+/** An 802.11 data encryption algorithm */
119
+enum net80211_crypto_alg {
120
+	/** No security, an "Open" network */
121
+	NET80211_CRYPT_NONE = 0,
122
+
123
+	/** Network protected with WEP (awful RC4-based system)
124
+	 *
125
+	 * WEP uses a naive application of RC4, with a monotonically
126
+	 * increasing initialization vector that is prepended to the
127
+	 * key to initialize the RC4 keystream. It is highly insecure
128
+	 * and can be completely cracked or subverted using automated,
129
+	 * robust, freely available tools (aircrack-ng) in minutes.
130
+	 *
131
+	 * 40-bit and 104-bit WEP are differentiated only by the size
132
+	 * of the key. They may be advertised as 64-bit and 128-bit,
133
+	 * counting the non-random IV as part of the key bits.
134
+	 */
135
+	NET80211_CRYPT_WEP = 1,
136
+
137
+	/** Network protected with TKIP (better RC4-based system)
138
+	 *
139
+	 * Usually known by its trade name of WPA (Wi-Fi Protected
140
+	 * Access), TKIP implements a message integrity code (MIC)
141
+	 * called Michael, a timestamp counter for replay prevention,
142
+	 * and a key mixing function that together remove almost all
143
+	 * the security problems with WEP. Countermeasures are
144
+	 * implemented to prevent high data-rate attacks.
145
+	 *
146
+	 * There exists one known attack on TKIP, that allows one to
147
+	 * send between 7 and 15 arbitrary short data packets on a
148
+	 * QoS-enabled network given about an hour of data
149
+	 * gathering. Since gPXE does not support QoS for 802.11
150
+	 * networks, this is not a threat to us. The only other method
151
+	 * is a brute-force passphrase attack.
152
+	 */
153
+	NET80211_CRYPT_TKIP = 2,
154
+
155
+	/** Network protected with CCMP (AES-based system)
156
+	 *
157
+	 * Often called WPA2 in commerce, or RSNA (Robust Security
158
+	 * Network Architecture) in the 802.11 standard, CCMP is
159
+	 * highly secure and does not have any known attack vectors.
160
+	 * Since it is based on a block cipher, the statistical
161
+	 * correlation and "chopchop" attacks used with great success
162
+	 * against WEP and minor success against TKIP fail.
163
+	 */
164
+	NET80211_CRYPT_CCMP = 3,
165
+};
166
+
167
+
168
+/** @defgroup net80211_state Bits for the 802.11 association state field */
169
+/** @{ */
170
+
171
+/** An error code indicating the failure mode, or 0 if successful */
172
+#define NET80211_STATUS_MASK    0x7F
173
+
174
+/** Whether the error code provided is a "reason" code, not a "status" code */
175
+#define NET80211_IS_REASON	0x80
176
+
177
+/** Whether we have found the network we will be associating with */
178
+#define NET80211_PROBED		(1 << 8)
179
+
180
+/** Whether we have successfully authenticated with the network
181
+ *
182
+ * This usually has nothing to do with actual security; it is a
183
+ * holdover from older 802.11 implementation ideas.
184
+ */
185
+#define NET80211_AUTHENTICATED  (1 << 9)
186
+
187
+/** Whether we have successfully associated with the network */
188
+#define NET80211_ASSOCIATED     (1 << 10)
189
+
190
+/** Whether we have completed security handshaking with the network
191
+ *
192
+ * Once this is set, we can send data packets. For that reason this
193
+ * bit is set even in cases where no security handshaking is
194
+ * required.
195
+ */
196
+#define NET80211_CRYPTO_SYNCED  (1 << 11)
197
+
198
+/** Whether the auto-association task is running */
199
+#define NET80211_WORKING        (1 << 12)
200
+
201
+/** Whether the auto-association task is waiting for a reply from the AP */
202
+#define NET80211_WAITING        (1 << 13)
203
+
204
+/** Whether the auto-association task should be suppressed
205
+ *
206
+ * This is set by the `iwlist' command so that it can open the device
207
+ * without starting another probe process that will interfere with its
208
+ * own.
209
+ */
210
+#define NET80211_NO_ASSOC	(1 << 14)
211
+
212
+/** Whether this association was performed using a broadcast SSID
213
+ *
214
+ * If the user opened this device without netX/ssid set, the device's
215
+ * SSID will be set to that of the network it chooses to associate
216
+ * with, but the netX/ssid setting will remain blank. If we don't
217
+ * remember that we started from no specified SSID, it will appear
218
+ * every time settings are updated (e.g. after DHCP) that we need to
219
+ * reassociate due to the difference between the set SSID and our own.
220
+ */
221
+#define NET80211_AUTO_SSID	(1 << 15)
222
+
223
+
224
+/** @} */
225
+
226
+
227
+/** @defgroup net80211_phy 802.11 physical layer flags */
228
+/** @{ */
229
+
230
+/** Whether to use RTS/CTS or CTS-to-self protection for transmissions
231
+ *
232
+ * Since the RTS or CTS is transmitted using 802.11b signaling, and
233
+ * includes a field indicating the amount of time that will be used by
234
+ * transmission of the following packet, this serves as an effective
235
+ * protection mechanism to avoid 802.11b clients interfering with
236
+ * 802.11g clients on mixed networks.
237
+ */
238
+#define NET80211_PHY_USE_PROTECTION      (1 << 1)
239
+
240
+/** Whether to use 802.11b short preamble operation
241
+ *
242
+ * Short-preamble operation can moderately increase throughput on
243
+ * 802.11b networks operating between 2Mbps and 11Mbps. It is
244
+ * irrelevant for 802.11g data rates, since they use a different
245
+ * modulation scheme.
246
+ */
247
+#define NET80211_PHY_USE_SHORT_PREAMBLE  (1 << 2)
248
+
249
+/** Whether to use 802.11g short slot operation
250
+ *
251
+ * This affects a low-level timing parameter of 802.11g transmissions.
252
+ */
253
+#define NET80211_PHY_USE_SHORT_SLOT      (1 << 3)
254
+
255
+/** @} */
256
+
257
+
258
+/** The maximum number of TX rates we allow to be configured simultaneously */
259
+#define NET80211_MAX_RATES	16
260
+
261
+/** The maximum number of channels we allow to be configured simultaneously */
262
+#define NET80211_MAX_CHANNELS	32
263
+
264
+/** Seconds we'll wait to get all fragments of a packet */
265
+#define NET80211_FRAG_TIMEOUT	2
266
+
267
+/** The number of fragments we can receive at once
268
+ *
269
+ * The 802.11 standard requires that this be at least 3.
270
+ */
271
+#define NET80211_NR_CONCURRENT_FRAGS 3
272
+
273
+/** Maximum TX power to allow (dBm), if we don't get a regulatory hint */
274
+#define NET80211_REG_TXPOWER	20
275
+
276
+
277
+struct net80211_device;
278
+
279
+/** Operations that must be implemented by an 802.11 driver */
280
+struct net80211_device_operations {
281
+	/** Open 802.11 device
282
+	 *
283
+	 * @v dev	802.11 device
284
+	 * @ret rc	Return status code
285
+	 *
286
+	 * This method should allocate RX I/O buffers and enable the
287
+	 * hardware to start transmitting and receiving packets on the
288
+	 * channels its net80211_register() call indicated it could
289
+	 * handle. It does not need to tune the antenna to receive
290
+	 * packets on any particular channel.
291
+	 */
292
+	int ( * open ) ( struct net80211_device *dev );
293
+
294
+	/** Close 802.11 network device
295
+	 *
296
+	 * @v dev	802.11 device
297
+	 *
298
+	 * This method should stop the flow of packets, and call
299
+	 * net80211_tx_complete() for any packets remaining in the
300
+	 * device's TX queue.
301
+	 */
302
+	void ( * close ) ( struct net80211_device *dev );
303
+
304
+	/** Transmit packet on 802.11 network device
305
+	 *
306
+	 * @v dev	802.11 device
307
+	 * @v iobuf	I/O buffer
308
+	 * @ret rc	Return status code
309
+	 *
310
+	 * This method should cause the hardware to initiate
311
+	 * transmission of the I/O buffer, using the channel and rate
312
+	 * most recently indicated by an appropriate call to the
313
+	 * @c config callback. The 802.11 layer guarantees that said
314
+	 * channel and rate will be the same as those currently
315
+	 * reflected in the fields of @a dev.
316
+	 *
317
+	 * If this method returns success, the I/O buffer remains
318
+	 * owned by the network layer's TX queue, and the driver must
319
+	 * eventually call net80211_tx_complete() to free the buffer
320
+	 * whether transmission succeeded or not. If this method
321
+	 * returns failure, it will be interpreted as "failure to
322
+	 * enqueue buffer" and the I/O buffer will be immediately
323
+	 * released.
324
+	 *
325
+	 * This method is guaranteed to be called only when the device
326
+	 * is open.
327
+	 */
328
+	int ( * transmit ) ( struct net80211_device *dev,
329
+			     struct io_buffer *iobuf );
330
+
331
+	/** Poll for completed and received packets
332
+	 *
333
+	 * @v dev	802.11 device
334
+	 *
335
+	 * This method should cause the hardware to check for
336
+	 * completed transmissions and received packets. Any received
337
+	 * packets should be delivered via net80211_rx(), and
338
+	 * completed transmissions should be indicated using
339
+	 * net80211_tx_complete().
340
+	 *
341
+	 * This method is guaranteed to be called only when the device
342
+	 * is open.
343
+	 */
344
+	void ( * poll ) ( struct net80211_device *dev );
345
+
346
+	/** Enable or disable interrupts
347
+	 *
348
+	 * @v dev	802.11 device
349
+	 * @v enable	If TRUE, interrupts should be enabled
350
+	 */
351
+	void ( * irq ) ( struct net80211_device *dev, int enable );
352
+
353
+	/** Update hardware state to match 802.11 layer state
354
+	 *
355
+	 * @v dev	802.11 device
356
+	 * @v changed	Set of flags indicating what may have changed
357
+	 * @ret rc	Return status code
358
+	 *
359
+	 * This method should cause the hardware state to be
360
+	 * reinitialized from the state indicated in fields of
361
+	 * net80211_device, in the areas indicated by bits set in
362
+	 * @a changed. If the hardware is unable to do so, this method
363
+	 * may return an appropriate error indication.
364
+	 *
365
+	 * This method is guaranteed to be called only when the device
366
+	 * is open.
367
+	 */
368
+	int ( * config ) ( struct net80211_device *dev, int changed );
369
+};
370
+
371
+/** An 802.11 RF channel. */
372
+struct net80211_channel
373
+{
374
+	/** The band with which this channel is associated */
375
+	u8 band;
376
+
377
+	/** A channel number interpreted according to the band
378
+	 *
379
+	 * The 2.4GHz band uses channel numbers from 1-13 at 5MHz
380
+	 * intervals such that channel 1 is 2407 MHz; channel 14,
381
+	 * legal for use only in Japan, is defined separately as 2484
382
+	 * MHz. Adjacent channels will overlap, since 802.11
383
+	 * transmissions use a 20 MHz (4-channel) bandwidth. Most
384
+	 * commonly, channels 1, 6, and 11 are used.
385
+	 *
386
+	 * The 5GHz band uses channel numbers derived directly from
387
+	 * the frequency; channel 0 is 5000 MHz, and channels are
388
+	 * always spaced 5 MHz apart. Channel numbers over 180 are
389
+	 * relative to 4GHz instead of 5GHz, but these are rarely
390
+	 * seen. Most channels are not legal for use.
391
+	 */
392
+	u8 channel_nr;
393
+
394
+	/** The center frequency for this channel
395
+	 *
396
+	 * Currently a bandwidth of 20 MHz is assumed.
397
+	 */
398
+	u16 center_freq;
399
+
400
+	/** Maximum allowable transmit power, in dBm
401
+	 *
402
+	 * This should be interpreted as EIRP, the power supplied to
403
+	 * an ideal isotropic antenna in order to achieve the same
404
+	 * average signal intensity as the real hardware at a
405
+	 * particular distance.
406
+	 *
407
+	 * Currently no provision is made for directional antennas.
408
+	 */
409
+	u8 maxpower;
410
+};
411
+
412
+/** Information on the capabilities of an 802.11 hardware device
413
+ *
414
+ * In its probe callback, an 802.11 driver must read hardware
415
+ * registers to determine the appropriate contents of this structure,
416
+ * fill it, and pass it to net80211_register() so that the 802.11
417
+ * layer knows how to treat the hardware and what to advertise as
418
+ * supported to access points.
419
+ */
420
+struct net80211_hw_info
421
+{
422
+	/** Default hardware MAC address.
423
+	 *
424
+	 * The user may change this by setting the @c netX/mac setting
425
+	 * before the driver's open function is called; in that case
426
+	 * the driver must set the hardware MAC address to the address
427
+	 * contained in the wrapping net_device's ll_addr field, or if
428
+	 * that is impossible, set that ll_addr field back to the
429
+	 * unchangeable hardware MAC address.
430
+	 */
431
+	u8 hwaddr[ETH_ALEN];
432
+
433
+	/** A bitwise OR of the 802.11x modes supported by this device */
434
+	int modes;
435
+
436
+	/** A bitwise OR of the bands on which this device can communicate */
437
+	int bands;
438
+
439
+	/** A set of flags indicating peculiarities of this device. */
440
+	enum {
441
+		/** Received frames include a frame check sequence. */
442
+		NET80211_HW_RX_HAS_FCS = (1 << 1),
443
+
444
+		/** Hardware doesn't support 2.4GHz short preambles
445
+		 *
446
+		 * This is only relevant for 802.11b operation above
447
+		 * 2Mbps. All 802.11g devices support short preambles.
448
+		 */
449
+		NET80211_HW_NO_SHORT_PREAMBLE = (1 << 2),
450
+
451
+		/** Hardware doesn't support 802.11g short slot operation */
452
+		NET80211_HW_NO_SHORT_SLOT = (1 << 3),
453
+	} flags;
454
+
455
+	/** Signal strength information that can be provided by the device
456
+	 *
457
+	 * Signal strength is passed to net80211_rx(), primarily to
458
+	 * allow determination of the closest access point for a
459
+	 * multi-AP network. The units are provided for completeness
460
+	 * of status displays.
461
+	 */
462
+	enum {
463
+		/** No signal strength information supported */
464
+		NET80211_SIGNAL_NONE = 0,
465
+		/** Signal strength in arbitrary units */
466
+		NET80211_SIGNAL_ARBITRARY,
467
+		/** Signal strength in decibels relative to arbitrary base */
468
+		NET80211_SIGNAL_DB,
469
+		/** Signal strength in decibels relative to 1mW */
470
+		NET80211_SIGNAL_DBM,
471
+	} signal_type;
472
+
473
+	/** Maximum signal in arbitrary cases
474
+	 *
475
+	 * If signal_type is NET80211_SIGNAL_ARBITRARY or
476
+	 * NET80211_SIGNAL_DB, the driver should report it on a scale
477
+	 * from 0 to signal_max.
478
+	 */
479
+	unsigned signal_max;
480
+
481
+	/** List of transmission rates supported by the card
482
+	 *
483
+	 * Rates should be in 100kbps increments (e.g. 11 Mbps would
484
+	 * be represented as the number 110).
485
+	 */
486
+	u16 supported_rates[NET80211_MAX_RATES];
487
+
488
+	/** Number of supported rates */
489
+	int nr_supported_rates;
490
+
491
+	/** Estimate of the time required to change channels, in microseconds
492
+	 *
493
+	 * If this is not known, a guess on the order of a few
494
+	 * milliseconds (value of 1000-5000) is reasonable.
495
+	 */
496
+	unsigned channel_change_time;
497
+};
498
+
499
+/** Structure tracking received fragments for a packet
500
+ *
501
+ * We set up a fragment cache entry when we receive a packet marked as
502
+ * fragment 0 with the "more fragments" bit set in its frame control
503
+ * header. We are required by the 802.11 standard to track 3
504
+ * fragmented packets arriving simultaneously; if we receive more we
505
+ * may drop some. Upon receipt of a new fragment-0 packet, if no entry
506
+ * is available or expired, we take over the most @e recent entry for
507
+ * the new packet, since we don't want to starve old entries from ever
508
+ * finishing at all. If we get a fragment after the zeroth with no
509
+ * cache entry for its packet, we drop it.
510
+ */
511
+struct net80211_frag_cache
512
+{
513
+	/** Whether this cache entry is in use */
514
+	u8 in_use;
515
+
516
+	/** Sequence number of this MSDU (packet) */
517
+	u16 seqnr;
518
+
519
+	/** Timestamp from point at which first fragment was collected */
520
+	u32 start_ticks;
521
+
522
+	/** Buffers for each fragment */
523
+	struct io_buffer *iob[16];
524
+};
525
+
526
+/** Interface to an 802.11 cryptographic algorithm
527
+ *
528
+ * Cryptographic algorithms define a net80211_crypto structure
529
+ * statically, using a gPXE linker table to make it available to the
530
+ * 802.11 layer. When the algorithm needs to be used, the 802.11 code
531
+ * will allocate a copy of the static definition plus whatever space
532
+ * the algorithm has requested for private state, and point
533
+ * net80211_device::crypto at it.
534
+ */
535
+struct net80211_crypto
536
+{
537
+	/** The cryptographic algorithm implemented */
538
+	enum net80211_crypto_alg algorithm;
539
+
540
+	/** Initialize cryptographic algorithm using a given key
541
+	 *
542
+	 * @v crypto	802.11 cryptographic algorithm
543
+	 * @v key	Pointer to key bytes
544
+	 * @v keylen	Number of key bytes
545
+	 * @ret rc	Return status code
546
+	 *
547
+	 * This method is passed the communication key provided by the
548
+	 * security handshake handler, which will already be in the
549
+	 * low-level form required.
550
+	 */
551
+	int ( * initialize ) ( struct net80211_crypto *crypto, u8 *key,
552
+			       int keylen );
553
+
554
+	/** Encrypt a frame using the cryptographic algorithm
555
+	 *
556
+	 * @v crypto	802.11 cryptographic algorithm
557
+	 * @v iob	I/O buffer
558
+	 * @ret eiob	Newly allocated I/O buffer with encrypted packet
559
+	 *
560
+	 * This method is called to encrypt a single frame. It is
561
+	 * guaranteed that initialize() will have completed
562
+	 * successfully before this method is called.
563
+	 *
564
+	 * The frame passed already has an 802.11 header prepended,
565
+	 * but the PROTECTED bit in the frame control field will not
566
+	 * be set; this method is responsible for setting it. The
567
+	 * returned I/O buffer should contain a complete copy of @a
568
+	 * iob, including the 802.11 header, but with the PROTECTED
569
+	 * bit set, the data encrypted, and whatever encryption
570
+	 * headers/trailers are necessary added.
571
+	 *
572
+	 * This method should never free the passed I/O buffer.
573
+	 *
574
+	 * Return NULL if the packet could not be encrypted, due to
575
+	 * memory limitations or otherwise.
576
+	 */
577
+	struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
578
+					   struct io_buffer *iob );
579
+
580
+	/** Decrypt a frame using the cryptographic algorithm
581
+	 *
582
+	 * @v crypto	802.11 cryptographic algorithm
583
+	 * @v eiob	Encrypted I/O buffer
584
+	 * @ret iob	Newly allocated I/O buffer with decrypted packet
585
+	 *
586
+	 * This method is called to decrypt a single frame. It is
587
+	 * guaranteed that initialize() will have completed
588
+	 * successfully before this method is called.
589
+	 *
590
+	 * Decryption follows the reverse of the pattern used for
591
+	 * encryption: this method must copy the 802.11 header into
592
+	 * the returned packet, decrypt the data stream, remove any
593
+	 * encryption header or trailer, and clear the PROTECTED bit
594
+	 * in the frame control header.
595
+	 *
596
+	 * This method should never free the passed I/O buffer.
597
+	 *
598
+	 * Return NULL if memory was not available for decryption, if
599
+	 * a consistency or integrity check on the decrypted frame
600
+	 * failed, or if the decrypted frame should not be processed
601
+	 * by the network stack for any other reason.
602
+	 */
603
+	struct io_buffer * ( * decrypt ) ( struct net80211_crypto *crypto,
604
+					   struct io_buffer *iob );
605
+
606
+	/** Length of private data requested to be allocated */
607
+	int priv_len;
608
+
609
+	/** Private data for the algorithm to store key and state info */
610
+	void *priv;
611
+};
612
+
613
+
614
+struct net80211_probe_ctx;
615
+struct net80211_assoc_ctx;
616
+
617
+
618
+/** Structure encapsulating the complete state of an 802.11 device
619
+ *
620
+ * An 802.11 device is always wrapped by a network device, and this
621
+ * network device is always pointed to by the @a netdev field. In
622
+ * general, operations should never be performed by 802.11 code using
623
+ * netdev functions directly. It is usually the case that the 802.11
624
+ * layer might need to do some processing or bookkeeping on top of
625
+ * what the netdevice code will do.
626
+ */
627
+struct net80211_device
628
+{
629
+	/** The net_device that wraps us. */
630
+	struct net_device *netdev;
631
+
632
+	/** List of 802.11 devices. */
633
+	struct list_head list;
634
+
635
+	/** 802.11 device operations */
636
+	struct net80211_device_operations *op;
637
+
638
+	/** Driver private data */
639
+	void *priv;
640
+
641
+	/** Information about the hardware, provided to net80211_register() */
642
+	struct net80211_hw_info *hw;
643
+
644
+	/* ---------- Channel and rate fields ---------- */
645
+
646
+	/** A list of all possible channels we might use */
647
+	struct net80211_channel channels[NET80211_MAX_CHANNELS];
648
+
649
+	/** The number of channels in the channels array */
650
+	u8 nr_channels;
651
+
652
+	/** The channel currently in use, as an index into the channels array */
653
+	u8 channel;
654
+
655
+	/** A list of all possible TX rates we might use
656
+	 *
657
+	 * Rates are in units of 100 kbps.
658
+	 */
659
+	u16 rates[NET80211_MAX_RATES];
660
+
661
+	/** The number of transmission rates in the rates array */
662
+	u8 nr_rates;
663
+
664
+	/** The rate currently in use, as an index into the rates array */
665
+	u8 rate;
666
+
667
+	/** The rate to use for RTS/CTS transmissions
668
+	 *
669
+	 * This is always the fastest basic rate that is not faster
670
+	 * than the data rate in use. Also an index into the rates array.
671
+	 */
672
+	u8 rtscts_rate;
673
+
674
+	/** Bitmask of basic rates
675
+	 *
676
+	 * If bit N is set in this value, with the LSB considered to
677
+	 * be bit 0, then rate N in the rates array is a "basic" rate.
678
+	 *
679
+	 * We don't decide which rates are "basic"; our AP does, and
680
+	 * we respect its wishes. We need to be able to identify basic
681
+	 * rates in order to calculate the duration of a CTS packet
682
+	 * used for 802.11 g/b interoperability.
683
+	 */
684
+	u32 basic_rates;
685
+
686
+	/* ---------- Association fields ---------- */
687
+
688
+	/** The asynchronous association process.
689
+	 *
690
+	 * When an 802.11 netdev is opened, or when the user changes
691
+	 * the SSID setting on an open 802.11 device, an
692
+	 * autoassociation task is started by net80211_autoassocate()
693
+	 * to associate with the new best network. The association is
694
+	 * asynchronous, but no packets can be transmitted until it is
695
+	 * complete. If it is successful, the wrapping net_device is
696
+	 * set as "link up". If it fails, @c assoc_rc will be set with
697
+	 * an error indication.
698
+	 */
699
+	struct process proc_assoc;
700
+
701
+	/** Network with which we are associating
702
+	 *
703
+	 * This will be NULL when we are not actively in the process
704
+	 * of associating with a network we have already successfully
705
+	 * probed for.
706
+	 */
707
+	struct net80211_wlan *associating;
708
+
709
+	/** Context for the association process
710
+	 *
711
+	 * This is a probe_ctx if the @c PROBED flag is not set in @c
712
+	 * state, and an assoc_ctx otherwise.
713
+	 */
714
+	union {
715
+		struct net80211_probe_ctx *probe;
716
+		struct net80211_assoc_ctx *assoc;
717
+	} ctx;
718
+
719
+	/** State of our association to the network
720
+	 *
721
+	 * Since the association process happens asynchronously, it's
722
+	 * necessary to have some channel of communication so the
723
+	 * driver can say "I got an association reply and we're OK" or
724
+	 * similar. This variable provides that link. It is a bitmask
725
+	 * of any of NET80211_PROBED, NET80211_AUTHENTICATED,
726
+	 * NET80211_ASSOCIATED, NET80211_CRYPTO_SYNCED to indicate how
727
+	 * far along in associating we are; NET80211_WORKING if the
728
+	 * association task is running; and NET80211_WAITING if a
729
+	 * packet has been sent that we're waiting for a reply to. We
730
+	 * can only be crypto-synced if we're associated, we can
731
+	 * only be associated if we're authenticated, we can only be
732
+	 * authenticated if we've probed.
733
+	 *
734
+	 * If an association process fails (that is, we receive a
735
+	 * packet with an error indication), the error code is copied
736
+	 * into bits 6-0 of this variable and bit 7 is set to specify
737
+	 * what type of error code it is. An AP can provide either a
738
+	 * "status code" (0-51 are defined) explaining why it refused
739
+	 * an association immediately, or a "reason code" (0-45 are
740
+	 * defined) explaining why it canceled an association after it
741
+	 * had originally OK'ed it. Status and reason codes serve
742
+	 * similar functions, but they use separate error message
743
+	 * tables. A gPXE-formatted return status code (negative) is
744
+	 * placed in @c assoc_rc.
745
+	 *
746
+	 * If the failure to associate is indicated by a status code,
747
+	 * the NET80211_IS_REASON bit will be clear; if it is
748
+	 * indicated by a reason code, the bit will be set. If we were
749
+	 * successful, both zero status and zero reason mean success,
750
+	 * so there is no ambiguity.
751
+	 *
752
+	 * To prevent association when opening the device, user code
753
+	 * can set the NET80211_NO_ASSOC bit. The final bit in this
754
+	 * variable, NET80211_AUTO_SSID, is used to remember whether
755
+	 * we picked our SSID through automated probing as opposed to
756
+	 * user specification; the distinction becomes relevant in the
757
+	 * settings applicator.
758
+	 */
759
+	u16 state;
760
+
761
+	/** Return status code associated with @c state */
762
+	int assoc_rc;
763
+
764
+	/* ---------- Parameters of currently associated network ---------- */
765
+
766
+	/** 802.11 cryptographic algorithm for our current network
767
+	 *
768
+	 * For an open network, this will be set to NULL.
769
+	 */
770
+	struct net80211_crypto *crypto;
771
+
772
+	/** MAC address of the access point most recently associated */
773
+	u8 bssid[ETH_ALEN];
774
+
775
+	/** SSID of the access point we are or will be associated with
776
+	 *
777
+	 * Although the SSID field in 802.11 packets is generally not
778
+	 * NUL-terminated, here and in net80211_wlan we add a NUL for
779
+	 * convenience.
780
+	 */
781
+	char essid[IEEE80211_MAX_SSID_LEN+1];
782
+
783
+	/** Association ID given to us by the AP */
784
+	u16 aid;
785
+
786
+	/** TSFT value for last beacon received, microseconds */
787
+	u64 last_beacon_timestamp;
788
+
789
+	/** Time between AP sending beacons, microseconds */
790
+	u32 tx_beacon_interval;
791
+
792
+	/** Smoothed average time between beacons, microseconds */
793
+	u32 rx_beacon_interval;
794
+
795
+	/* ---------- Physical layer information ---------- */
796
+
797
+	/** Physical layer options
798
+	 *
799
+	 * These control the use of CTS protection, short preambles,
800
+	 * and short-slot operation.
801
+	 */
802
+	int phy_flags;
803
+
804
+	/** Signal strength of last received packet */
805
+	int last_signal;
806
+
807
+	/** Rate control state */
808
+	struct rc80211_ctx *rctl;
809
+
810
+	/* ---------- Packet handling state ---------- */
811
+
812
+	/** Fragment reassembly state */
813
+	struct net80211_frag_cache frags[NET80211_NR_CONCURRENT_FRAGS];
814
+
815
+	/** The sequence number of the last packet we sent */
816
+	u16 last_tx_seqnr;
817
+
818
+	/** Packet duplication elimination state
819
+	 *
820
+	 * We are only required to handle immediate duplicates for
821
+	 * each direct sender, and since we can only have one direct
822
+	 * sender (the AP), we need only keep the sequence control
823
+	 * field from the most recent packet we've received. Thus,
824
+	 * this field stores the last sequence control field we've
825
+	 * received for a packet from the AP.
826
+	 */
827
+	u16 last_rx_seq;
828
+
829
+	/** RX management packet queue
830
+	 *
831
+	 * Sometimes we want to keep probe, beacon, and action packets
832
+	 * that we receive, such as when we're scanning for networks.
833
+	 * Ordinarily we drop them because they are sent at a large
834
+	 * volume (ten beacons per second per AP, broadcast) and we
835
+	 * have no need of them except when we're scanning.
836
+	 *
837
+	 * When keep_mgmt is TRUE, received probe, beacon, and action
838
+	 * management packets will be stored in this queue.
839
+	 */
840
+	struct list_head mgmt_queue;
841
+
842
+	/** RX management packet info queue
843
+	 *
844
+	 * We need to keep track of the signal strength for management
845
+	 * packets we're keeping, because that provides the only way
846
+	 * to distinguish between multiple APs for the same network.
847
+	 * Since we can't extend io_buffer to store signal, this field
848
+	 * heads a linked list of "RX packet info" structures that
849
+	 * contain that signal strength field. Its entries always
850
+	 * parallel the entries in mgmt_queue, because the two queues
851
+	 * are always added to or removed from in parallel.
852
+	 */
853
+	struct list_head mgmt_info_queue;
854
+
855
+	/** Whether to store management packets
856
+	 *
857
+	 * Received beacon, probe, and action packets will be added to
858
+	 * mgmt_queue (and their signal strengths added to
859
+	 * mgmt_info_queue) only when this variable is TRUE. It should
860
+	 * be set by net80211_keep_mgmt() (which returns the old
861
+	 * value) only when calling code is prepared to poll the
862
+	 * management queue frequently, because packets will otherwise
863
+	 * pile up and exhaust memory.
864
+	 */
865
+	int keep_mgmt;
866
+};
867
+
868
+/** Structure representing a probed network.
869
+ *
870
+ * This is returned from the net80211_probe_finish functions and
871
+ * passed to the low-level association functions. At least essid,
872
+ * bssid, channel, beacon, and security must be filled in if you want
873
+ * to build this structure manually.
874
+ */
875
+struct net80211_wlan
876
+{
877
+	/** The human-readable ESSID (network name)
878
+	 *
879
+	 * Although the 802.11 SSID field is generally not
880
+	 * NUL-terminated, the gPXE code adds an extra NUL (and
881
+	 * expects one in this structure) for convenience.
882
+	 */
883
+	char essid[IEEE80211_MAX_SSID_LEN+1];
884
+
885
+	/** MAC address of the strongest-signal access point for this ESSID */
886
+	u8 bssid[ETH_ALEN];
887
+
888
+	/** Signal strength of beacon frame from that access point */
889
+	int signal;
890
+
891
+	/** The channel on which that access point communicates
892
+	 *
893
+	 * This is a raw channel number (net80211_channel::channel_nr),
894
+	 * so that it will not be affected by reconfiguration of the
895
+	 * device channels array.
896
+	 */
897
+	int channel;
898
+
899
+	/** The complete beacon or probe-response frame received */
900
+	struct io_buffer *beacon;
901
+
902
+	/** Security handshaking method used on the network */
903
+	enum net80211_security_proto handshaking;
904
+
905
+	/** Cryptographic algorithm used on the network */
906
+	enum net80211_crypto_alg crypto;
907
+
908
+	/** Link to allow chaining multiple structures into a list to
909
+	    be returned from net80211_probe_finish_all(). */
910
+	struct list_head list;
911
+};
912
+
913
+
914
+/**
915
+ * @defgroup net80211_probe 802.11 network location API
916
+ * @{
917
+ */
918
+int net80211_prepare_probe ( struct net80211_device *dev, int band,
919
+			     int active );
920
+struct net80211_probe_ctx * net80211_probe_start ( struct net80211_device *dev,
921
+						   const char *essid,
922
+						   int active );
923
+int net80211_probe_step ( struct net80211_probe_ctx *ctx );
924
+struct net80211_wlan *
925
+net80211_probe_finish_best ( struct net80211_probe_ctx *ctx );
926
+struct list_head *net80211_probe_finish_all ( struct net80211_probe_ctx *ctx );
927
+
928
+void net80211_free_wlan ( struct net80211_wlan *wlan );
929
+void net80211_free_wlanlist ( struct list_head *list );
930
+/** @} */
931
+
932
+
933
+/**
934
+ * @defgroup net80211_mgmt 802.11 network management API
935
+ * @{
936
+ */
937
+struct net80211_device * net80211_get ( struct net_device *netdev );
938
+void net80211_autoassociate ( struct net80211_device *dev );
939
+
940
+int net80211_change_channel ( struct net80211_device *dev, int channel );
941
+void net80211_set_rate_idx ( struct net80211_device *dev, int rate );
942
+
943
+int net80211_keep_mgmt ( struct net80211_device *dev, int enable );
944
+struct io_buffer * net80211_mgmt_dequeue ( struct net80211_device *dev,
945
+					   int *signal );
946
+int net80211_tx_mgmt ( struct net80211_device *dev, u16 fc,
947
+		       u8 bssid[ETH_ALEN], struct io_buffer *iob );
948
+/** @} */
949
+
950
+
951
+/**
952
+ * @defgroup net80211_assoc 802.11 network association API
953
+ * @{
954
+ */
955
+int net80211_prepare_assoc ( struct net80211_device *dev,
956
+			     struct net80211_wlan *wlan );
957
+int net80211_send_auth ( struct net80211_device *dev,
958
+			 struct net80211_wlan *wlan, int method );
959
+int net80211_send_assoc ( struct net80211_device *dev,
960
+			  struct net80211_wlan *wlan );
961
+/** @} */
962
+
963
+
964
+/**
965
+ * @defgroup net80211_driver 802.11 driver interface API
966
+ * @{
967
+ */
968
+struct net80211_device *net80211_alloc ( size_t priv_size );
969
+int net80211_register ( struct net80211_device *dev,
970
+			struct net80211_device_operations *ops,
971
+			struct net80211_hw_info *hw );
972
+void net80211_rx ( struct net80211_device *dev, struct io_buffer *iob,
973
+		   int signal, u16 rate );
974
+void net80211_rx_err ( struct net80211_device *dev,
975
+		       struct io_buffer *iob, int rc );
976
+void net80211_tx_complete ( struct net80211_device *dev,
977
+			    struct io_buffer *iob, int retries, int rc );
978
+void net80211_unregister ( struct net80211_device *dev );
979
+void net80211_free ( struct net80211_device *dev );
980
+/** @} */
981
+
982
+
983
+#endif

+ 19
- 0
src/include/gpxe/rc80211.h Переглянути файл

@@ -0,0 +1,19 @@
1
+#ifndef _GPXE_RC80211_H
2
+#define _GPXE_RC80211_H
3
+
4
+/** @file
5
+ *
6
+ * Rate-control algorithm prototype for 802.11.
7
+ */
8
+
9
+FILE_LICENCE ( GPL2_OR_LATER );
10
+
11
+struct net80211_device;
12
+struct rc80211_ctx;
13
+
14
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev );
15
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc );
16
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate );
17
+void rc80211_free ( struct rc80211_ctx *ctx );
18
+
19
+#endif /* _GPXE_RC80211_H */

+ 2595
- 0
src/net/80211/net80211.c
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 371
- 0
src/net/80211/rc80211.c Переглянути файл

@@ -0,0 +1,371 @@
1
+/*
2
+ * Simple 802.11 rate-control algorithm for gPXE.
3
+ *
4
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
5
+ *
6
+ * This program is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU General Public License as
8
+ * published by the Free Software Foundation; either version 2 of the
9
+ * License, or any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful, but
12
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
+ */
20
+
21
+FILE_LICENCE ( GPL2_OR_LATER );
22
+
23
+#include <stdlib.h>
24
+#include <gpxe/net80211.h>
25
+
26
+/**
27
+ * @file
28
+ *
29
+ * Simple 802.11 rate-control algorithm
30
+ */
31
+
32
+/** @page rc80211 Rate control philosophy
33
+ *
34
+ * We want to maximize our transmission speed, to the extent that we
35
+ * can do that without dropping undue numbers of packets. We also
36
+ * don't want to take up very much code space, so our algorithm has to
37
+ * be pretty simple
38
+ *
39
+ * When we receive a packet, we know what rate it was transmitted at,
40
+ * and whether it had to be retransmitted to get to us.
41
+ *
42
+ * When we send a packet, we hear back how many times it had to be
43
+ * retried to get through, and whether it got through at all.
44
+ *
45
+ * Indications of TX success are more reliable than RX success, but RX
46
+ * information helps us know where to start.
47
+ *
48
+ * To handle all of this, we keep for each rate and each direction (TX
49
+ * and RX separately) some state information for the most recent
50
+ * packets on that rate and the number of packets for which we have
51
+ * information. The state is a 32-bit unsigned integer in which two
52
+ * bits represent a packet: 11 if it went through well, 10 if it went
53
+ * through with one retry, 01 if it went through with more than one
54
+ * retry, or 00 if it didn't go through at all. We define the
55
+ * "goodness" for a particular (rate, direction) combination as the
56
+ * sum of all the 2-bit fields, times 33, divided by the number of
57
+ * 2-bit fields containing valid information (16 except when we're
58
+ * starting out). The number produced is between 0 and 99; we use -1
59
+ * for rates with less than 4 RX packets or 1 TX, as an indicator that
60
+ * we do not have enough information to rely on them.
61
+ *
62
+ * In deciding which rates are best, we find the weighted average of
63
+ * TX and RX goodness, where the weighting is by number of packets
64
+ * with data and TX packets are worth 4 times as much as RX packets.
65
+ * The weighted average is called "net goodness" and is also a number
66
+ * between 0 and 99.  If 3 consecutive packets fail transmission
67
+ * outright, we automatically ratchet down the rate; otherwise, we
68
+ * switch to the best rate whenever the current rate's goodness falls
69
+ * below some threshold, and try increasing our rate when the goodness
70
+ * is very high.
71
+ *
72
+ * This system is optimized for gPXE's style of usage. Because normal
73
+ * operation always involves receiving something, we'll make our way
74
+ * to the best rate pretty quickly. We tend to follow the lead of the
75
+ * sending AP in choosing rates, but we won't use rates for long that
76
+ * don't work well for us in transmission. We assume gPXE won't be
77
+ * running for long enough that rate patterns will change much, so we
78
+ * don't have to keep time counters or the like.  And if this doesn't
79
+ * work well in practice there are many ways it could be tweaked.
80
+ *
81
+ * To avoid staying at 1Mbps for a long time, we don't track any
82
+ * transmitted packets until we've set our rate based on received
83
+ * packets.
84
+ */
85
+
86
+/** Two-bit packet status indicator for a packet with no retries */
87
+#define RC_PKT_OK		0x3
88
+
89
+/** Two-bit packet status indicator for a packet with one retry */
90
+#define RC_PKT_RETRIED_ONCE	0x2
91
+
92
+/** Two-bit packet status indicator for a TX packet with multiple retries
93
+ *
94
+ * It is not possible to tell whether an RX packet had one or multiple
95
+ * retries; we rely instead on the fact that failed RX packets won't
96
+ * get to us at all, so if we receive a lot of RX packets on a certain
97
+ * rate it must be pretty good.
98
+ */
99
+#define RC_PKT_RETRIED_MULTI	0x1
100
+
101
+/** Two-bit packet status indicator for a TX packet that was never ACKed
102
+ *
103
+ * It is not possible to tell whether an RX packet was setn if it
104
+ * didn't get through to us, but if we don't see one we won't increase
105
+ * the goodness for its rate. This asymmetry is part of why TX packets
106
+ * are weighted much more heavily than RX.
107
+ */
108
+#define RC_PKT_FAILED		0x0
109
+
110
+/** Number of times to weight TX packets more heavily than RX packets */
111
+#define RC_TX_FACTOR		4
112
+
113
+/** Number of consecutive failed TX packets that cause an automatic rate drop */
114
+#define RC_TX_EMERG_FAIL	3
115
+
116
+/** Minimum net goodness below which we will search for a better rate */
117
+#define RC_GOODNESS_MIN		85
118
+
119
+/** Maximum net goodness above which we will try to increase our rate */
120
+#define RC_GOODNESS_MAX		95
121
+
122
+/** Minimum (num RX + @c RC_TX_FACTOR * num TX) to use a certain rate */
123
+#define RC_UNCERTAINTY_THRESH	4
124
+
125
+/** TX direction */
126
+#define TX	0
127
+
128
+/** RX direction */
129
+#define RX	1
130
+
131
+/** A rate control context */
132
+struct rc80211_ctx
133
+{
134
+	/** Goodness state for each rate, TX and RX */
135
+	u32 goodness[2][NET80211_MAX_RATES];
136
+
137
+	/** Number of packets recorded for each rate */
138
+	u8 count[2][NET80211_MAX_RATES];
139
+
140
+	/** Indication of whether we've set the device rate yet */
141
+	int started;
142
+
143
+	/** Counter of all packets sent and received */
144
+	int packets;
145
+};
146
+
147
+/**
148
+ * Initialize rate-control algorithm
149
+ *
150
+ * @v dev	802.11 device
151
+ * @ret ctx	Rate-control context, to be stored in @c dev->rctl
152
+ */
153
+struct rc80211_ctx * rc80211_init ( struct net80211_device *dev __unused )
154
+{
155
+	struct rc80211_ctx *ret = zalloc ( sizeof ( *ret ) );
156
+	return ret;
157
+}
158
+
159
+/**
160
+ * Calculate net goodness for a certain rate
161
+ *
162
+ * @v ctx	Rate-control context
163
+ * @v rate_idx	Index of rate to calculate net goodness for
164
+ */
165
+static int rc80211_calc_net_goodness ( struct rc80211_ctx *ctx,
166
+				       int rate_idx )
167
+{
168
+	int sum[2], num[2], dir, pkt;
169
+
170
+	for ( dir = 0; dir < 2; dir++ ) {
171
+		u32 good = ctx->goodness[dir][rate_idx];
172
+
173
+		num[dir] = ctx->count[dir][rate_idx];
174
+		sum[dir] = 0;
175
+
176
+		for ( pkt = 0; pkt < num[dir]; pkt++ )
177
+			sum[dir] += ( good >> ( 2 * pkt ) ) & 0x3;
178
+	}
179
+
180
+	if ( ( num[TX] * RC_TX_FACTOR + num[RX] ) < RC_UNCERTAINTY_THRESH )
181
+		return -1;
182
+
183
+	return ( 33 * ( sum[TX] * RC_TX_FACTOR + sum[RX] ) /
184
+		      ( num[TX] * RC_TX_FACTOR + num[RX] ) );
185
+}
186
+
187
+/**
188
+ * Determine the best rate to switch to and return it
189
+ *
190
+ * @v dev		802.11 device
191
+ * @ret rate_idx	Index of the best rate to switch to
192
+ */
193
+static int rc80211_pick_best ( struct net80211_device *dev )
194
+{
195
+	struct rc80211_ctx *ctx = dev->rctl;
196
+	int best_net_good = 0, best_rate = -1, i;
197
+
198
+	for ( i = 0; i < dev->nr_rates; i++ ) {
199
+		int net_good = rc80211_calc_net_goodness ( ctx, i );
200
+
201
+		if ( net_good > best_net_good ||
202
+		     ( best_net_good > RC_GOODNESS_MIN &&
203
+		       net_good > RC_GOODNESS_MIN ) ) {
204
+			best_net_good = net_good;
205
+			best_rate = i;
206
+		}
207
+	}
208
+
209
+	if ( best_rate >= 0 ) {
210
+		int old_good = rc80211_calc_net_goodness ( ctx, dev->rate );
211
+		if ( old_good != best_net_good )
212
+			DBGC ( ctx, "802.11 RC %p switching from goodness "
213
+			       "%d to %d\n", ctx, old_good, best_net_good );
214
+
215
+		ctx->started = 1;
216
+		return best_rate;
217
+	}
218
+
219
+	return dev->rate;
220
+}
221
+
222
+/**
223
+ * Set 802.11 device rate
224
+ *
225
+ * @v dev	802.11 device
226
+ * @v rate_idx	Index of rate to switch to
227
+ *
228
+ * This is a thin wrapper around net80211_set_rate_idx to insert a
229
+ * debugging message where appropriate.
230
+ */
231
+static inline void rc80211_set_rate ( struct net80211_device *dev,
232
+				      int rate_idx )
233
+{
234
+	DBGC ( dev->rctl, "802.11 RC %p changing rate %d->%d Mbps\n", dev->rctl,
235
+	       dev->rates[dev->rate] / 10, dev->rates[rate_idx] / 10 );
236
+
237
+	net80211_set_rate_idx ( dev, rate_idx );
238
+}
239
+
240
+/**
241
+ * Check rate-control state and change rate if necessary
242
+ *
243
+ * @v dev	802.11 device
244
+ */
245
+static void rc80211_maybe_set_new ( struct net80211_device *dev )
246
+{
247
+	struct rc80211_ctx *ctx = dev->rctl;
248
+	int net_good;
249
+
250
+	net_good = rc80211_calc_net_goodness ( ctx, dev->rate );
251
+
252
+	if ( ! ctx->started ) {
253
+		rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
254
+		return;
255
+	}
256
+
257
+	if ( net_good < 0 )	/* insufficient data */
258
+		return;
259
+
260
+	if ( net_good > RC_GOODNESS_MAX && dev->rate + 1 < dev->nr_rates ) {
261
+		int higher = rc80211_calc_net_goodness ( ctx, dev->rate + 1 );
262
+		if ( higher > net_good || higher < 0 )
263
+			rc80211_set_rate ( dev, dev->rate + 1 );
264
+		else
265
+			rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
266
+	}
267
+
268
+	if ( net_good < RC_GOODNESS_MIN ) {
269
+		rc80211_set_rate ( dev, rc80211_pick_best ( dev ) );
270
+	}
271
+}
272
+
273
+/**
274
+ * Update rate-control state
275
+ *
276
+ * @v dev		802.11 device
277
+ * @v direction		One of the direction constants TX or RX
278
+ * @v rate_idx		Index of rate at which packet was sent or received
279
+ * @v retries		Number of times packet was retried before success
280
+ * @v failed		If nonzero, the packet failed to get through
281
+ */
282
+static void rc80211_update ( struct net80211_device *dev, int direction,
283
+			     int rate_idx, int retries, int failed )
284
+{
285
+	struct rc80211_ctx *ctx = dev->rctl;
286
+	u32 goodness = ctx->goodness[direction][rate_idx];
287
+
288
+	if ( ctx->count[direction][rate_idx] < 16 )
289
+		ctx->count[direction][rate_idx]++;
290
+
291
+	goodness <<= 2;
292
+	if ( failed )
293
+		goodness |= RC_PKT_FAILED;
294
+	else if ( retries > 1 )
295
+		goodness |= RC_PKT_RETRIED_MULTI;
296
+	else if ( retries )
297
+		goodness |= RC_PKT_RETRIED_ONCE;
298
+	else
299
+		goodness |= RC_PKT_OK;
300
+
301
+	ctx->goodness[direction][rate_idx] = goodness;
302
+
303
+	ctx->packets++;
304
+
305
+	rc80211_maybe_set_new ( dev );
306
+}
307
+
308
+/**
309
+ * Update rate-control state for transmitted packet
310
+ *
311
+ * @v dev	802.11 device
312
+ * @v retries	Number of times packet was transmitted before success
313
+ * @v rc	Return status code for transmission
314
+ */
315
+void rc80211_update_tx ( struct net80211_device *dev, int retries, int rc )
316
+{
317
+	struct rc80211_ctx *ctx = dev->rctl;
318
+
319
+	if ( ! ctx->started )
320
+		return;
321
+
322
+	rc80211_update ( dev, TX, dev->rate, retries, rc );
323
+
324
+	/* Check if the last RC_TX_EMERG_FAIL packets have all failed */
325
+	if ( ! ( ctx->goodness[TX][dev->rate] &
326
+		 ( ( 1 << ( 2 * RC_TX_EMERG_FAIL ) ) - 1 ) ) ) {
327
+		if ( dev->rate == 0 )
328
+			DBGC ( dev->rctl, "802.11 RC %p saw %d consecutive "
329
+			       "failed TX, but cannot lower rate any further\n",
330
+			       dev->rctl, RC_TX_EMERG_FAIL );
331
+		else {
332
+			DBGC ( dev->rctl, "802.11 RC %p lowering rate (%d->%d "
333
+			       "Mbps) due to %d consecutive TX failures\n",
334
+			       dev->rctl, dev->rates[dev->rate] / 10,
335
+			       dev->rates[dev->rate - 1] / 10,
336
+			       RC_TX_EMERG_FAIL );
337
+
338
+			rc80211_set_rate ( dev, dev->rate - 1 );
339
+		}
340
+	}
341
+}
342
+
343
+/**
344
+ * Update rate-control state for received packet
345
+ *
346
+ * @v dev	802.11 device
347
+ * @v retry	Whether the received packet had been retransmitted
348
+ * @v rate	Rate at which packet was received, in 100 kbps units
349
+ */
350
+void rc80211_update_rx ( struct net80211_device *dev, int retry, u16 rate )
351
+{
352
+	int ridx;
353
+
354
+	for ( ridx = 0; ridx < dev->nr_rates && dev->rates[ridx] != rate;
355
+	      ridx++ )
356
+		;
357
+	if ( ridx >= dev->nr_rates )
358
+		return;		/* couldn't find the rate */
359
+
360
+	rc80211_update ( dev, RX, ridx, retry, 0 );
361
+}
362
+
363
+/**
364
+ * Free rate-control context
365
+ *
366
+ * @v ctx	Rate-control context
367
+ */
368
+void rc80211_free ( struct rc80211_ctx *ctx )
369
+{
370
+	free ( ctx );
371
+}

Завантаження…
Відмінити
Зберегти