Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/ath/ath_rate/onoe/onoe.c
39566 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer,
12
* without modification.
13
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
14
* similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
15
* redistribution must be conditioned upon including a substantially
16
* similar Disclaimer requirement for further binary redistribution.
17
*
18
* NO WARRANTY
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
* LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
22
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
* THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
24
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29
* THE POSSIBILITY OF SUCH DAMAGES.
30
*/
31
32
#include <sys/cdefs.h>
33
/*
34
* Atsushi Onoe's rate control algorithm.
35
*/
36
#include "opt_ath.h"
37
#include "opt_inet.h"
38
#include "opt_wlan.h"
39
40
#include <sys/param.h>
41
#include <sys/systm.h>
42
#include <sys/sysctl.h>
43
#include <sys/kernel.h>
44
#include <sys/lock.h>
45
#include <sys/mutex.h>
46
#include <sys/errno.h>
47
48
#include <machine/bus.h>
49
#include <machine/resource.h>
50
#include <sys/bus.h>
51
52
#include <sys/socket.h>
53
54
#include <net/if.h>
55
#include <net/if_media.h>
56
#include <net/if_arp.h>
57
#include <net/ethernet.h> /* XXX for ether_sprintf */
58
59
#include <net80211/ieee80211_var.h>
60
61
#include <net/bpf.h>
62
63
#ifdef INET
64
#include <netinet/in.h>
65
#include <netinet/if_ether.h>
66
#endif
67
68
#include <dev/ath/if_athvar.h>
69
#include <dev/ath/ath_rate/onoe/onoe.h>
70
#include <dev/ath/ath_hal/ah_desc.h>
71
72
/*
73
* Default parameters for the rate control algorithm. These are
74
* all tunable with sysctls. The rate controller runs periodically
75
* (each ath_rateinterval ms) analyzing transmit statistics for each
76
* neighbor/station (when operating in station mode this is only the AP).
77
* If transmits look to be working well over a sampling period then
78
* it gives a "raise rate credit". If transmits look to not be working
79
* well than it deducts a credit. If the credits cross a threshold then
80
* the transmit rate is raised. Various error conditions force the
81
* the transmit rate to be dropped.
82
*
83
* The decision to issue/deduct a credit is based on the errors and
84
* retries accumulated over the sampling period. ath_rate_raise defines
85
* the percent of retransmits for which a credit is issued/deducted.
86
* ath_rate_raise_threshold defines the threshold on credits at which
87
* the transmit rate is increased.
88
*
89
* XXX this algorithm is flawed.
90
*/
91
static int ath_rateinterval = 1000; /* rate ctl interval (ms) */
92
static int ath_rate_raise = 10; /* add credit threshold */
93
static int ath_rate_raise_threshold = 10; /* rate ctl raise threshold */
94
95
static void ath_rate_update(struct ath_softc *, struct ieee80211_node *,
96
int rate);
97
static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *);
98
static void ath_rate_ctl(void *, struct ieee80211_node *);
99
100
void
101
ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
102
{
103
/* NB: assumed to be zero'd by caller */
104
}
105
106
void
107
ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
108
{
109
}
110
111
void
112
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
113
int shortPreamble, size_t frameLen, int tid, int is_aggr,
114
u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur,
115
int *maxpktlen)
116
{
117
struct onoe_node *on = ATH_NODE_ONOE(an);
118
119
*rix = on->on_tx_rix0;
120
*try0 = on->on_tx_try0;
121
if (shortPreamble)
122
*txrate = on->on_tx_rate0sp;
123
else
124
*txrate = on->on_tx_rate0;
125
*maxdur = -1;
126
*maxpktlen = -1;
127
}
128
129
/*
130
* Get the TX rates.
131
*
132
* The short preamble bits aren't set here; the caller should augment
133
* the returned rate with the relevant preamble rate flag.
134
*/
135
void
136
ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
137
uint8_t rix0, int is_aggr, struct ath_rc_series *rc)
138
{
139
struct onoe_node *on = ATH_NODE_ONOE(an);
140
141
rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
142
143
rc[0].rix = on->on_tx_rate0;
144
rc[1].rix = on->on_tx_rate1;
145
rc[2].rix = on->on_tx_rate2;
146
rc[3].rix = on->on_tx_rate3;
147
148
rc[0].tries = on->on_tx_try0;
149
rc[1].tries = 2;
150
rc[2].tries = 2;
151
rc[3].tries = 2;
152
}
153
154
void
155
ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
156
struct ath_desc *ds, int shortPreamble, u_int8_t rix)
157
{
158
struct onoe_node *on = ATH_NODE_ONOE(an);
159
160
ath_hal_setupxtxdesc(sc->sc_ah, ds
161
, on->on_tx_rate1sp, 2 /* series 1 */
162
, on->on_tx_rate2sp, 2 /* series 2 */
163
, on->on_tx_rate3sp, 2 /* series 3 */
164
);
165
}
166
167
void
168
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
169
const struct ath_rc_series *rc, const struct ath_tx_status *ts,
170
int frame_size, int rc_framesize, int nframes, int nbad)
171
{
172
struct onoe_node *on = ATH_NODE_ONOE(an);
173
174
if (ts->ts_status == 0)
175
on->on_tx_ok++;
176
else
177
on->on_tx_err++;
178
on->on_tx_retr += ts->ts_shortretry
179
+ ts->ts_longretry;
180
if (on->on_interval != 0 && ticks - on->on_ticks > on->on_interval) {
181
ath_rate_ctl(sc, &an->an_node);
182
on->on_ticks = ticks;
183
}
184
}
185
186
void
187
ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
188
{
189
if (isnew)
190
ath_rate_ctl_start(sc, &an->an_node);
191
}
192
193
void
194
ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
195
{
196
}
197
198
static void
199
ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate)
200
{
201
struct ath_node *an = ATH_NODE(ni);
202
struct onoe_node *on = ATH_NODE_ONOE(an);
203
struct ieee80211vap *vap = ni->ni_vap;
204
const HAL_RATE_TABLE *rt = sc->sc_currates;
205
u_int8_t rix;
206
uint8_t dot11rate;
207
208
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
209
210
IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni,
211
"%s: set xmit rate to %dM", __func__,
212
ni->ni_rates.rs_nrates > 0 ?
213
(ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0);
214
215
/*
216
* Before associating a node has no rate set setup
217
* so we can't calculate any transmit codes to use.
218
* This is ok since we should never be sending anything
219
* but management frames and those always go at the
220
* lowest hardware rate.
221
*/
222
if (ni->ni_rates.rs_nrates == 0)
223
goto done;
224
on->on_rix = rate;
225
dot11rate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL;
226
ieee80211_node_set_txrate_dot11rate(ni, dot11rate);
227
on->on_tx_rix0 = sc->sc_rixmap[dot11rate];
228
on->on_tx_rate0 = rt->info[on->on_tx_rix0].rateCode;
229
230
on->on_tx_rate0sp = on->on_tx_rate0 |
231
rt->info[on->on_tx_rix0].shortPreamble;
232
if (sc->sc_mrretry) {
233
/*
234
* Hardware supports multi-rate retry; setup two
235
* step-down retry rates and make the lowest rate
236
* be the ``last chance''. We use 4, 2, 2, 2 tries
237
* respectively (4 is set here, the rest are fixed
238
* in the xmit routine).
239
*/
240
on->on_tx_try0 = 1 + 3; /* 4 tries at rate 0 */
241
if (--rate >= 0) {
242
rix = sc->sc_rixmap[
243
ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
244
on->on_tx_rate1 = rt->info[rix].rateCode;
245
on->on_tx_rate1sp = on->on_tx_rate1 |
246
rt->info[rix].shortPreamble;
247
} else {
248
on->on_tx_rate1 = on->on_tx_rate1sp = 0;
249
}
250
if (--rate >= 0) {
251
rix = sc->sc_rixmap[
252
ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL];
253
on->on_tx_rate2 = rt->info[rix].rateCode;
254
on->on_tx_rate2sp = on->on_tx_rate2 |
255
rt->info[rix].shortPreamble;
256
} else {
257
on->on_tx_rate2 = on->on_tx_rate2sp = 0;
258
}
259
if (rate > 0) {
260
/* NB: only do this if we didn't already do it above */
261
on->on_tx_rate3 = rt->info[0].rateCode;
262
on->on_tx_rate3sp =
263
on->on_tx_rate3 | rt->info[0].shortPreamble;
264
} else {
265
on->on_tx_rate3 = on->on_tx_rate3sp = 0;
266
}
267
} else {
268
on->on_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */
269
on->on_tx_rate1 = on->on_tx_rate1sp = 0;
270
on->on_tx_rate2 = on->on_tx_rate2sp = 0;
271
on->on_tx_rate3 = on->on_tx_rate3sp = 0;
272
}
273
done:
274
on->on_tx_ok = on->on_tx_err = on->on_tx_retr = on->on_tx_upper = 0;
275
276
on->on_interval = ath_rateinterval;
277
if (vap->iv_opmode == IEEE80211_M_STA)
278
on->on_interval /= 2;
279
on->on_interval = (on->on_interval * hz) / 1000;
280
}
281
282
/*
283
* Set the starting transmit rate for a node.
284
*/
285
static void
286
ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni)
287
{
288
#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
289
const struct ieee80211_txparam *tp = ni->ni_txparms;
290
int srate;
291
292
KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
293
if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) {
294
/*
295
* No fixed rate is requested. For 11b start with
296
* the highest negotiated rate; otherwise, for 11g
297
* and 11a, we start "in the middle" at 24Mb or 36Mb.
298
*/
299
srate = ni->ni_rates.rs_nrates - 1;
300
if (sc->sc_curmode != IEEE80211_MODE_11B) {
301
/*
302
* Scan the negotiated rate set to find the
303
* closest rate.
304
*/
305
/* NB: the rate set is assumed sorted */
306
for (; srate >= 0 && RATE(srate) > 72; srate--)
307
;
308
}
309
} else {
310
/*
311
* A fixed rate is to be used; ic_fixed_rate is the
312
* IEEE code for this rate (sans basic bit). Convert this
313
* to the index into the negotiated rate set for
314
* the node. We know the rate is there because the
315
* rate set is checked when the station associates.
316
*/
317
/* NB: the rate set is assumed sorted */
318
srate = ni->ni_rates.rs_nrates - 1;
319
for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--)
320
;
321
}
322
/*
323
* The selected rate may not be available due to races
324
* and mode settings. Also orphaned nodes created in
325
* adhoc mode may not have any rate set so this lookup
326
* can fail. This is not fatal.
327
*/
328
ath_rate_update(sc, ni, srate < 0 ? 0 : srate);
329
#undef RATE
330
}
331
332
/*
333
* Examine and potentially adjust the transmit rate.
334
*/
335
static void
336
ath_rate_ctl(void *arg, struct ieee80211_node *ni)
337
{
338
struct ath_softc *sc = arg;
339
struct onoe_node *on = ATH_NODE_ONOE(ATH_NODE(ni));
340
struct ieee80211_rateset *rs = &ni->ni_rates;
341
int dir = 0, nrate, enough;
342
343
/*
344
* Rate control
345
* XXX: very primitive version.
346
*/
347
enough = (on->on_tx_ok + on->on_tx_err >= 10);
348
349
/* no packet reached -> down */
350
if (on->on_tx_err > 0 && on->on_tx_ok == 0)
351
dir = -1;
352
353
/* all packets needs retry in average -> down */
354
if (enough && on->on_tx_ok < on->on_tx_retr)
355
dir = -1;
356
357
/* no error and less than rate_raise% of packets need retry -> up */
358
if (enough && on->on_tx_err == 0 &&
359
on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100)
360
dir = 1;
361
362
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
363
"ok %d err %d retr %d upper %d dir %d",
364
on->on_tx_ok, on->on_tx_err, on->on_tx_retr, on->on_tx_upper, dir);
365
366
nrate = on->on_rix;
367
switch (dir) {
368
case 0:
369
if (enough && on->on_tx_upper > 0)
370
on->on_tx_upper--;
371
break;
372
case -1:
373
if (nrate > 0) {
374
nrate--;
375
sc->sc_stats.ast_rate_drop++;
376
}
377
on->on_tx_upper = 0;
378
break;
379
case 1:
380
/* raise rate if we hit rate_raise_threshold */
381
if (++on->on_tx_upper < ath_rate_raise_threshold)
382
break;
383
on->on_tx_upper = 0;
384
if (nrate + 1 < rs->rs_nrates) {
385
nrate++;
386
sc->sc_stats.ast_rate_raise++;
387
}
388
break;
389
}
390
391
if (nrate != on->on_rix) {
392
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
393
"%s: %dM -> %dM (%d ok, %d err, %d retr)", __func__,
394
ieee80211_node_get_txrate_kbit(ni) / 1000,
395
(rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2,
396
on->on_tx_ok, on->on_tx_err, on->on_tx_retr);
397
ath_rate_update(sc, ni, nrate);
398
} else if (enough)
399
on->on_tx_ok = on->on_tx_err = on->on_tx_retr = 0;
400
}
401
402
static void
403
ath_rate_sysctlattach(struct ath_softc *sc)
404
{
405
struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
406
struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
407
408
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
409
"rate_interval", CTLFLAG_RW, &ath_rateinterval, 0,
410
"rate control: operation interval (ms)");
411
/* XXX bounds check values */
412
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
413
"rate_raise", CTLFLAG_RW, &ath_rate_raise, 0,
414
"rate control: retry threshold to credit rate raise (%%)");
415
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
416
"rate_raise_threshold", CTLFLAG_RW, &ath_rate_raise_threshold,0,
417
"rate control: # good periods before raising rate");
418
}
419
420
static int
421
ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an,
422
struct ath_rateioctl *re)
423
{
424
425
return (EINVAL);
426
}
427
428
struct ath_ratectrl *
429
ath_rate_attach(struct ath_softc *sc)
430
{
431
struct onoe_softc *osc;
432
433
osc = malloc(sizeof(struct onoe_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
434
if (osc == NULL)
435
return NULL;
436
osc->arc.arc_space = sizeof(struct onoe_node);
437
ath_rate_sysctlattach(sc);
438
439
return &osc->arc;
440
}
441
442
void
443
ath_rate_detach(struct ath_ratectrl *arc)
444
{
445
struct onoe_softc *osc = (struct onoe_softc *) arc;
446
447
free(osc, M_DEVBUF);
448
}
449
450