FreeBSD kernel ATH device code
sample.c
Go to the documentation of this file.
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2005 John Bicket
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 * 3. Neither the names of the above-listed copyright holders nor the names
18 * of any contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * Alternatively, this software may be distributed under the terms of the
22 * GNU General Public License ("GPL") version 2 as published by the Free
23 * Software Foundation.
24 *
25 * NO WARRANTY
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
30 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
31 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
36 * THE POSSIBILITY OF SUCH DAMAGES.
37 *
38 */
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD$");
42
43/*
44 * John Bicket's SampleRate control algorithm.
45 */
46#include "opt_ath.h"
47#include "opt_inet.h"
48#include "opt_wlan.h"
49#include "opt_ah.h"
50
51#include <sys/param.h>
52#include <sys/systm.h>
53#include <sys/sysctl.h>
54#include <sys/kernel.h>
55#include <sys/lock.h>
56#include <sys/malloc.h>
57#include <sys/mutex.h>
58#include <sys/errno.h>
59
60#include <machine/bus.h>
61#include <machine/resource.h>
62#include <sys/bus.h>
63
64#include <sys/socket.h>
65
66#include <net/if.h>
67#include <net/if_var.h>
68#include <net/if_media.h>
69#include <net/if_arp.h>
70#include <net/ethernet.h> /* XXX for ether_sprintf */
71
72#include <net80211/ieee80211_var.h>
73
74#include <net/bpf.h>
75
76#ifdef INET
77#include <netinet/in.h>
78#include <netinet/if_ether.h>
79#endif
80
81#include <dev/ath/if_athvar.h>
85
86/*
87 * This file is an implementation of the SampleRate algorithm
88 * in "Bit-rate Selection in Wireless Networks"
89 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps)
90 *
91 * SampleRate chooses the bit-rate it predicts will provide the most
92 * throughput based on estimates of the expected per-packet
93 * transmission time for each bit-rate. SampleRate periodically sends
94 * packets at bit-rates other than the current one to estimate when
95 * another bit-rate will provide better performance. SampleRate
96 * switches to another bit-rate when its estimated per-packet
97 * transmission time becomes smaller than the current bit-rate's.
98 * SampleRate reduces the number of bit-rates it must sample by
99 * eliminating those that could not perform better than the one
100 * currently being used. SampleRate also stops probing at a bit-rate
101 * if it experiences several successive losses.
102 *
103 * The difference between the algorithm in the thesis and the one in this
104 * file is that the one in this file uses a ewma instead of a window.
105 *
106 * Also, this implementation tracks the average transmission time for
107 * a few different packet sizes independently for each link.
108 */
109
110/* XXX TODO: move this into ath_hal/net80211 so it can be shared */
111
112#define MCS_HT20 0
113#define MCS_HT20_SGI 1
114#define MCS_HT40 2
115#define MCS_HT40_SGI 3
116
117/*
118 * This is currently a copy/paste from the 11n tx code.
119 *
120 * It's used to determine the maximum frame length allowed for the
121 * given rate. For now this ignores SGI/LGI and will assume long-GI.
122 * This only matters for lower rates that can't fill a full 64k A-MPDU.
123 *
124 * (But it's also important because right now rate control doesn't set
125 * flags like SGI/LGI, STBC, LDPC, TX power, etc.)
126 *
127 * When selecting a set of rates the rate control code will iterate
128 * over the HT20/HT40 max frame length and tell the caller the maximum
129 * length (@ LGI.) It will also choose a bucket that's the minimum
130 * of this value and the provided aggregate length. That way the
131 * rate selection will closely match what the eventual formed aggregate
132 * will be rather than "not at all".
133 */
134
136 [MCS_HT20] = {
137 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
138 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
139 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
140 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
141 },
142 [MCS_HT20_SGI] = {
143 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
144 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
145 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
146 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
147 },
148 [MCS_HT40] = {
149 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
150 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
151 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
152 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
153 },
154 [MCS_HT40_SGI] = {
155 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
156 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
157 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
158 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
159 }
160};
161
162/*
163 * Given the (potentially MRR) transmit schedule, calculate the maximum
164 * allowed packet size for forming aggregates based on the lowest
165 * MCS rate in the transmit schedule.
166 *
167 * Returns -1 if it's a legacy rate or no MRR.
168 *
169 * XXX TODO: this needs to be limited by the RTS/CTS AR5416 8KB bug limit!
170 * (by checking rts/cts flags and applying sc_rts_aggr_limit)
171 *
172 * XXX TODO: apply per-node max-ampdu size and driver ampdu size limits too.
173 */
174static int
176 struct ath_node *an, uint8_t rix0, int is_aggr)
177{
178#define MCS_IDX(ix) (rt->info[ix].dot11Rate)
179 const HAL_RATE_TABLE *rt = sc->sc_currates;
180 struct sample_node *sn = ATH_NODE_SAMPLE(an);
181 const struct txschedule *sched = &sn->sched[rix0];
182 int max_pkt_length = 65530; // ATH_AGGR_MAXSIZE
183 // Note: this may not be true in all cases; need to check?
184 int is_ht40 = (an->an_node.ni_chw == 40);
185 // Note: not great, but good enough..
186 int idx = is_ht40 ? MCS_HT40 : MCS_HT20;
187
188 if (rt->info[rix0].phy != IEEE80211_T_HT) {
189 return -1;
190 }
191
192 if (! sc->sc_mrretry) {
193 return -1;
194 }
195
196 KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n",
197 rix0, sched->r0));
198
199 /*
200 * Update based on sched->r{0,1,2,3} if sched->t{0,1,2,3}
201 * is not zero.
202 *
203 * Note: assuming all four PHYs are HT!
204 *
205 * XXX TODO: right now I hardcode here and in getxtxrates() that
206 * rates 2 and 3 in the tx schedule are ignored. This is important
207 * for forming larger aggregates because right now (a) the tx schedule
208 * per rate is fixed, and (b) reliable packet transmission at those
209 * higher rates kinda needs a lower MCS rate in there somewhere.
210 * However, this means we can only form shorter aggregates.
211 * If we've negotiated aggregation then we can actually just
212 * rely on software retransmit rather than having things fall
213 * back to like MCS0/1 in hardware, and rate control will hopefully
214 * do the right thing.
215 *
216 * Once the whole rate schedule is passed into ath_rate_findrate(),
217 * the ath_rc_series is populated ,the fixed tx schedule stuff
218 * is removed AND getxtxrates() is removed then we can remove this
219 * check as it can just NOT populate t2/t3. It also means
220 * probing can actually use rix0 for probeing and rix1 for the
221 * current best rate..
222 */
223 if (sched->t0 != 0) {
224 max_pkt_length = MIN(max_pkt_length,
226 }
227 if (sched->t1 != 0) {
228 max_pkt_length = MIN(max_pkt_length,
230 }
231 if (sched->t2 != 0 && (! is_aggr)) {
232 max_pkt_length = MIN(max_pkt_length,
234 }
235 if (sched->t3 != 0 && (! is_aggr)) {
236 max_pkt_length = MIN(max_pkt_length,
238 }
239
240 return max_pkt_length;
241#undef MCS
242}
243
244static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
245
246static __inline int
247size_to_bin(int size)
248{
249#if NUM_PACKET_SIZE_BINS > 1
250 if (size <= packet_size_bins[0])
251 return 0;
252#endif
253#if NUM_PACKET_SIZE_BINS > 2
254 if (size <= packet_size_bins[1])
255 return 1;
256#endif
257#if NUM_PACKET_SIZE_BINS > 3
258 if (size <= packet_size_bins[2])
259 return 2;
260#endif
261#if NUM_PACKET_SIZE_BINS > 4
262 if (size <= packet_size_bins[3])
263 return 3;
264#endif
265#if NUM_PACKET_SIZE_BINS > 5
266 if (size <= packet_size_bins[4])
267 return 4;
268#endif
269#if NUM_PACKET_SIZE_BINS > 6
270 if (size <= packet_size_bins[5])
271 return 5;
272#endif
273#if NUM_PACKET_SIZE_BINS > 7
274 if (size <= packet_size_bins[6])
275 return 6;
276#endif
277#if NUM_PACKET_SIZE_BINS > 8
278#error "add support for more packet sizes"
279#endif
280 return NUM_PACKET_SIZE_BINS-1;
281}
282
283void
284ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
285{
286 /* NB: assumed to be zero'd by caller */
287}
288
289void
291{
292}
293
294static int
295dot11rate(const HAL_RATE_TABLE *rt, int rix)
296{
297 if (rix < 0)
298 return -1;
299 return rt->info[rix].phy == IEEE80211_T_HT ?
300 rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2;
301}
302
303static const char *
305{
306 if (rix < 0)
307 return "";
308 return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb ";
309}
310
311/*
312 * Return the rix with the lowest average_tx_time,
313 * or -1 if all the average_tx_times are 0.
314 */
315static __inline int
317 int size_bin, int require_acked_before)
318{
319 struct sample_node *sn = ATH_NODE_SAMPLE(an);
320 int best_rate_rix, best_rate_tt, best_rate_pct;
321 uint64_t mask;
322 int rix, tt, pct;
323
324 best_rate_rix = 0;
325 best_rate_tt = 0;
326 best_rate_pct = 0;
327 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
328 if ((mask & 1) == 0) /* not a supported rate */
329 continue;
330
331 /* Don't pick a non-HT rate for a HT node */
332 if ((an->an_node.ni_flags & IEEE80211_NODE_HT) &&
333 (rt->info[rix].phy != IEEE80211_T_HT)) {
334 continue;
335 }
336
337 tt = sn->stats[size_bin][rix].average_tx_time;
338 if (tt <= 0 ||
339 (require_acked_before &&
340 !sn->stats[size_bin][rix].packets_acked))
341 continue;
342
343 /* Calculate percentage if possible */
344 if (sn->stats[size_bin][rix].total_packets > 0) {
345 pct = sn->stats[size_bin][rix].ewma_pct;
346 } else {
347 pct = -1; /* No percent yet to compare against! */
348 }
349
350 /* don't use a bit-rate that has been failing */
351 if (sn->stats[size_bin][rix].successive_failures > 3)
352 continue;
353
354 /*
355 * For HT, Don't use a bit rate that is more
356 * lossy than the best. Give a bit of leeway.
357 *
358 * Don't consider best rates that we haven't seen
359 * packets for yet; let sampling start inflence that.
360 */
361 if (an->an_node.ni_flags & IEEE80211_NODE_HT) {
362 if (pct == -1)
363 continue;
364#if 0
365 IEEE80211_NOTE(an->an_node.ni_vap,
366 IEEE80211_MSG_RATECTL,
367 &an->an_node,
368 "%s: size %d comparing best rate 0x%x pkts/ewma/tt (%ju/%d/%d) "
369 "to 0x%x pkts/ewma/tt (%ju/%d/%d)",
370 __func__,
371 bin_to_size(size_bin),
372 rt->info[best_rate_rix].dot11Rate,
373 sn->stats[size_bin][best_rate_rix].total_packets,
374 best_rate_pct,
375 best_rate_tt,
376 rt->info[rix].dot11Rate,
377 sn->stats[size_bin][rix].total_packets,
378 pct,
379 tt);
380#endif
381 if (best_rate_pct > (pct + 50))
382 continue;
383 }
384 /*
385 * For non-MCS rates, use the current average txtime for
386 * comparison.
387 */
388 if (! (an->an_node.ni_flags & IEEE80211_NODE_HT)) {
389 if (best_rate_tt == 0 || tt <= best_rate_tt) {
390 best_rate_tt = tt;
391 best_rate_rix = rix;
392 best_rate_pct = pct;
393 }
394 }
395
396 /*
397 * Since 2 and 3 stream rates have slightly higher TX times,
398 * allow a little bit of leeway. This should later
399 * be abstracted out and properly handled.
400 */
401 if (an->an_node.ni_flags & IEEE80211_NODE_HT) {
402 if (best_rate_tt == 0 || ((tt * 10) <= (best_rate_tt * 10))) {
403 best_rate_tt = tt;
404 best_rate_rix = rix;
405 best_rate_pct = pct;
406 }
407 }
408 }
409 return (best_rate_tt ? best_rate_rix : -1);
410}
411
412/*
413 * Pick a good "random" bit-rate to sample other than the current one.
414 */
415static __inline int
416pick_sample_rate(struct sample_softc *ssc , struct ath_node *an,
417 const HAL_RATE_TABLE *rt, int size_bin)
418{
419#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
420#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
421 struct sample_node *sn = ATH_NODE_SAMPLE(an);
422 int current_rix, rix;
423 unsigned current_tt;
424 uint64_t mask;
425
426 current_rix = sn->current_rix[size_bin];
427 if (current_rix < 0) {
428 /* no successes yet, send at the lowest bit-rate */
429 /* XXX TODO should return MCS0 if HT */
430 return 0;
431 }
432
433 current_tt = sn->stats[size_bin][current_rix].average_tx_time;
434
435 rix = sn->last_sample_rix[size_bin]+1; /* next sample rate */
436 mask = sn->ratemask &~ ((uint64_t) 1<<current_rix);/* don't sample current rate */
437 while (mask != 0) {
438 if ((mask & ((uint64_t) 1<<rix)) == 0) { /* not a supported rate */
439 nextrate:
440 if (++rix >= rt->rateCount)
441 rix = 0;
442 continue;
443 }
444
445 /*
446 * The following code stops trying to sample
447 * non-MCS rates when speaking to an MCS node.
448 * However, at least for CCK rates in 2.4GHz mode,
449 * the non-MCS rates MAY actually provide better
450 * PER at the very far edge of reception.
451 *
452 * However! Until ath_rate_form_aggr() grows
453 * some logic to not form aggregates if the
454 * selected rate is non-MCS, this won't work.
455 *
456 * So don't disable this code until you've taught
457 * ath_rate_form_aggr() to drop out if any of
458 * the selected rates are non-MCS.
459 */
460#if 1
461 /* if the node is HT and the rate isn't HT, don't bother sample */
462 if ((an->an_node.ni_flags & IEEE80211_NODE_HT) &&
463 (rt->info[rix].phy != IEEE80211_T_HT)) {
464 mask &= ~((uint64_t) 1<<rix);
465 goto nextrate;
466 }
467#endif
468
469 /* this bit-rate is always worse than the current one */
470 if (sn->stats[size_bin][rix].perfect_tx_time > current_tt) {
471 mask &= ~((uint64_t) 1<<rix);
472 goto nextrate;
473 }
474
475 /* rarely sample bit-rates that fail a lot */
476 if (sn->stats[size_bin][rix].successive_failures > ssc->max_successive_failures &&
477 ticks - sn->stats[size_bin][rix].last_tx < ssc->stale_failure_timeout) {
478 mask &= ~((uint64_t) 1<<rix);
479 goto nextrate;
480 }
481
482 /*
483 * For HT, only sample a few rates on either side of the
484 * current rix; there's quite likely a lot of them.
485 *
486 * This is limited to testing rate indexes on either side of
487 * this MCS, but for all spatial streams.
488 *
489 * Otherwise we'll (a) never really sample higher MCS
490 * rates if we're stuck low, and we'll make weird moves
491 * like sample MCS8 if we're using MCS7.
492 */
493 if (an->an_node.ni_flags & IEEE80211_NODE_HT) {
494 uint8_t current_mcs, rix_mcs;
495
496 current_mcs = MCS(current_rix) & 0x7;
497 rix_mcs = MCS(rix) & 0x7;
498
499 if (rix_mcs < (current_mcs - 2) ||
500 rix_mcs > (current_mcs + 2)) {
501 mask &= ~((uint64_t) 1<<rix);
502 goto nextrate;
503 }
504 }
505
506 /* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */
507 if (! (an->an_node.ni_flags & IEEE80211_NODE_HT)) {
508 if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) {
509 mask &= ~((uint64_t) 1<<rix);
510 goto nextrate;
511 }
512 }
513
514 sn->last_sample_rix[size_bin] = rix;
515 return rix;
516 }
517 return current_rix;
518#undef DOT11RATE
519#undef MCS
520}
521
522static int
523ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni)
524{
525#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
526#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
527#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
528 const struct ieee80211_txparam *tp = ni->ni_txparms;
529 int srate;
530
531 /* Check MCS rates */
532 for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) {
533 if (MCS(srate) == tp->ucastrate)
534 return sc->sc_rixmap[tp->ucastrate];
535 }
536
537 /* Check legacy rates */
538 for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) {
539 if (RATE(srate) == tp->ucastrate)
540 return sc->sc_rixmap[tp->ucastrate];
541 }
542 return -1;
543#undef RATE
544#undef DOT11RATE
545#undef MCS
546}
547
548static void
549ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni)
550{
551 struct ath_node *an = ATH_NODE(ni);
552 const struct ieee80211_txparam *tp = ni->ni_txparms;
553 struct sample_node *sn = ATH_NODE_SAMPLE(an);
554
555 if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) {
556 /*
557 * A fixed rate is to be used; ucastrate is the IEEE code
558 * for this rate (sans basic bit). Check this against the
559 * negotiated rate set for the node. Note the fixed rate
560 * may not be available for various reasons so we only
561 * setup the static rate index if the lookup is successful.
562 */
564 } else {
565 sn->static_rix = -1;
566 }
567}
568
569/*
570 * Pick a non-HT rate to begin using.
571 */
572static int
574 int frameLen)
575{
576#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
577#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
578#define RATE(ix) (DOT11RATE(ix) / 2)
579 int rix = -1;
580 const HAL_RATE_TABLE *rt = sc->sc_currates;
581 struct sample_node *sn = ATH_NODE_SAMPLE(an);
582 const int size_bin = size_to_bin(frameLen);
583
584 /* no packet has been sent successfully yet */
585 for (rix = rt->rateCount-1; rix > 0; rix--) {
586 if ((sn->ratemask & ((uint64_t) 1<<rix)) == 0)
587 continue;
588
589 /* Skip HT rates */
590 if (rt->info[rix].phy == IEEE80211_T_HT)
591 continue;
592
593 /*
594 * Pick the highest rate <= 36 Mbps
595 * that hasn't failed.
596 */
597 if (DOT11RATE(rix) <= 72 &&
598 sn->stats[size_bin][rix].successive_failures == 0) {
599 break;
600 }
601 }
602 return rix;
603#undef RATE
604#undef MCS
605#undef DOT11RATE
606}
607
608/*
609 * Pick a HT rate to begin using.
610 *
611 * Don't use any non-HT rates; only consider HT rates.
612 */
613static int
615 int frameLen)
616{
617#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
618#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
619#define RATE(ix) (DOT11RATE(ix) / 2)
620 int rix = -1, ht_rix = -1;
621 const HAL_RATE_TABLE *rt = sc->sc_currates;
622 struct sample_node *sn = ATH_NODE_SAMPLE(an);
623 const int size_bin = size_to_bin(frameLen);
624
625 /* no packet has been sent successfully yet */
626 for (rix = rt->rateCount-1; rix > 0; rix--) {
627 /* Skip rates we can't use */
628 if ((sn->ratemask & ((uint64_t) 1<<rix)) == 0)
629 continue;
630
631 /* Keep a copy of the last seen HT rate index */
632 if (rt->info[rix].phy == IEEE80211_T_HT)
633 ht_rix = rix;
634
635 /* Skip non-HT rates */
636 if (rt->info[rix].phy != IEEE80211_T_HT)
637 continue;
638
639 /*
640 * Pick a medium-speed rate at 1 spatial stream
641 * which has not seen any failures.
642 * Higher rates may fail; we'll try them later.
643 */
644 if (((MCS(rix)& 0x7f) <= 4) &&
645 sn->stats[size_bin][rix].successive_failures == 0) {
646 break;
647 }
648 }
649
650 /*
651 * If all the MCS rates have successive failures, rix should be
652 * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.)
653 */
654 return MAX(rix, ht_rix);
655#undef RATE
656#undef MCS
657#undef DOT11RATE
658}
659
660void
661ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
662 int shortPreamble, size_t frameLen, int tid,
663 int is_aggr, u_int8_t *rix0, int *try0,
664 u_int8_t *txrate, int *maxdur, int *maxpktlen)
665{
666#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
667#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
668#define RATE(ix) (DOT11RATE(ix) / 2)
669 struct sample_node *sn = ATH_NODE_SAMPLE(an);
670 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
671 struct ieee80211com *ic = &sc->sc_ic;
672 const HAL_RATE_TABLE *rt = sc->sc_currates;
673 int size_bin = size_to_bin(frameLen);
674 int rix, mrr, best_rix, change_rates;
675 unsigned average_tx_time;
676 int max_pkt_len;
677
679
680 /* For now don't take TID, is_aggr into account */
681 /* Also for now don't calculate a max duration; that'll come later */
682 *maxdur = -1;
683
684 /*
685 * For now just set it to the frame length; we'll optimise it later.
686 */
687 *maxpktlen = frameLen;
688
689 if (sn->currates != sc->sc_currates) {
690 device_printf(sc->sc_dev, "%s: currates != sc_currates!\n",
691 __func__);
692 rix = 0;
693 *try0 = ATH_TXMAXTRY;
694 goto done;
695 }
696
697 if (sn->static_rix != -1) {
698 rix = sn->static_rix;
699 *try0 = ATH_TXMAXTRY;
700
701 /*
702 * Ensure we limit max packet length here too!
703 */
704 max_pkt_len = ath_rate_sample_find_min_pktlength(sc, an,
705 sn->static_rix,
706 is_aggr);
707 if (max_pkt_len > 0) {
708 *maxpktlen = frameLen = MIN(frameLen, max_pkt_len);
709 size_bin = size_to_bin(frameLen);
710 }
711 goto done;
712 }
713
714 mrr = sc->sc_mrretry;
715 /* XXX check HT protmode too */
716 /* XXX turn into a cap; 11n MACs support MRR+RTSCTS */
717 if (mrr && (ic->ic_flags & IEEE80211_F_USEPROT && !sc->sc_mrrprot))
718 mrr = 0;
719
720 best_rix = pick_best_rate(an, rt, size_bin, !mrr);
721
722 /*
723 * At this point we've chosen the best rix, so now we
724 * need to potentially update our maximum packet length
725 * and size_bin if we're doing 11n rates.
726 */
727 max_pkt_len = ath_rate_sample_find_min_pktlength(sc, an, best_rix,
728 is_aggr);
729 if (max_pkt_len > 0) {
730#if 0
731 device_printf(sc->sc_dev,
732 "Limiting maxpktlen from %d to %d bytes\n",
733 (int) frameLen, max_pkt_len);
734#endif
735 *maxpktlen = frameLen = MIN(frameLen, max_pkt_len);
736 size_bin = size_to_bin(frameLen);
737 }
738
739 if (best_rix >= 0) {
740 average_tx_time = sn->stats[size_bin][best_rix].average_tx_time;
741 } else {
742 average_tx_time = 0;
743 }
744
745 /*
746 * Limit the time measuring the performance of other tx
747 * rates to sample_rate% of the total transmission time.
748 */
749 if (sn->sample_tt[size_bin] <
750 average_tx_time *
751 (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) {
752 rix = pick_sample_rate(ssc, an, rt, size_bin);
753 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
754 &an->an_node, "att %d sample_tt %d size %u "
755 "sample rate %d %s current rate %d %s",
756 average_tx_time,
757 sn->sample_tt[size_bin],
758 bin_to_size(size_bin),
759 dot11rate(rt, rix),
760 dot11rate_label(rt, rix),
761 dot11rate(rt, sn->current_rix[size_bin]),
762 dot11rate_label(rt, sn->current_rix[size_bin]));
763 if (rix != sn->current_rix[size_bin]) {
764 sn->current_sample_rix[size_bin] = rix;
765 } else {
766 sn->current_sample_rix[size_bin] = -1;
767 }
768 sn->packets_since_sample[size_bin] = 0;
769 } else {
770 change_rates = 0;
771 if (!sn->packets_sent[size_bin] || best_rix == -1) {
772 /* no packet has been sent successfully yet */
773 change_rates = 1;
774 if (an->an_node.ni_flags & IEEE80211_NODE_HT)
775 best_rix =
776 ath_rate_pick_seed_rate_ht(sc, an, frameLen);
777 else
778 best_rix =
779 ath_rate_pick_seed_rate_legacy(sc, an, frameLen);
780 } else if (sn->packets_sent[size_bin] < 20) {
781 /* let the bit-rate switch quickly during the first few packets */
782 IEEE80211_NOTE(an->an_node.ni_vap,
783 IEEE80211_MSG_RATECTL, &an->an_node,
784 "%s: switching quickly..", __func__);
785 change_rates = 1;
786 } else if (ticks - ssc->min_switch > sn->ticks_since_switch[size_bin]) {
787 /* min_switch seconds have gone by */
788 IEEE80211_NOTE(an->an_node.ni_vap,
789 IEEE80211_MSG_RATECTL, &an->an_node,
790 "%s: min_switch %d > ticks_since_switch %d..",
791 __func__, ticks - ssc->min_switch, sn->ticks_since_switch[size_bin]);
792 change_rates = 1;
793 } else if ((! (an->an_node.ni_flags & IEEE80211_NODE_HT)) &&
794 (2*average_tx_time < sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time)) {
795 /* the current bit-rate is twice as slow as the best one */
796 IEEE80211_NOTE(an->an_node.ni_vap,
797 IEEE80211_MSG_RATECTL, &an->an_node,
798 "%s: 2x att (= %d) < cur_rix att %d",
799 __func__,
800 2 * average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time);
801 change_rates = 1;
802 } else if ((an->an_node.ni_flags & IEEE80211_NODE_HT)) {
803 int cur_rix = sn->current_rix[size_bin];
804 int cur_att = sn->stats[size_bin][cur_rix].average_tx_time;
805 /*
806 * If the node is HT, it if the rate isn't the
807 * same and the average tx time is within 10%
808 * of the current rate. It can fail a little.
809 *
810 * This is likely not optimal!
811 */
812#if 0
813 printf("cur rix/att %x/%d, best rix/att %x/%d\n",
814 MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time);
815#endif
816 if ((best_rix != cur_rix) &&
817 (average_tx_time * 9) <= (cur_att * 10)) {
818 IEEE80211_NOTE(an->an_node.ni_vap,
819 IEEE80211_MSG_RATECTL, &an->an_node,
820 "%s: HT: size %d best_rix 0x%x > "
821 " cur_rix 0x%x, average_tx_time %d,"
822 " cur_att %d",
823 __func__, bin_to_size(size_bin),
824 MCS(best_rix), MCS(cur_rix),
825 average_tx_time, cur_att);
826 change_rates = 1;
827 }
828 }
829
830 sn->packets_since_sample[size_bin]++;
831
832 if (change_rates) {
833 if (best_rix != sn->current_rix[size_bin]) {
834 IEEE80211_NOTE(an->an_node.ni_vap,
835 IEEE80211_MSG_RATECTL,
836 &an->an_node,
837"%s: size %d switch rate %d %s (%d/%d) EWMA %d -> %d %s (%d/%d) EWMA %d after %d packets mrr %d",
838 __func__,
839 bin_to_size(size_bin),
840 dot11rate(rt, sn->current_rix[size_bin]),
841 dot11rate_label(rt, sn->current_rix[size_bin]),
842 sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time,
843 sn->stats[size_bin][sn->current_rix[size_bin]].perfect_tx_time,
844 sn->stats[size_bin][sn->current_rix[size_bin]].ewma_pct,
845 dot11rate(rt, best_rix),
846 dot11rate_label(rt, best_rix),
847 sn->stats[size_bin][best_rix].average_tx_time,
848 sn->stats[size_bin][best_rix].perfect_tx_time,
849 sn->stats[size_bin][best_rix].ewma_pct,
850 sn->packets_since_switch[size_bin],
851 mrr);
852 }
853 sn->packets_since_switch[size_bin] = 0;
854 sn->current_rix[size_bin] = best_rix;
855 sn->ticks_since_switch[size_bin] = ticks;
856 /*
857 * Set the visible txrate for this node.
858 */
859 an->an_node.ni_txrate =
860 (rt->info[best_rix].phy == IEEE80211_T_HT) ?
861 MCS(best_rix) : DOT11RATE(best_rix);
862 }
863 rix = sn->current_rix[size_bin];
864 sn->packets_since_switch[size_bin]++;
865 }
866 *try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY;
867done:
868
869 /*
870 * This bug totally sucks and should be fixed.
871 *
872 * For now though, let's not panic, so we can start to figure
873 * out how to better reproduce it.
874 */
875 if (rix < 0 || rix >= rt->rateCount) {
876 printf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
877 __func__,
878 rix,
879 rt->rateCount);
880 rix = 0; /* XXX just default for now */
881 }
882 KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix));
883
884 *rix0 = rix;
885 *txrate = rt->info[rix].rateCode
886 | (shortPreamble ? rt->info[rix].shortPreamble : 0);
887 sn->packets_sent[size_bin]++;
888
889#undef DOT11RATE
890#undef MCS
891#undef RATE
892}
893
894/*
895 * Get the TX rates. Don't fiddle with short preamble flags for them;
896 * the caller can do that.
897 */
898void
900 uint8_t rix0, int is_aggr, struct ath_rc_series *rc)
901{
902 struct sample_node *sn = ATH_NODE_SAMPLE(an);
903 const struct txschedule *sched = &sn->sched[rix0];
904
905 KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n",
906 rix0, sched->r0));
907
908 rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0;
909
910 rc[0].rix = sched->r0;
911 rc[1].rix = sched->r1;
912 rc[2].rix = sched->r2;
913 rc[3].rix = sched->r3;
914
915 rc[0].tries = sched->t0;
916 rc[1].tries = sched->t1;
917
918 if (is_aggr) {
919 rc[2].tries = rc[3].tries = 0;
920 } else {
921 rc[2].tries = sched->t2;
922 rc[3].tries = sched->t3;
923 }
924}
925
926void
928 struct ath_desc *ds, int shortPreamble, u_int8_t rix)
929{
930 struct sample_node *sn = ATH_NODE_SAMPLE(an);
931 const struct txschedule *sched = &sn->sched[rix];
932 const HAL_RATE_TABLE *rt = sc->sc_currates;
933 uint8_t rix1, s1code, rix2, s2code, rix3, s3code;
934
935 /* XXX precalculate short preamble tables */
936 rix1 = sched->r1;
937 s1code = rt->info[rix1].rateCode
938 | (shortPreamble ? rt->info[rix1].shortPreamble : 0);
939 rix2 = sched->r2;
940 s2code = rt->info[rix2].rateCode
941 | (shortPreamble ? rt->info[rix2].shortPreamble : 0);
942 rix3 = sched->r3;
943 s3code = rt->info[rix3].rateCode
944 | (shortPreamble ? rt->info[rix3].shortPreamble : 0);
946 s1code, sched->t1, /* series 1 */
947 s2code, sched->t2, /* series 2 */
948 s3code, sched->t3); /* series 3 */
949}
950
951/*
952 * Update the current statistics.
953 *
954 * Note that status is for the FINAL transmit status, not this
955 * particular attempt. So, check if tries > tries0 and if so
956 * assume this status failed.
957 *
958 * This is important because some failures are due to both
959 * short AND long retries; if the final issue was a short
960 * retry failure then we still want to account for the
961 * bad long retry attempts.
962 */
963static void
964update_stats(struct ath_softc *sc, struct ath_node *an,
965 int frame_size,
966 int rix0, int tries0,
967 int short_tries, int tries, int status,
968 int nframes, int nbad)
969{
970 struct sample_node *sn = ATH_NODE_SAMPLE(an);
971 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
972#ifdef IEEE80211_DEBUG
973 const HAL_RATE_TABLE *rt = sc->sc_currates;
974#endif
975 const int size_bin = size_to_bin(frame_size);
976 const int size = bin_to_size(size_bin);
977 int tt;
978 int is_ht40 = (an->an_node.ni_chw == 40);
979 int pct;
980
981 if (!IS_RATE_DEFINED(sn, rix0))
982 return;
983
984 /*
985 * Treat long retries as us exceeding retries, even
986 * if the eventual attempt at some other MRR schedule
987 * succeeded.
988 */
989 if (tries > tries0) {
990 status = HAL_TXERR_XRETRY;
991 }
992
993 /*
994 * If status is FAIL then we treat all frames as bad.
995 * This better accurately tracks EWMA and average TX time
996 * because even if the eventual transmission succeeded,
997 * transmission at this rate did not.
998 */
999 if (status != 0)
1000 nbad = nframes;
1001
1002 /*
1003 * Ignore short tries count as contributing to failure.
1004 * Right now there's no way to know if it's part of any
1005 * given rate attempt, and outside of the RTS/CTS management
1006 * rate, it doesn't /really/ help.
1007 */
1008 tt = calc_usecs_unicast_packet(sc, size, rix0,
1009 0 /* short_tries */, MIN(tries0, tries) - 1, is_ht40);
1010
1011 if (sn->stats[size_bin][rix0].total_packets < ssc->smoothing_minpackets) {
1012 /* just average the first few packets */
1013 int avg_tx = sn->stats[size_bin][rix0].average_tx_time;
1014 int packets = sn->stats[size_bin][rix0].total_packets;
1015 sn->stats[size_bin][rix0].average_tx_time = (tt+(avg_tx*packets))/(packets+nframes);
1016 } else {
1017 /* use a ewma */
1018 sn->stats[size_bin][rix0].average_tx_time =
1019 ((sn->stats[size_bin][rix0].average_tx_time * ssc->smoothing_rate) +
1020 (tt * (100 - ssc->smoothing_rate))) / 100;
1021 }
1022
1023 if (nframes == nbad) {
1024 sn->stats[size_bin][rix0].successive_failures += nbad;
1025 } else {
1026 sn->stats[size_bin][rix0].packets_acked += (nframes - nbad);
1027 sn->stats[size_bin][rix0].successive_failures = 0;
1028 }
1029 sn->stats[size_bin][rix0].tries += tries;
1030 sn->stats[size_bin][rix0].last_tx = ticks;
1031 sn->stats[size_bin][rix0].total_packets += nframes;
1032
1033 /* update EWMA for this rix */
1034
1035 /* Calculate percentage based on current rate */
1036 if (nframes == 0)
1037 nframes = nbad = 1;
1038 pct = ((nframes - nbad) * 1000) / nframes;
1039
1040 if (sn->stats[size_bin][rix0].total_packets <
1041 ssc->smoothing_minpackets) {
1042 /* just average the first few packets */
1043 int a_pct = (sn->stats[size_bin][rix0].packets_acked * 1000) /
1044 (sn->stats[size_bin][rix0].total_packets);
1045 sn->stats[size_bin][rix0].ewma_pct = a_pct;
1046 } else {
1047 /* use a ewma */
1048 sn->stats[size_bin][rix0].ewma_pct =
1049 ((sn->stats[size_bin][rix0].ewma_pct * ssc->smoothing_rate) +
1050 (pct * (100 - ssc->smoothing_rate))) / 100;
1051 }
1052
1053 /*
1054 * Only update the sample time for the initial sample rix.
1055 * We've updated the statistics on each of the other retries
1056 * fine, but we should only update the sample_tt with what
1057 * was actually sampled.
1058 *
1059 * However, to aide in debugging, log all the failures for
1060 * each of the buckets
1061 */
1062 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
1063 &an->an_node,
1064 "%s: size %d %s %s rate %d %s tries (%d/%d) tt %d "
1065 "avg_tt (%d/%d) nfrm %d nbad %d",
1066 __func__,
1067 size,
1068 status ? "FAIL" : "OK",
1069 rix0 == sn->current_sample_rix[size_bin] ? "sample" : "mrr",
1070 dot11rate(rt, rix0),
1071 dot11rate_label(rt, rix0),
1072 short_tries, tries, tt,
1073 sn->stats[size_bin][rix0].average_tx_time,
1074 sn->stats[size_bin][rix0].perfect_tx_time,
1075 nframes, nbad);
1076
1077 if (rix0 == sn->current_sample_rix[size_bin]) {
1078 sn->sample_tt[size_bin] = tt;
1079 sn->current_sample_rix[size_bin] = -1;
1080 }
1081}
1082
1083static void
1084badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status)
1085{
1086
1087 device_printf(sc->sc_dev,
1088 "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
1089 series, hwrate, tries, status);
1090}
1091
1092void
1094 const struct ath_rc_series *rc, const struct ath_tx_status *ts,
1095 int frame_size, int rc_framesize, int nframes, int nbad)
1096{
1097 struct ieee80211com *ic = &sc->sc_ic;
1098 struct sample_node *sn = ATH_NODE_SAMPLE(an);
1099 int final_rix, short_tries, long_tries;
1100 const HAL_RATE_TABLE *rt = sc->sc_currates;
1101 int status = ts->ts_status;
1102 int mrr;
1103
1104 final_rix = rt->rateCodeToIndex[ts->ts_rate];
1105 short_tries = ts->ts_shortretry;
1106 long_tries = ts->ts_longretry + 1;
1107
1108 if (nframes == 0) {
1109 device_printf(sc->sc_dev, "%s: nframes=0?\n", __func__);
1110 return;
1111 }
1112
1113 if (frame_size == 0) /* NB: should not happen */
1114 frame_size = 1500;
1115 if (rc_framesize == 0) /* NB: should not happen */
1116 rc_framesize = 1500;
1117
1118 /*
1119 * There are still some places where what rate control set as
1120 * a limit but the hardware decided, for some reason, to transmit
1121 * at a smaller size that fell into a different bucket.
1122 *
1123 * The eternal question here is - which size_bin should it go in?
1124 * The one that was requested, or the one that was transmitted?
1125 *
1126 * Here's the problem - if we use the one that was transmitted,
1127 * we may continue to hit corner cases where we make a rate
1128 * selection using a higher bin but only update the smaller bin;
1129 * thus never really "adapting".
1130 *
1131 * If however we update the larger bin, we're not accurately
1132 * representing the channel state at that frame/aggregate size.
1133 * However if we keep hitting the larger request but completing
1134 * a smaller size, we at least updates based on what the
1135 * request was /for/.
1136 *
1137 * I'm going to err on the side of caution and choose the
1138 * latter.
1139 */
1140 if (size_to_bin(frame_size) != size_to_bin(rc_framesize)) {
1141#if 0
1142 device_printf(sc->sc_dev,
1143 "%s: completed but frame size buckets mismatch "
1144 "(completed %d tx'ed %d)\n",
1145 __func__, frame_size, rc_framesize);
1146#endif
1147 frame_size = rc_framesize;
1148 }
1149
1150 if (sn->ratemask == 0) {
1151 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
1152 &an->an_node,
1153 "%s: size %d %s rate/try %d/%d no rates yet",
1154 __func__,
1155 bin_to_size(size_to_bin(frame_size)),
1156 status ? "FAIL" : "OK",
1157 short_tries, long_tries);
1158 return;
1159 }
1160 mrr = sc->sc_mrretry;
1161 /* XXX check HT protmode too */
1162 if (mrr && (ic->ic_flags & IEEE80211_F_USEPROT && !sc->sc_mrrprot))
1163 mrr = 0;
1164
1165 if (!mrr || ts->ts_finaltsi == 0) {
1166 if (!IS_RATE_DEFINED(sn, final_rix)) {
1167 device_printf(sc->sc_dev,
1168 "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
1169 __func__, ts->ts_rate, ts->ts_finaltsi, final_rix);
1170 badrate(sc, 0, ts->ts_rate, long_tries, status);
1171 return;
1172 }
1173 /*
1174 * Only one rate was used; optimize work.
1175 */
1176 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
1177 &an->an_node, "%s: size %d (%d bytes) %s rate/short/long %d %s/%d/%d nframes/nbad [%d/%d]",
1178 __func__,
1179 bin_to_size(size_to_bin(frame_size)),
1180 frame_size,
1181 status ? "FAIL" : "OK",
1182 dot11rate(rt, final_rix), dot11rate_label(rt, final_rix),
1183 short_tries, long_tries, nframes, nbad);
1184 update_stats(sc, an, frame_size,
1185 final_rix, long_tries,
1186 short_tries, long_tries, status,
1187 nframes, nbad);
1188
1189 } else {
1190 int finalTSIdx = ts->ts_finaltsi;
1191 int i;
1192
1193 /*
1194 * Process intermediate rates that failed.
1195 */
1196
1197 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
1198 &an->an_node,
1199"%s: size %d (%d bytes) finaltsidx %d short %d long %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d] nframes/nbad [%d/%d]",
1200 __func__,
1201 bin_to_size(size_to_bin(frame_size)),
1202 frame_size,
1203 finalTSIdx,
1204 short_tries,
1205 long_tries,
1206 status ? "FAIL" : "OK",
1207 dot11rate(rt, rc[0].rix),
1208 dot11rate_label(rt, rc[0].rix), rc[0].tries,
1209 dot11rate(rt, rc[1].rix),
1210 dot11rate_label(rt, rc[1].rix), rc[1].tries,
1211 dot11rate(rt, rc[2].rix),
1212 dot11rate_label(rt, rc[2].rix), rc[2].tries,
1213 dot11rate(rt, rc[3].rix),
1214 dot11rate_label(rt, rc[3].rix), rc[3].tries,
1215 nframes, nbad);
1216
1217 for (i = 0; i < 4; i++) {
1218 if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix))
1219 badrate(sc, 0, rc[i].ratecode, rc[i].tries,
1220 status);
1221 }
1222
1223 /*
1224 * This used to not penalise other tries because loss
1225 * can be bursty, but it's then not accurately keeping
1226 * the avg TX time and EWMA updated.
1227 */
1228 if (rc[0].tries) {
1229 update_stats(sc, an, frame_size,
1230 rc[0].rix, rc[0].tries,
1231 short_tries, long_tries,
1232 status,
1233 nframes, nbad);
1234 long_tries -= rc[0].tries;
1235 }
1236
1237 if (rc[1].tries && finalTSIdx > 0) {
1238 update_stats(sc, an, frame_size,
1239 rc[1].rix, rc[1].tries,
1240 short_tries, long_tries,
1241 status,
1242 nframes, nbad);
1243 long_tries -= rc[1].tries;
1244 }
1245
1246 if (rc[2].tries && finalTSIdx > 1) {
1247 update_stats(sc, an, frame_size,
1248 rc[2].rix, rc[2].tries,
1249 short_tries, long_tries,
1250 status,
1251 nframes, nbad);
1252 long_tries -= rc[2].tries;
1253 }
1254
1255 if (rc[3].tries && finalTSIdx > 2) {
1256 update_stats(sc, an, frame_size,
1257 rc[3].rix, rc[3].tries,
1258 short_tries, long_tries,
1259 status,
1260 nframes, nbad);
1261 }
1262 }
1263}
1264
1265void
1266ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
1267{
1268 if (isnew)
1269 ath_rate_ctl_reset(sc, &an->an_node);
1270}
1271
1272void
1273ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
1274{
1275}
1276
1277static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = {
1278 NULL, /* IEEE80211_MODE_AUTO */
1279 series_11a, /* IEEE80211_MODE_11A */
1280 series_11g, /* IEEE80211_MODE_11B */
1281 series_11g, /* IEEE80211_MODE_11G */
1282 NULL, /* IEEE80211_MODE_FH */
1283 series_11a, /* IEEE80211_MODE_TURBO_A */
1284 series_11g, /* IEEE80211_MODE_TURBO_G */
1285 series_11a, /* IEEE80211_MODE_STURBO_A */
1286 series_11na, /* IEEE80211_MODE_11NA */
1287 series_11ng, /* IEEE80211_MODE_11NG */
1288 series_half, /* IEEE80211_MODE_HALF */
1289 series_quarter, /* IEEE80211_MODE_QUARTER */
1290};
1291
1292/*
1293 * Initialize the tables for a node.
1294 */
1295static void
1296ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
1297{
1298#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
1299#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
1300#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
1301 struct ath_node *an = ATH_NODE(ni);
1302 struct sample_node *sn = ATH_NODE_SAMPLE(an);
1303 const HAL_RATE_TABLE *rt = sc->sc_currates;
1304 int x, y, rix;
1305
1306 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
1307
1308 KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2,
1309 ("curmode %u", sc->sc_curmode));
1310
1311 sn->sched = mrr_schedules[sc->sc_curmode];
1312 KASSERT(sn->sched != NULL,
1313 ("no mrr schedule for mode %u", sc->sc_curmode));
1314
1315 sn->static_rix = -1;
1317
1318 sn->currates = sc->sc_currates;
1319
1320 /*
1321 * Construct a bitmask of usable rates. This has all
1322 * negotiated rates minus those marked by the hal as
1323 * to be ignored for doing rate control.
1324 */
1325 sn->ratemask = 0;
1326 /* MCS rates */
1327 if (ni->ni_flags & IEEE80211_NODE_HT) {
1328 for (x = 0; x < ni->ni_htrates.rs_nrates; x++) {
1329 rix = sc->sc_rixmap[MCS(x)];
1330 if (rix == 0xff)
1331 continue;
1332 /* skip rates marked broken by hal */
1333 if (!rt->info[rix].valid)
1334 continue;
1335 KASSERT(rix < SAMPLE_MAXRATES,
1336 ("mcs %u has rix %d", MCS(x), rix));
1337 sn->ratemask |= (uint64_t) 1<<rix;
1338 }
1339 }
1340
1341 /* Legacy rates */
1342 for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
1343 rix = sc->sc_rixmap[RATE(x)];
1344 if (rix == 0xff)
1345 continue;
1346 /* skip rates marked broken by hal */
1347 if (!rt->info[rix].valid)
1348 continue;
1349 KASSERT(rix < SAMPLE_MAXRATES,
1350 ("rate %u has rix %d", RATE(x), rix));
1351 sn->ratemask |= (uint64_t) 1<<rix;
1352 }
1353#ifdef IEEE80211_DEBUG
1354 if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) {
1355 uint64_t mask;
1356
1357 ieee80211_note(ni->ni_vap, "[%6D] %s: size 1600 rate/tt",
1358 ni->ni_macaddr, ":", __func__);
1359 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
1360 if ((mask & 1) == 0)
1361 continue;
1362 printf(" %d %s/%d", dot11rate(rt, rix), dot11rate_label(rt, rix),
1363 calc_usecs_unicast_packet(sc, 1600, rix, 0,0,
1364 (ni->ni_chw == 40)));
1365 }
1366 printf("\n");
1367 }
1368#endif
1369 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
1370 int size = bin_to_size(y);
1371 uint64_t mask;
1372
1373 sn->packets_sent[y] = 0;
1374 sn->current_sample_rix[y] = -1;
1375 sn->last_sample_rix[y] = 0;
1376 /* XXX start with first valid rate */
1377 sn->current_rix[y] = ffs(sn->ratemask)-1;
1378
1379 /*
1380 * Initialize the statistics buckets; these are
1381 * indexed by the rate code index.
1382 */
1383 for (rix = 0, mask = sn->ratemask; mask != 0; rix++, mask >>= 1) {
1384 if ((mask & 1) == 0) /* not a valid rate */
1385 continue;
1386 sn->stats[y][rix].successive_failures = 0;
1387 sn->stats[y][rix].tries = 0;
1388 sn->stats[y][rix].total_packets = 0;
1389 sn->stats[y][rix].packets_acked = 0;
1390 sn->stats[y][rix].last_tx = 0;
1391 sn->stats[y][rix].ewma_pct = 0;
1392
1393 sn->stats[y][rix].perfect_tx_time =
1394 calc_usecs_unicast_packet(sc, size, rix, 0, 0,
1395 (ni->ni_chw == 40));
1396 sn->stats[y][rix].average_tx_time =
1397 sn->stats[y][rix].perfect_tx_time;
1398 }
1399 }
1400#if 0
1401 /* XXX 0, num_rates-1 are wrong */
1402 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni,
1403 "%s: %d rates %d%sMbps (%dus)- %d%sMbps (%dus)", __func__,
1404 sn->num_rates,
1405 DOT11RATE(0)/2, DOT11RATE(0) % 1 ? ".5" : "",
1406 sn->stats[1][0].perfect_tx_time,
1407 DOT11RATE(sn->num_rates-1)/2, DOT11RATE(sn->num_rates-1) % 1 ? ".5" : "",
1408 sn->stats[1][sn->num_rates-1].perfect_tx_time
1409 );
1410#endif
1411 /* set the visible bit-rate */
1412 if (sn->static_rix != -1)
1413 ni->ni_txrate = DOT11RATE(sn->static_rix);
1414 else
1415 ni->ni_txrate = RATE(0);
1416#undef RATE
1417#undef DOT11RATE
1418}
1419
1420/*
1421 * Fetch the statistics for the given node.
1422 *
1423 * The ieee80211 node must be referenced and unlocked, however the ath_node
1424 * must be locked.
1425 *
1426 * The main difference here is that we convert the rate indexes
1427 * to 802.11 rates, or the userland output won't make much sense
1428 * as it has no access to the rix table.
1429 */
1430int
1432 struct ath_rateioctl *rs)
1433{
1434 struct sample_node *sn = ATH_NODE_SAMPLE(an);
1435 const HAL_RATE_TABLE *rt = sc->sc_currates;
1436 struct ath_rateioctl_tlv av;
1437 struct ath_rateioctl_rt *tv;
1438 int y;
1439 int o = 0;
1440
1442
1443 /*
1444 * Ensure there's enough space for the statistics.
1445 */
1446 if (rs->len <
1447 sizeof(struct ath_rateioctl_tlv) +
1448 sizeof(struct ath_rateioctl_rt) +
1449 sizeof(struct ath_rateioctl_tlv) +
1450 sizeof(struct sample_node)) {
1451 device_printf(sc->sc_dev, "%s: len=%d, too short\n",
1452 __func__,
1453 rs->len);
1454 return (EINVAL);
1455 }
1456
1457 /*
1458 * Take a temporary copy of the sample node state so we can
1459 * modify it before we copy it.
1460 */
1461 tv = malloc(sizeof(struct ath_rateioctl_rt), M_TEMP,
1462 M_NOWAIT | M_ZERO);
1463 if (tv == NULL) {
1464 return (ENOMEM);
1465 }
1466
1467 /*
1468 * Populate the rate table mapping TLV.
1469 */
1470 tv->nentries = rt->rateCount;
1471 for (y = 0; y < rt->rateCount; y++) {
1472 tv->ratecode[y] = rt->info[y].dot11Rate & IEEE80211_RATE_VAL;
1473 if (rt->info[y].phy == IEEE80211_T_HT)
1474 tv->ratecode[y] |= IEEE80211_RATE_MCS;
1475 }
1476
1477 o = 0;
1478 /*
1479 * First TLV - rate code mapping
1480 */
1482 av.tlv_len = sizeof(struct ath_rateioctl_rt);
1483 copyout(&av, rs->buf + o, sizeof(struct ath_rateioctl_tlv));
1484 o += sizeof(struct ath_rateioctl_tlv);
1485 copyout(tv, rs->buf + o, sizeof(struct ath_rateioctl_rt));
1486 o += sizeof(struct ath_rateioctl_rt);
1487
1488 /*
1489 * Second TLV - sample node statistics
1490 */
1492 av.tlv_len = sizeof(struct sample_node);
1493 copyout(&av, rs->buf + o, sizeof(struct ath_rateioctl_tlv));
1494 o += sizeof(struct ath_rateioctl_tlv);
1495
1496 /*
1497 * Copy the statistics over to the provided buffer.
1498 */
1499 copyout(sn, rs->buf + o, sizeof(struct sample_node));
1500 o += sizeof(struct sample_node);
1501
1502 free(tv, M_TEMP);
1503
1504 return (0);
1505}
1506
1507static void
1508sample_stats(void *arg, struct ieee80211_node *ni)
1509{
1510 struct ath_softc *sc = arg;
1511 const HAL_RATE_TABLE *rt = sc->sc_currates;
1512 struct sample_node *sn = ATH_NODE_SAMPLE(ATH_NODE(ni));
1513 uint64_t mask;
1514 int rix, y;
1515
1516 printf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
1517 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni),
1518 dot11rate(rt, sn->static_rix),
1519 dot11rate_label(rt, sn->static_rix),
1520 (uintmax_t)sn->ratemask);
1521 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
1522 printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
1523 bin_to_size(y), sn->current_rix[y],
1524 dot11rate(rt, sn->current_rix[y]),
1525 dot11rate_label(rt, sn->current_rix[y]),
1527 printf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
1528 bin_to_size(y),
1529 dot11rate(rt, sn->last_sample_rix[y]),
1530 dot11rate_label(rt, sn->last_sample_rix[y]),
1531 dot11rate(rt, sn->current_sample_rix[y]),
1533 sn->packets_sent[y]);
1534 printf("[%4u] packets since sample %d sample tt %u\n",
1536 sn->sample_tt[y]);
1537 }
1538 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) {
1539 if ((mask & 1) == 0)
1540 continue;
1541 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
1542 if (sn->stats[y][rix].total_packets == 0)
1543 continue;
1544 printf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
1545 dot11rate(rt, rix), dot11rate_label(rt, rix),
1546 bin_to_size(y),
1547 (uintmax_t) sn->stats[y][rix].total_packets,
1548 (uintmax_t) sn->stats[y][rix].packets_acked,
1549 (int) ((sn->stats[y][rix].packets_acked * 100ULL) /
1550 sn->stats[y][rix].total_packets),
1551 sn->stats[y][rix].ewma_pct / 10,
1552 sn->stats[y][rix].ewma_pct % 10,
1553 (uintmax_t) sn->stats[y][rix].tries,
1554 sn->stats[y][rix].successive_failures,
1555 sn->stats[y][rix].average_tx_time,
1556 ticks - sn->stats[y][rix].last_tx);
1557 }
1558 }
1559}
1560
1561static int
1562ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
1563{
1564 struct ath_softc *sc = arg1;
1565 struct ieee80211com *ic = &sc->sc_ic;
1566 int error, v;
1567
1568 v = 0;
1569 error = sysctl_handle_int(oidp, &v, 0, req);
1570 if (error || !req->newptr)
1571 return error;
1572 ieee80211_iterate_nodes(&ic->ic_sta, sample_stats, sc);
1573 return 0;
1574}
1575
1576static int
1578{
1579 struct sample_softc *ssc = arg1;
1580 int rate, error;
1581
1582 rate = ssc->smoothing_rate;
1583 error = sysctl_handle_int(oidp, &rate, 0, req);
1584 if (error || !req->newptr)
1585 return error;
1586 if (!(0 <= rate && rate < 100))
1587 return EINVAL;
1588 ssc->smoothing_rate = rate;
1589 ssc->smoothing_minpackets = 100 / (100 - rate);
1590 return 0;
1591}
1592
1593static int
1595{
1596 struct sample_softc *ssc = arg1;
1597 int rate, error;
1598
1599 rate = ssc->sample_rate;
1600 error = sysctl_handle_int(oidp, &rate, 0, req);
1601 if (error || !req->newptr)
1602 return error;
1603 if (!(2 <= rate && rate <= 100))
1604 return EINVAL;
1605 ssc->sample_rate = rate;
1606 return 0;
1607}
1608
1609static void
1611{
1612 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
1613 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
1614
1615 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1616 "smoothing_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1617 ssc, 0, ath_rate_sysctl_smoothing_rate, "I",
1618 "sample: smoothing rate for avg tx time (%%)");
1619 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1620 "sample_rate", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1621 ssc, 0, ath_rate_sysctl_sample_rate, "I",
1622 "sample: percent air time devoted to sampling new rates (%%)");
1623 /* XXX max_successive_failures, stale_failure_timeout, min_switch */
1624 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
1625 "sample_stats", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1626 sc, 0, ath_rate_sysctl_stats, "I", "sample: print statistics");
1627}
1628
1629struct ath_ratectrl *
1631{
1632 struct sample_softc *ssc;
1633
1634 ssc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
1635 if (ssc == NULL)
1636 return NULL;
1637 ssc->arc.arc_space = sizeof(struct sample_node);
1638 ssc->smoothing_rate = 75; /* ewma percentage ([0..99]) */
1639 ssc->smoothing_minpackets = 100 / (100 - ssc->smoothing_rate);
1640 ssc->sample_rate = 10; /* %time to try diff tx rates */
1641 ssc->max_successive_failures = 3; /* threshold for rate sampling*/
1642 ssc->stale_failure_timeout = 10 * hz; /* 10 seconds */
1643 ssc->min_switch = hz; /* 1 second */
1644 ath_rate_sysctlattach(sc, ssc);
1645 return &ssc->arc;
1646}
1647
1648void
1650{
1651 struct sample_softc *ssc = (struct sample_softc *) arc;
1652
1653 free(ssc, M_DEVBUF);
1654}
#define HAL_TXERR_XRETRY
Definition: ah_desc.h:63
#define ATH_RATE_TLV_RATETABLE
Definition: if_athioctl.h:230
#define ATH_RATE_TLV_SAMPLENODE
Definition: if_athioctl.h:236
#define ATH_TXMAXTRY
Definition: if_athvar.h:78
#define ath_hal_setupxtxdesc(_ah, _ds, _txr1, _txtr1, _txr2, _txtr2, _txr3, _txtr3)
Definition: if_athvar.h:1396
#define ATH_NODE(ni)
Definition: if_athvar.h:210
#define ATH_NODE_LOCK_ASSERT(_an)
Definition: if_athvar.h:416
static void sample_stats(void *arg, struct ieee80211_node *ni)
Definition: sample.c:1508
void ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
Definition: sample.c:284
static int ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
Definition: sample.c:1562
static __inline int pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin, int require_acked_before)
Definition: sample.c:316
void ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
Definition: sample.c:1266
int ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an, struct ath_rateioctl *rs)
Definition: sample.c:1431
#define MCS(ix)
static void ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *ssc)
Definition: sample.c:1610
#define RATE(_ix)
static void ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni)
Definition: sample.c:549
#define MCS_HT40_SGI
Definition: sample.c:115
void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, uint8_t rix0, int is_aggr, struct ath_rc_series *rc)
Definition: sample.c:899
static int ath_rate_pick_seed_rate_legacy(struct ath_softc *sc, struct ath_node *an, int frameLen)
Definition: sample.c:573
#define MCS_IDX(ix)
void ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi)
Definition: sample.c:1273
void ath_rate_detach(struct ath_ratectrl *arc)
Definition: sample.c:1649
struct ath_ratectrl * ath_rate_attach(struct ath_softc *sc)
Definition: sample.c:1630
static __inline int size_to_bin(int size)
Definition: sample.c:247
void ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, const struct ath_rc_series *rc, const struct ath_tx_status *ts, int frame_size, int rc_framesize, int nframes, int nbad)
Definition: sample.c:1093
static const char * dot11rate_label(const HAL_RATE_TABLE *rt, int rix)
Definition: sample.c:304
static void update_stats(struct ath_softc *sc, struct ath_node *an, int frame_size, int rix0, int tries0, int short_tries, int tries, int status, int nframes, int nbad)
Definition: sample.c:964
static __inline int pick_sample_rate(struct sample_softc *ssc, struct ath_node *an, const HAL_RATE_TABLE *rt, int size_bin)
Definition: sample.c:416
static int ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, int frameLen)
Definition: sample.c:614
__FBSDID("$FreeBSD$")
static int ath_rate_sysctl_sample_rate(SYSCTL_HANDLER_ARGS)
Definition: sample.c:1594
#define DOT11RATE(ix)
#define MCS_HT20_SGI
Definition: sample.c:113
#define MCS_HT20
Definition: sample.c:112
static int ath_rate_sample_max_4ms_framelen[4][32]
Definition: sample.c:135
static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *)
Definition: sample.c:1296
static int ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni)
Definition: sample.c:523
void ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, struct ath_desc *ds, int shortPreamble, u_int8_t rix)
Definition: sample.c:927
void ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
Definition: sample.c:290
static int dot11rate(const HAL_RATE_TABLE *rt, int rix)
Definition: sample.c:295
static const struct txschedule * mrr_schedules[IEEE80211_MODE_MAX+2]
Definition: sample.c:1277
static void badrate(struct ath_softc *sc, int series, int hwrate, int tries, int status)
Definition: sample.c:1084
static int ath_rate_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS)
Definition: sample.c:1577
static int ath_rate_sample_find_min_pktlength(struct ath_softc *sc, struct ath_node *an, uint8_t rix0, int is_aggr)
Definition: sample.c:175
#define MCS_HT40
Definition: sample.c:114
void ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, int tid, int is_aggr, u_int8_t *rix0, int *try0, u_int8_t *txrate, int *maxdur, int *maxpktlen)
Definition: sample.c:661
#define ATH_SOFTC_SAMPLE(sc)
Definition: sample.h:58
#define NUM_PACKET_SIZE_BINS
Definition: sample.h:81
#define MIN(a, b)
Definition: sample.h:120
#define IS_RATE_DEFINED(sn, rix)
Definition: sample.h:117
#define SAMPLE_MAXRATES
Definition: sample.h:94
static unsigned calc_usecs_unicast_packet(struct ath_softc *sc, int length, int rix, int short_retries, int long_retries, int is_ht40)
Definition: sample.h:132
#define ATH_NODE_SAMPLE(an)
Definition: sample.h:116
static const int packet_size_bins[NUM_PACKET_SIZE_BINS]
Definition: sample.h:83
static int bin_to_size(int index)
Definition: sample.h:86
#define MAX(a, b)
Definition: sample.h:123
int rateCount
Definition: ah.h:682
uint8_t rateCodeToIndex[256]
Definition: ah.h:683
uint8_t shortPreamble
Definition: ah.h:689
uint8_t rateCode
Definition: ah.h:688
struct HAL_RATE_TABLE::@3 info[64]
uint8_t valid
Definition: ah.h:685
uint8_t dot11Rate
Definition: ah.h:691
uint8_t phy
Definition: ah.h:686
struct ieee80211_node an_node
Definition: if_athvar.h:193
size_t arc_space
Definition: if_athrate.h:74
uint8_t ratecode[ATH_RATE_TLV_RATETABLE_NENTRIES]
Definition: if_athioctl.h:228
uint16_t nentries
Definition: if_athioctl.h:226
uint32_t len
Definition: if_athioctl.h:244
uint16_t flags
Definition: if_athrate.h:97
uint8_t tries
Definition: if_athrate.h:95
uint8_t rix
Definition: if_athrate.h:93
const HAL_RATE_TABLE * sc_currates
Definition: if_athvar.h:678
enum ieee80211_phymode sc_curmode
Definition: if_athvar.h:679
u_int8_t sc_rixmap[256]
Definition: if_athvar.h:685
device_t sc_dev
Definition: if_athvar.h:598
struct ath_hal * sc_ah
Definition: if_athvar.h:612
uint32_t sc_mrretry
Definition: if_athvar.h:621
struct ieee80211com sc_ic
Definition: if_athvar.h:562
uint32_t sc_mrrprot
Definition: if_athvar.h:622
uint8_t ts_status
Definition: ah_desc.h:38
uint8_t ts_finaltsi
Definition: ah_desc.h:45
uint8_t ts_longretry
Definition: ah_desc.h:42
uint8_t ts_rate
Definition: ah_desc.h:39
uint8_t ts_shortretry
Definition: ah_desc.h:41
unsigned average_tx_time
Definition: sample.h:61
uint64_t packets_acked
Definition: sample.h:65
int successive_failures
Definition: sample.h:62
uint64_t total_packets
Definition: sample.h:64
uint64_t tries
Definition: sample.h:63
int last_tx
Definition: sample.h:68
unsigned perfect_tx_time
Definition: sample.h:67
int ewma_pct
Definition: sample.h:66
int static_rix
Definition: sample.h:93
unsigned sample_tt[NUM_PACKET_SIZE_BINS]
Definition: sample.h:111
struct rate_stats stats[NUM_PACKET_SIZE_BINS][SAMPLE_MAXRATES]
Definition: sample.h:100
int current_rix[NUM_PACKET_SIZE_BINS]
Definition: sample.h:106
const HAL_RATE_TABLE * currates
Definition: sample.h:98
int ticks_since_switch[NUM_PACKET_SIZE_BINS]
Definition: sample.h:108
int current_sample_rix[NUM_PACKET_SIZE_BINS]
Definition: sample.h:103
int packets_since_sample[NUM_PACKET_SIZE_BINS]
Definition: sample.h:110
const struct txschedule * sched
Definition: sample.h:96
int last_sample_rix[NUM_PACKET_SIZE_BINS]
Definition: sample.h:101
int packets_sent[NUM_PACKET_SIZE_BINS]
Definition: sample.h:104
uint64_t ratemask
Definition: sample.h:95
int packets_since_switch[NUM_PACKET_SIZE_BINS]
Definition: sample.h:107
struct ath_ratectrl arc
Definition: sample.h:49
int smoothing_minpackets
Definition: sample.h:51
int min_switch
Definition: sample.h:55
int smoothing_rate
Definition: sample.h:50
int stale_failure_timeout
Definition: sample.h:54
int sample_rate
Definition: sample.h:52
int max_successive_failures
Definition: sample.h:53
uint8_t r3
Definition: sample.h:75
uint8_t r1
Definition: sample.h:73
uint8_t t3
Definition: sample.h:75
uint8_t t1
Definition: sample.h:73
uint8_t t2
Definition: sample.h:74
uint8_t t0
Definition: sample.h:72
uint8_t r2
Definition: sample.h:74
uint8_t r0
Definition: sample.h:72
static const struct txschedule series_11ng[]
Definition: tx_schedules.h:153
static const struct txschedule series_11na[]
Definition: tx_schedules.h:72
static const struct txschedule series_quarter[]
Definition: tx_schedules.h:229
static const struct txschedule series_half[]
Definition: tx_schedules.h:210
static const struct txschedule series_11a[]
Definition: tx_schedules.h:49
static const struct txschedule series_11g[]
Definition: tx_schedules.h:125