2 * Copyright (c) 2005 John Bicket
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 * 3. Neither the names of the above-listed copyright holders nor the names
16 * of any contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * Alternatively, this software may be distributed under the terms of the
20 * GNU General Public License ("GPL") version 2 as published by the Free
21 * Software Foundation.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGES.
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
42 * John Bicket's SampleRate control algorithm.
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/sysctl.h>
52 #include <sys/kernel.h>
54 #include <sys/malloc.h>
55 #include <sys/errno.h>
57 #if defined(__DragonFly__)
60 #include <machine/bus.h>
61 #include <machine/resource.h>
65 #include <sys/socket.h>
68 #include <net/if_var.h>
69 #include <net/if_media.h>
70 #include <net/if_arp.h>
71 #include <net/ethernet.h> /* XXX for ether_sprintf */
73 #include <netproto/802_11/ieee80211_var.h>
78 #include <netinet/in.h>
79 #include <netinet/if_ether.h>
82 #include <dev/netif/ath/ath/if_athvar.h>
83 #include <dev/netif/ath/ath_rate/sample/sample.h>
84 #include <dev/netif/ath/ath_hal/ah_desc.h>
85 #include <dev/netif/ath/ath_rate/sample/tx_schedules.h>
87 #if defined(__DragonFly__)
88 extern const char* ath_hal_ether_sprintf(const uint8_t *mac
);
92 * This file is an implementation of the SampleRate algorithm
93 * in "Bit-rate Selection in Wireless Networks"
94 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps)
96 * SampleRate chooses the bit-rate it predicts will provide the most
97 * throughput based on estimates of the expected per-packet
98 * transmission time for each bit-rate. SampleRate periodically sends
99 * packets at bit-rates other than the current one to estimate when
100 * another bit-rate will provide better performance. SampleRate
101 * switches to another bit-rate when its estimated per-packet
102 * transmission time becomes smaller than the current bit-rate's.
103 * SampleRate reduces the number of bit-rates it must sample by
104 * eliminating those that could not perform better than the one
105 * currently being used. SampleRate also stops probing at a bit-rate
106 * if it experiences several successive losses.
108 * The difference between the algorithm in the thesis and the one in this
109 * file is that the one in this file uses a ewma instead of a window.
111 * Also, this implementation tracks the average transmission time for
112 * a few different packet sizes independently for each link.
115 static void ath_rate_ctl_reset(struct ath_softc
*, struct ieee80211_node
*);
118 size_to_bin(int size
)
120 #if NUM_PACKET_SIZE_BINS > 1
121 if (size
<= packet_size_bins
[0])
124 #if NUM_PACKET_SIZE_BINS > 2
125 if (size
<= packet_size_bins
[1])
128 #if NUM_PACKET_SIZE_BINS > 3
129 if (size
<= packet_size_bins
[2])
132 #if NUM_PACKET_SIZE_BINS > 4
133 #error "add support for more packet sizes"
135 return NUM_PACKET_SIZE_BINS
-1;
139 ath_rate_node_init(struct ath_softc
*sc
, struct ath_node
*an
)
141 /* NB: assumed to be zero'd by caller */
145 ath_rate_node_cleanup(struct ath_softc
*sc
, struct ath_node
*an
)
150 dot11rate(const HAL_RATE_TABLE
*rt
, int rix
)
154 return rt
->info
[rix
].phy
== IEEE80211_T_HT
?
155 rt
->info
[rix
].dot11Rate
: (rt
->info
[rix
].dot11Rate
& IEEE80211_RATE_VAL
) / 2;
159 dot11rate_label(const HAL_RATE_TABLE
*rt
, int rix
)
163 return rt
->info
[rix
].phy
== IEEE80211_T_HT
? "MCS" : "Mb ";
167 * Return the rix with the lowest average_tx_time,
168 * or -1 if all the average_tx_times are 0.
171 pick_best_rate(struct ath_node
*an
, const HAL_RATE_TABLE
*rt
,
172 int size_bin
, int require_acked_before
)
174 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
175 int best_rate_rix
, best_rate_tt
, best_rate_pct
;
182 for (mask
= sn
->ratemask
, rix
= 0; mask
!= 0; mask
>>= 1, rix
++) {
183 if ((mask
& 1) == 0) /* not a supported rate */
186 /* Don't pick a non-HT rate for a HT node */
187 if ((an
->an_node
.ni_flags
& IEEE80211_NODE_HT
) &&
188 (rt
->info
[rix
].phy
!= IEEE80211_T_HT
)) {
192 tt
= sn
->stats
[size_bin
][rix
].average_tx_time
;
194 (require_acked_before
&&
195 !sn
->stats
[size_bin
][rix
].packets_acked
))
198 /* Calculate percentage if possible */
199 if (sn
->stats
[size_bin
][rix
].total_packets
> 0) {
200 pct
= sn
->stats
[size_bin
][rix
].ewma_pct
;
202 /* XXX for now, assume 95% ok */
206 /* don't use a bit-rate that has been failing */
207 if (sn
->stats
[size_bin
][rix
].successive_failures
> 3)
211 * For HT, Don't use a bit rate that is much more
212 * lossy than the best.
214 * XXX this isn't optimal; it's just designed to
215 * eliminate rates that are going to be obviously
218 if (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
) {
219 if (best_rate_pct
> (pct
+ 50))
224 * For non-MCS rates, use the current average txtime for
227 if (! (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
)) {
228 if (best_rate_tt
== 0 || tt
<= best_rate_tt
) {
236 * Since 2 stream rates have slightly higher TX times,
237 * allow a little bit of leeway. This should later
238 * be abstracted out and properly handled.
240 if (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
) {
241 if (best_rate_tt
== 0 || (tt
* 8 <= best_rate_tt
* 10)) {
248 return (best_rate_tt
? best_rate_rix
: -1);
252 * Pick a good "random" bit-rate to sample other than the current one.
255 pick_sample_rate(struct sample_softc
*ssc
, struct ath_node
*an
,
256 const HAL_RATE_TABLE
*rt
, int size_bin
)
258 #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
259 #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
260 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
261 int current_rix
, rix
;
265 current_rix
= sn
->current_rix
[size_bin
];
266 if (current_rix
< 0) {
267 /* no successes yet, send at the lowest bit-rate */
268 /* XXX should return MCS0 if HT */
272 current_tt
= sn
->stats
[size_bin
][current_rix
].average_tx_time
;
274 rix
= sn
->last_sample_rix
[size_bin
]+1; /* next sample rate */
275 mask
= sn
->ratemask
&~ ((uint64_t) 1<<current_rix
);/* don't sample current rate */
277 if ((mask
& ((uint64_t) 1<<rix
)) == 0) { /* not a supported rate */
279 if (++rix
>= rt
->rateCount
)
285 * The following code stops trying to sample
286 * non-MCS rates when speaking to an MCS node.
287 * However, at least for CCK rates in 2.4GHz mode,
288 * the non-MCS rates MAY actually provide better
289 * PER at the very far edge of reception.
291 * However! Until ath_rate_form_aggr() grows
292 * some logic to not form aggregates if the
293 * selected rate is non-MCS, this won't work.
295 * So don't disable this code until you've taught
296 * ath_rate_form_aggr() to drop out if any of
297 * the selected rates are non-MCS.
300 /* if the node is HT and the rate isn't HT, don't bother sample */
301 if ((an
->an_node
.ni_flags
& IEEE80211_NODE_HT
) &&
302 (rt
->info
[rix
].phy
!= IEEE80211_T_HT
)) {
303 mask
&= ~((uint64_t) 1<<rix
);
308 /* this bit-rate is always worse than the current one */
309 if (sn
->stats
[size_bin
][rix
].perfect_tx_time
> current_tt
) {
310 mask
&= ~((uint64_t) 1<<rix
);
314 /* rarely sample bit-rates that fail a lot */
315 if (sn
->stats
[size_bin
][rix
].successive_failures
> ssc
->max_successive_failures
&&
316 ticks
- sn
->stats
[size_bin
][rix
].last_tx
< ssc
->stale_failure_timeout
) {
317 mask
&= ~((uint64_t) 1<<rix
);
322 * For HT, only sample a few rates on either side of the
323 * current rix; there's quite likely a lot of them.
325 if (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
) {
326 if (rix
< (current_rix
- 3) ||
327 rix
> (current_rix
+ 3)) {
328 mask
&= ~((uint64_t) 1<<rix
);
333 /* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */
334 if (! (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
)) {
335 if (DOT11RATE(rix
) > 2*11 && rix
> current_rix
+ 2) {
336 mask
&= ~((uint64_t) 1<<rix
);
341 sn
->last_sample_rix
[size_bin
] = rix
;
350 ath_rate_get_static_rix(struct ath_softc
*sc
, const struct ieee80211_node
*ni
)
352 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
353 #define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
354 #define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
355 const struct ieee80211_txparam
*tp
= ni
->ni_txparms
;
358 /* Check MCS rates */
359 for (srate
= ni
->ni_htrates
.rs_nrates
- 1; srate
>= 0; srate
--) {
360 if (MCS(srate
) == tp
->ucastrate
)
361 return sc
->sc_rixmap
[tp
->ucastrate
];
364 /* Check legacy rates */
365 for (srate
= ni
->ni_rates
.rs_nrates
- 1; srate
>= 0; srate
--) {
366 if (RATE(srate
) == tp
->ucastrate
)
367 return sc
->sc_rixmap
[tp
->ucastrate
];
376 ath_rate_update_static_rix(struct ath_softc
*sc
, struct ieee80211_node
*ni
)
378 struct ath_node
*an
= ATH_NODE(ni
);
379 const struct ieee80211_txparam
*tp
= ni
->ni_txparms
;
380 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
382 if (tp
!= NULL
&& tp
->ucastrate
!= IEEE80211_FIXED_RATE_NONE
) {
384 * A fixed rate is to be used; ucastrate is the IEEE code
385 * for this rate (sans basic bit). Check this against the
386 * negotiated rate set for the node. Note the fixed rate
387 * may not be available for various reasons so we only
388 * setup the static rate index if the lookup is successful.
390 sn
->static_rix
= ath_rate_get_static_rix(sc
, ni
);
397 * Pick a non-HT rate to begin using.
400 ath_rate_pick_seed_rate_legacy(struct ath_softc
*sc
, struct ath_node
*an
,
403 #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
404 #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
405 #define RATE(ix) (DOT11RATE(ix) / 2)
407 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
408 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
409 const int size_bin
= size_to_bin(frameLen
);
411 /* no packet has been sent successfully yet */
412 for (rix
= rt
->rateCount
-1; rix
> 0; rix
--) {
413 if ((sn
->ratemask
& ((uint64_t) 1<<rix
)) == 0)
417 if (rt
->info
[rix
].phy
== IEEE80211_T_HT
)
421 * Pick the highest rate <= 36 Mbps
422 * that hasn't failed.
424 if (DOT11RATE(rix
) <= 72 &&
425 sn
->stats
[size_bin
][rix
].successive_failures
== 0) {
436 * Pick a HT rate to begin using.
438 * Don't use any non-HT rates; only consider HT rates.
441 ath_rate_pick_seed_rate_ht(struct ath_softc
*sc
, struct ath_node
*an
,
444 #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
445 #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
446 #define RATE(ix) (DOT11RATE(ix) / 2)
447 int rix
= -1, ht_rix
= -1;
448 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
449 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
450 const int size_bin
= size_to_bin(frameLen
);
452 /* no packet has been sent successfully yet */
453 for (rix
= rt
->rateCount
-1; rix
> 0; rix
--) {
454 /* Skip rates we can't use */
455 if ((sn
->ratemask
& ((uint64_t) 1<<rix
)) == 0)
458 /* Keep a copy of the last seen HT rate index */
459 if (rt
->info
[rix
].phy
== IEEE80211_T_HT
)
462 /* Skip non-HT rates */
463 if (rt
->info
[rix
].phy
!= IEEE80211_T_HT
)
467 * Pick a medium-speed rate regardless of stream count
468 * which has not seen any failures. Higher rates may fail;
469 * we'll try them later.
471 if (((MCS(rix
) & 0x7) <= 4) &&
472 sn
->stats
[size_bin
][rix
].successive_failures
== 0) {
478 * If all the MCS rates have successive failures, rix should be
479 * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.)
481 return MAX(rix
, ht_rix
);
489 ath_rate_findrate(struct ath_softc
*sc
, struct ath_node
*an
,
490 int shortPreamble
, size_t frameLen
,
491 u_int8_t
*rix0
, int *try0
, u_int8_t
*txrate
)
493 #define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
494 #define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
495 #define RATE(ix) (DOT11RATE(ix) / 2)
496 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
497 struct sample_softc
*ssc
= ATH_SOFTC_SAMPLE(sc
);
498 struct ieee80211com
*ic
= &sc
->sc_ic
;
499 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
500 const int size_bin
= size_to_bin(frameLen
);
501 int rix
, mrr
, best_rix
, change_rates
;
502 unsigned average_tx_time
;
504 ath_rate_update_static_rix(sc
, &an
->an_node
);
506 if (sn
->currates
!= sc
->sc_currates
) {
507 device_printf(sc
->sc_dev
, "%s: currates != sc_currates!\n",
510 *try0
= ATH_TXMAXTRY
;
514 if (sn
->static_rix
!= -1) {
515 rix
= sn
->static_rix
;
516 *try0
= ATH_TXMAXTRY
;
520 mrr
= sc
->sc_mrretry
;
521 /* XXX check HT protmode too */
522 if (mrr
&& (ic
->ic_flags
& IEEE80211_F_USEPROT
&& !sc
->sc_mrrprot
))
525 best_rix
= pick_best_rate(an
, rt
, size_bin
, !mrr
);
527 average_tx_time
= sn
->stats
[size_bin
][best_rix
].average_tx_time
;
532 * Limit the time measuring the performance of other tx
533 * rates to sample_rate% of the total transmission time.
535 if (sn
->sample_tt
[size_bin
] < average_tx_time
* (sn
->packets_since_sample
[size_bin
]*ssc
->sample_rate
/100)) {
536 rix
= pick_sample_rate(ssc
, an
, rt
, size_bin
);
537 IEEE80211_NOTE(an
->an_node
.ni_vap
, IEEE80211_MSG_RATECTL
,
538 &an
->an_node
, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s",
540 sn
->sample_tt
[size_bin
],
541 bin_to_size(size_bin
),
543 dot11rate_label(rt
, rix
),
544 dot11rate(rt
, sn
->current_rix
[size_bin
]),
545 dot11rate_label(rt
, sn
->current_rix
[size_bin
]));
546 if (rix
!= sn
->current_rix
[size_bin
]) {
547 sn
->current_sample_rix
[size_bin
] = rix
;
549 sn
->current_sample_rix
[size_bin
] = -1;
551 sn
->packets_since_sample
[size_bin
] = 0;
554 if (!sn
->packets_sent
[size_bin
] || best_rix
== -1) {
555 /* no packet has been sent successfully yet */
557 if (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
)
559 ath_rate_pick_seed_rate_ht(sc
, an
, frameLen
);
562 ath_rate_pick_seed_rate_legacy(sc
, an
, frameLen
);
563 } else if (sn
->packets_sent
[size_bin
] < 20) {
564 /* let the bit-rate switch quickly during the first few packets */
565 IEEE80211_NOTE(an
->an_node
.ni_vap
,
566 IEEE80211_MSG_RATECTL
, &an
->an_node
,
567 "%s: switching quickly..", __func__
);
569 } else if (ticks
- ssc
->min_switch
> sn
->ticks_since_switch
[size_bin
]) {
570 /* min_switch seconds have gone by */
571 IEEE80211_NOTE(an
->an_node
.ni_vap
,
572 IEEE80211_MSG_RATECTL
, &an
->an_node
,
573 "%s: min_switch %d > ticks_since_switch %d..",
574 __func__
, ticks
- ssc
->min_switch
, sn
->ticks_since_switch
[size_bin
]);
576 } else if ((! (an
->an_node
.ni_flags
& IEEE80211_NODE_HT
)) &&
577 (2*average_tx_time
< sn
->stats
[size_bin
][sn
->current_rix
[size_bin
]].average_tx_time
)) {
578 /* the current bit-rate is twice as slow as the best one */
579 IEEE80211_NOTE(an
->an_node
.ni_vap
,
580 IEEE80211_MSG_RATECTL
, &an
->an_node
,
581 "%s: 2x att (= %d) < cur_rix att %d",
583 2 * average_tx_time
, sn
->stats
[size_bin
][sn
->current_rix
[size_bin
]].average_tx_time
);
585 } else if ((an
->an_node
.ni_flags
& IEEE80211_NODE_HT
)) {
586 int cur_rix
= sn
->current_rix
[size_bin
];
587 int cur_att
= sn
->stats
[size_bin
][cur_rix
].average_tx_time
;
589 * If the node is HT, upgrade it if the MCS rate is
590 * higher and the average tx time is within 20% of
591 * the current rate. It can fail a little.
593 * This is likely not optimal!
596 kprintf("cur rix/att %x/%d, best rix/att %x/%d\n",
597 MCS(cur_rix
), cur_att
, MCS(best_rix
), average_tx_time
);
599 if ((MCS(best_rix
) > MCS(cur_rix
)) &&
600 (average_tx_time
* 8) <= (cur_att
* 10)) {
601 IEEE80211_NOTE(an
->an_node
.ni_vap
,
602 IEEE80211_MSG_RATECTL
, &an
->an_node
,
603 "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d",
605 MCS(best_rix
), MCS(cur_rix
), average_tx_time
, cur_att
);
610 sn
->packets_since_sample
[size_bin
]++;
613 if (best_rix
!= sn
->current_rix
[size_bin
]) {
614 IEEE80211_NOTE(an
->an_node
.ni_vap
,
615 IEEE80211_MSG_RATECTL
,
617 "%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d",
619 bin_to_size(size_bin
),
620 RATE(sn
->current_rix
[size_bin
]),
621 sn
->stats
[size_bin
][sn
->current_rix
[size_bin
]].average_tx_time
,
622 sn
->stats
[size_bin
][sn
->current_rix
[size_bin
]].perfect_tx_time
,
624 sn
->stats
[size_bin
][best_rix
].average_tx_time
,
625 sn
->stats
[size_bin
][best_rix
].perfect_tx_time
,
626 sn
->packets_since_switch
[size_bin
],
629 sn
->packets_since_switch
[size_bin
] = 0;
630 sn
->current_rix
[size_bin
] = best_rix
;
631 sn
->ticks_since_switch
[size_bin
] = ticks
;
633 * Set the visible txrate for this node.
635 an
->an_node
.ni_txrate
= (rt
->info
[best_rix
].phy
== IEEE80211_T_HT
) ? MCS(best_rix
) : DOT11RATE(best_rix
);
637 rix
= sn
->current_rix
[size_bin
];
638 sn
->packets_since_switch
[size_bin
]++;
640 *try0
= mrr
? sn
->sched
[rix
].t0
: ATH_TXMAXTRY
;
644 * This bug totally sucks and should be fixed.
646 * For now though, let's not panic, so we can start to figure
647 * out how to better reproduce it.
649 if (rix
< 0 || rix
>= rt
->rateCount
) {
650 kprintf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n",
654 rix
= 0; /* XXX just default for now */
656 KASSERT(rix
>= 0 && rix
< rt
->rateCount
, ("rix is %d", rix
));
659 *txrate
= rt
->info
[rix
].rateCode
660 | (shortPreamble
? rt
->info
[rix
].shortPreamble
: 0);
661 sn
->packets_sent
[size_bin
]++;
668 * Get the TX rates. Don't fiddle with short preamble flags for them;
669 * the caller can do that.
672 ath_rate_getxtxrates(struct ath_softc
*sc
, struct ath_node
*an
,
673 uint8_t rix0
, struct ath_rc_series
*rc
)
675 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
676 const struct txschedule
*sched
= &sn
->sched
[rix0
];
678 KASSERT(rix0
== sched
->r0
, ("rix0 (%x) != sched->r0 (%x)!\n",
681 rc
[0].flags
= rc
[1].flags
= rc
[2].flags
= rc
[3].flags
= 0;
683 rc
[0].rix
= sched
->r0
;
684 rc
[1].rix
= sched
->r1
;
685 rc
[2].rix
= sched
->r2
;
686 rc
[3].rix
= sched
->r3
;
688 rc
[0].tries
= sched
->t0
;
689 rc
[1].tries
= sched
->t1
;
690 rc
[2].tries
= sched
->t2
;
691 rc
[3].tries
= sched
->t3
;
695 ath_rate_setupxtxdesc(struct ath_softc
*sc
, struct ath_node
*an
,
696 struct ath_desc
*ds
, int shortPreamble
, u_int8_t rix
)
698 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
699 const struct txschedule
*sched
= &sn
->sched
[rix
];
700 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
701 uint8_t rix1
, s1code
, rix2
, s2code
, rix3
, s3code
;
703 /* XXX precalculate short preamble tables */
705 s1code
= rt
->info
[rix1
].rateCode
706 | (shortPreamble
? rt
->info
[rix1
].shortPreamble
: 0);
708 s2code
= rt
->info
[rix2
].rateCode
709 | (shortPreamble
? rt
->info
[rix2
].shortPreamble
: 0);
711 s3code
= rt
->info
[rix3
].rateCode
712 | (shortPreamble
? rt
->info
[rix3
].shortPreamble
: 0);
713 ath_hal_setupxtxdesc(sc
->sc_ah
, ds
,
714 s1code
, sched
->t1
, /* series 1 */
715 s2code
, sched
->t2
, /* series 2 */
716 s3code
, sched
->t3
); /* series 3 */
720 update_stats(struct ath_softc
*sc
, struct ath_node
*an
,
722 int rix0
, int tries0
,
723 int rix1
, int tries1
,
724 int rix2
, int tries2
,
725 int rix3
, int tries3
,
726 int short_tries
, int tries
, int status
,
727 int nframes
, int nbad
)
729 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
730 struct sample_softc
*ssc
= ATH_SOFTC_SAMPLE(sc
);
731 #ifdef IEEE80211_DEBUG
732 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
734 const int size_bin
= size_to_bin(frame_size
);
735 const int size
= bin_to_size(size_bin
);
736 int tt
, tries_so_far
;
737 int is_ht40
= (an
->an_node
.ni_chw
== 40);
740 if (!IS_RATE_DEFINED(sn
, rix0
))
742 tt
= calc_usecs_unicast_packet(sc
, size
, rix0
, short_tries
,
743 MIN(tries0
, tries
) - 1, is_ht40
);
744 tries_so_far
= tries0
;
746 if (tries1
&& tries_so_far
< tries
) {
747 if (!IS_RATE_DEFINED(sn
, rix1
))
749 tt
+= calc_usecs_unicast_packet(sc
, size
, rix1
, short_tries
,
750 MIN(tries1
+ tries_so_far
, tries
) - tries_so_far
- 1, is_ht40
);
751 tries_so_far
+= tries1
;
754 if (tries2
&& tries_so_far
< tries
) {
755 if (!IS_RATE_DEFINED(sn
, rix2
))
757 tt
+= calc_usecs_unicast_packet(sc
, size
, rix2
, short_tries
,
758 MIN(tries2
+ tries_so_far
, tries
) - tries_so_far
- 1, is_ht40
);
759 tries_so_far
+= tries2
;
762 if (tries3
&& tries_so_far
< tries
) {
763 if (!IS_RATE_DEFINED(sn
, rix3
))
765 tt
+= calc_usecs_unicast_packet(sc
, size
, rix3
, short_tries
,
766 MIN(tries3
+ tries_so_far
, tries
) - tries_so_far
- 1, is_ht40
);
769 if (sn
->stats
[size_bin
][rix0
].total_packets
< ssc
->smoothing_minpackets
) {
770 /* just average the first few packets */
771 int avg_tx
= sn
->stats
[size_bin
][rix0
].average_tx_time
;
772 int packets
= sn
->stats
[size_bin
][rix0
].total_packets
;
773 sn
->stats
[size_bin
][rix0
].average_tx_time
= (tt
+(avg_tx
*packets
))/(packets
+nframes
);
776 sn
->stats
[size_bin
][rix0
].average_tx_time
=
777 ((sn
->stats
[size_bin
][rix0
].average_tx_time
* ssc
->smoothing_rate
) +
778 (tt
* (100 - ssc
->smoothing_rate
))) / 100;
782 * XXX Don't mark the higher bit rates as also having failed; as this
783 * unfortunately stops those rates from being tasted when trying to
784 * TX. This happens with 11n aggregation.
786 if (nframes
== nbad
) {
790 sn
->stats
[size_bin
][rix0
].successive_failures
+= nbad
;
792 for (y
= size_bin
+1; y
< NUM_PACKET_SIZE_BINS
; y
++) {
794 * Also say larger packets failed since we
795 * assume if a small packet fails at a
796 * bit-rate then a larger one will also.
798 sn
->stats
[y
][rix0
].successive_failures
+= nbad
;
799 sn
->stats
[y
][rix0
].last_tx
= ticks
;
800 sn
->stats
[y
][rix0
].tries
+= tries
;
801 sn
->stats
[y
][rix0
].total_packets
+= nframes
;
805 sn
->stats
[size_bin
][rix0
].packets_acked
+= (nframes
- nbad
);
806 sn
->stats
[size_bin
][rix0
].successive_failures
= 0;
808 sn
->stats
[size_bin
][rix0
].tries
+= tries
;
809 sn
->stats
[size_bin
][rix0
].last_tx
= ticks
;
810 sn
->stats
[size_bin
][rix0
].total_packets
+= nframes
;
812 /* update EWMA for this rix */
814 /* Calculate percentage based on current rate */
817 pct
= ((nframes
- nbad
) * 1000) / nframes
;
819 if (sn
->stats
[size_bin
][rix0
].total_packets
<
820 ssc
->smoothing_minpackets
) {
821 /* just average the first few packets */
822 int a_pct
= (sn
->stats
[size_bin
][rix0
].packets_acked
* 1000) /
823 (sn
->stats
[size_bin
][rix0
].total_packets
);
824 sn
->stats
[size_bin
][rix0
].ewma_pct
= a_pct
;
827 sn
->stats
[size_bin
][rix0
].ewma_pct
=
828 ((sn
->stats
[size_bin
][rix0
].ewma_pct
* ssc
->smoothing_rate
) +
829 (pct
* (100 - ssc
->smoothing_rate
))) / 100;
833 if (rix0
== sn
->current_sample_rix
[size_bin
]) {
834 IEEE80211_NOTE(an
->an_node
.ni_vap
, IEEE80211_MSG_RATECTL
,
836 "%s: size %d %s sample rate %d %s tries (%d/%d) tt %d avg_tt (%d/%d) nfrm %d nbad %d",
839 status
? "FAIL" : "OK",
841 dot11rate_label(rt
, rix0
),
842 short_tries
, tries
, tt
,
843 sn
->stats
[size_bin
][rix0
].average_tx_time
,
844 sn
->stats
[size_bin
][rix0
].perfect_tx_time
,
846 sn
->sample_tt
[size_bin
] = tt
;
847 sn
->current_sample_rix
[size_bin
] = -1;
852 badrate(struct ath_softc
*sc
, int series
, int hwrate
, int tries
, int status
)
855 device_printf(sc
->sc_dev
,
856 "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n",
857 series
, hwrate
, tries
, status
);
861 ath_rate_tx_complete(struct ath_softc
*sc
, struct ath_node
*an
,
862 const struct ath_rc_series
*rc
, const struct ath_tx_status
*ts
,
863 int frame_size
, int nframes
, int nbad
)
865 struct ieee80211com
*ic
= &sc
->sc_ic
;
866 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
867 int final_rix
, short_tries
, long_tries
;
868 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
869 int status
= ts
->ts_status
;
872 final_rix
= rt
->rateCodeToIndex
[ts
->ts_rate
];
873 short_tries
= ts
->ts_shortretry
;
874 long_tries
= ts
->ts_longretry
+ 1;
877 device_printf(sc
->sc_dev
, "%s: nframes=0?\n", __func__
);
881 if (frame_size
== 0) /* NB: should not happen */
884 if (sn
->ratemask
== 0) {
885 IEEE80211_NOTE(an
->an_node
.ni_vap
, IEEE80211_MSG_RATECTL
,
887 "%s: size %d %s rate/try %d/%d no rates yet",
889 bin_to_size(size_to_bin(frame_size
)),
890 status
? "FAIL" : "OK",
891 short_tries
, long_tries
);
894 mrr
= sc
->sc_mrretry
;
895 /* XXX check HT protmode too */
896 if (mrr
&& (ic
->ic_flags
& IEEE80211_F_USEPROT
&& !sc
->sc_mrrprot
))
899 if (!mrr
|| ts
->ts_finaltsi
== 0) {
900 if (!IS_RATE_DEFINED(sn
, final_rix
)) {
901 device_printf(sc
->sc_dev
,
902 "%s: ts_rate=%d ts_finaltsi=%d, final_rix=%d\n",
903 __func__
, ts
->ts_rate
, ts
->ts_finaltsi
, final_rix
);
904 badrate(sc
, 0, ts
->ts_rate
, long_tries
, status
);
908 * Only one rate was used; optimize work.
910 IEEE80211_NOTE(an
->an_node
.ni_vap
, IEEE80211_MSG_RATECTL
,
911 &an
->an_node
, "%s: size %d (%d bytes) %s rate/short/long %d %s/%d/%d nframes/nbad [%d/%d]",
913 bin_to_size(size_to_bin(frame_size
)),
915 status
? "FAIL" : "OK",
916 dot11rate(rt
, final_rix
), dot11rate_label(rt
, final_rix
),
917 short_tries
, long_tries
, nframes
, nbad
);
918 update_stats(sc
, an
, frame_size
,
919 final_rix
, long_tries
,
923 short_tries
, long_tries
, status
,
927 int finalTSIdx
= ts
->ts_finaltsi
;
931 * Process intermediate rates that failed.
934 IEEE80211_NOTE(an
->an_node
.ni_vap
, IEEE80211_MSG_RATECTL
,
936 "%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]",
938 bin_to_size(size_to_bin(frame_size
)),
943 status
? "FAIL" : "OK",
944 dot11rate(rt
, rc
[0].rix
),
945 dot11rate_label(rt
, rc
[0].rix
), rc
[0].tries
,
946 dot11rate(rt
, rc
[1].rix
),
947 dot11rate_label(rt
, rc
[1].rix
), rc
[1].tries
,
948 dot11rate(rt
, rc
[2].rix
),
949 dot11rate_label(rt
, rc
[2].rix
), rc
[2].tries
,
950 dot11rate(rt
, rc
[3].rix
),
951 dot11rate_label(rt
, rc
[3].rix
), rc
[3].tries
,
954 for (i
= 0; i
< 4; i
++) {
955 if (rc
[i
].tries
&& !IS_RATE_DEFINED(sn
, rc
[i
].rix
))
956 badrate(sc
, 0, rc
[i
].ratecode
, rc
[i
].tries
,
961 * NB: series > 0 are not penalized for failure
962 * based on the try counts under the assumption
963 * that losses are often bursty and since we
964 * sample higher rates 1 try at a time doing so
965 * may unfairly penalize them.
968 update_stats(sc
, an
, frame_size
,
969 rc
[0].rix
, rc
[0].tries
,
970 rc
[1].rix
, rc
[1].tries
,
971 rc
[2].rix
, rc
[2].tries
,
972 rc
[3].rix
, rc
[3].tries
,
973 short_tries
, long_tries
,
974 long_tries
> rc
[0].tries
,
976 long_tries
-= rc
[0].tries
;
979 if (rc
[1].tries
&& finalTSIdx
> 0) {
980 update_stats(sc
, an
, frame_size
,
981 rc
[1].rix
, rc
[1].tries
,
982 rc
[2].rix
, rc
[2].tries
,
983 rc
[3].rix
, rc
[3].tries
,
985 short_tries
, long_tries
,
988 long_tries
-= rc
[1].tries
;
991 if (rc
[2].tries
&& finalTSIdx
> 1) {
992 update_stats(sc
, an
, frame_size
,
993 rc
[2].rix
, rc
[2].tries
,
994 rc
[3].rix
, rc
[3].tries
,
997 short_tries
, long_tries
,
1000 long_tries
-= rc
[2].tries
;
1003 if (rc
[3].tries
&& finalTSIdx
> 2) {
1004 update_stats(sc
, an
, frame_size
,
1005 rc
[3].rix
, rc
[3].tries
,
1009 short_tries
, long_tries
,
1017 ath_rate_newassoc(struct ath_softc
*sc
, struct ath_node
*an
, int isnew
)
1020 ath_rate_ctl_reset(sc
, &an
->an_node
);
1023 static const struct txschedule
*mrr_schedules
[IEEE80211_MODE_MAX
+2] = {
1024 NULL
, /* IEEE80211_MODE_AUTO */
1025 series_11a
, /* IEEE80211_MODE_11A */
1026 series_11g
, /* IEEE80211_MODE_11B */
1027 series_11g
, /* IEEE80211_MODE_11G */
1028 NULL
, /* IEEE80211_MODE_FH */
1029 series_11a
, /* IEEE80211_MODE_TURBO_A */
1030 series_11g
, /* IEEE80211_MODE_TURBO_G */
1031 series_11a
, /* IEEE80211_MODE_STURBO_A */
1032 series_11na
, /* IEEE80211_MODE_11NA */
1033 series_11ng
, /* IEEE80211_MODE_11NG */
1034 series_half
, /* IEEE80211_MODE_HALF */
1035 series_quarter
, /* IEEE80211_MODE_QUARTER */
1039 * Initialize the tables for a node.
1042 ath_rate_ctl_reset(struct ath_softc
*sc
, struct ieee80211_node
*ni
)
1044 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
1045 #define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL)
1046 #define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS)
1047 struct ath_node
*an
= ATH_NODE(ni
);
1048 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
1049 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
1052 KASSERT(rt
!= NULL
, ("no rate table, mode %u", sc
->sc_curmode
));
1054 KASSERT(sc
->sc_curmode
< IEEE80211_MODE_MAX
+2,
1055 ("curmode %u", sc
->sc_curmode
));
1057 sn
->sched
= mrr_schedules
[sc
->sc_curmode
];
1058 KASSERT(sn
->sched
!= NULL
,
1059 ("no mrr schedule for mode %u", sc
->sc_curmode
));
1061 sn
->static_rix
= -1;
1062 ath_rate_update_static_rix(sc
, ni
);
1064 sn
->currates
= sc
->sc_currates
;
1067 * Construct a bitmask of usable rates. This has all
1068 * negotiated rates minus those marked by the hal as
1069 * to be ignored for doing rate control.
1073 if (ni
->ni_flags
& IEEE80211_NODE_HT
) {
1074 for (x
= 0; x
< ni
->ni_htrates
.rs_nrates
; x
++) {
1075 rix
= sc
->sc_rixmap
[MCS(x
)];
1078 /* skip rates marked broken by hal */
1079 if (!rt
->info
[rix
].valid
)
1081 KASSERT(rix
< SAMPLE_MAXRATES
,
1082 ("mcs %u has rix %d", MCS(x
), rix
));
1083 sn
->ratemask
|= (uint64_t) 1<<rix
;
1088 for (x
= 0; x
< ni
->ni_rates
.rs_nrates
; x
++) {
1089 rix
= sc
->sc_rixmap
[RATE(x
)];
1092 /* skip rates marked broken by hal */
1093 if (!rt
->info
[rix
].valid
)
1095 KASSERT(rix
< SAMPLE_MAXRATES
,
1096 ("rate %u has rix %d", RATE(x
), rix
));
1097 sn
->ratemask
|= (uint64_t) 1<<rix
;
1099 #ifdef IEEE80211_DEBUG
1100 if (ieee80211_msg(ni
->ni_vap
, IEEE80211_MSG_RATECTL
)) {
1103 #if defined(__DragonFly__)
1104 ieee80211_note(ni
->ni_vap
, "[%s] %s: size 1600 rate/tt",
1105 ath_hal_ether_sprintf(ni
->ni_macaddr
), __func__
);
1107 ieee80211_note(ni
->ni_vap
, "[%6D] %s: size 1600 rate/tt",
1108 ni
->ni_macaddr
, ":", __func__
);
1110 for (mask
= sn
->ratemask
, rix
= 0; mask
!= 0; mask
>>= 1, rix
++) {
1111 if ((mask
& 1) == 0)
1113 kprintf(" %d %s/%d", dot11rate(rt
, rix
), dot11rate_label(rt
, rix
),
1114 calc_usecs_unicast_packet(sc
, 1600, rix
, 0,0,
1115 (ni
->ni_chw
== 40)));
1120 for (y
= 0; y
< NUM_PACKET_SIZE_BINS
; y
++) {
1121 int size
= bin_to_size(y
);
1124 sn
->packets_sent
[y
] = 0;
1125 sn
->current_sample_rix
[y
] = -1;
1126 sn
->last_sample_rix
[y
] = 0;
1127 /* XXX start with first valid rate */
1128 sn
->current_rix
[y
] = ffs(sn
->ratemask
)-1;
1131 * Initialize the statistics buckets; these are
1132 * indexed by the rate code index.
1134 for (rix
= 0, mask
= sn
->ratemask
; mask
!= 0; rix
++, mask
>>= 1) {
1135 if ((mask
& 1) == 0) /* not a valid rate */
1137 sn
->stats
[y
][rix
].successive_failures
= 0;
1138 sn
->stats
[y
][rix
].tries
= 0;
1139 sn
->stats
[y
][rix
].total_packets
= 0;
1140 sn
->stats
[y
][rix
].packets_acked
= 0;
1141 sn
->stats
[y
][rix
].last_tx
= 0;
1142 sn
->stats
[y
][rix
].ewma_pct
= 0;
1144 sn
->stats
[y
][rix
].perfect_tx_time
=
1145 calc_usecs_unicast_packet(sc
, size
, rix
, 0, 0,
1146 (ni
->ni_chw
== 40));
1147 sn
->stats
[y
][rix
].average_tx_time
=
1148 sn
->stats
[y
][rix
].perfect_tx_time
;
1152 /* XXX 0, num_rates-1 are wrong */
1153 IEEE80211_NOTE(ni
->ni_vap
, IEEE80211_MSG_RATECTL
, ni
,
1154 "%s: %d rates %d%sMbps (%dus)- %d%sMbps (%dus)", __func__
,
1156 DOT11RATE(0)/2, DOT11RATE(0) % 1 ? ".5" : "",
1157 sn
->stats
[1][0].perfect_tx_time
,
1158 DOT11RATE(sn
->num_rates
-1)/2, DOT11RATE(sn
->num_rates
-1) % 1 ? ".5" : "",
1159 sn
->stats
[1][sn
->num_rates
-1].perfect_tx_time
1162 /* set the visible bit-rate */
1163 if (sn
->static_rix
!= -1)
1164 ni
->ni_txrate
= DOT11RATE(sn
->static_rix
);
1166 ni
->ni_txrate
= RATE(0);
1172 * Fetch the statistics for the given node.
1174 * The ieee80211 node must be referenced and unlocked, however the ath_node
1177 * The main difference here is that we convert the rate indexes
1178 * to 802.11 rates, or the userland output won't make much sense
1179 * as it has no access to the rix table.
1182 ath_rate_fetch_node_stats(struct ath_softc
*sc
, struct ath_node
*an
,
1183 struct ath_rateioctl
*rs
)
1185 struct sample_node
*sn
= ATH_NODE_SAMPLE(an
);
1186 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
1187 struct ath_rateioctl_tlv av
;
1188 struct ath_rateioctl_rt
*tv
;
1192 ATH_NODE_LOCK_ASSERT(an
);
1195 * Ensure there's enough space for the statistics.
1198 sizeof(struct ath_rateioctl_tlv
) +
1199 sizeof(struct ath_rateioctl_rt
) +
1200 sizeof(struct ath_rateioctl_tlv
) +
1201 sizeof(struct sample_node
)) {
1202 device_printf(sc
->sc_dev
, "%s: len=%d, too short\n",
1209 * Take a temporary copy of the sample node state so we can
1210 * modify it before we copy it.
1212 #if defined(__DragonFly__)
1213 tv
= kmalloc(sizeof(struct ath_rateioctl_rt
), M_TEMP
,
1214 M_INTWAIT
| M_ZERO
);
1216 tv
= malloc(sizeof(struct ath_rateioctl_rt
), M_TEMP
,
1224 * Populate the rate table mapping TLV.
1226 tv
->nentries
= rt
->rateCount
;
1227 for (y
= 0; y
< rt
->rateCount
; y
++) {
1228 tv
->ratecode
[y
] = rt
->info
[y
].dot11Rate
& IEEE80211_RATE_VAL
;
1229 if (rt
->info
[y
].phy
== IEEE80211_T_HT
)
1230 tv
->ratecode
[y
] |= IEEE80211_RATE_MCS
;
1235 * First TLV - rate code mapping
1237 av
.tlv_id
= ATH_RATE_TLV_RATETABLE
;
1238 av
.tlv_len
= sizeof(struct ath_rateioctl_rt
);
1239 copyout(&av
, rs
->buf
+ o
, sizeof(struct ath_rateioctl_tlv
));
1240 o
+= sizeof(struct ath_rateioctl_tlv
);
1241 copyout(tv
, rs
->buf
+ o
, sizeof(struct ath_rateioctl_rt
));
1242 o
+= sizeof(struct ath_rateioctl_rt
);
1245 * Second TLV - sample node statistics
1247 av
.tlv_id
= ATH_RATE_TLV_SAMPLENODE
;
1248 av
.tlv_len
= sizeof(struct sample_node
);
1249 copyout(&av
, rs
->buf
+ o
, sizeof(struct ath_rateioctl_tlv
));
1250 o
+= sizeof(struct ath_rateioctl_tlv
);
1253 * Copy the statistics over to the provided buffer.
1255 copyout(sn
, rs
->buf
+ o
, sizeof(struct sample_node
));
1256 o
+= sizeof(struct sample_node
);
1264 sample_stats(void *arg
, struct ieee80211_node
*ni
)
1266 struct ath_softc
*sc
= arg
;
1267 const HAL_RATE_TABLE
*rt
= sc
->sc_currates
;
1268 struct sample_node
*sn
= ATH_NODE_SAMPLE(ATH_NODE(ni
));
1272 kprintf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%jx\n",
1273 ether_sprintf(ni
->ni_macaddr
), ieee80211_node_refcnt(ni
),
1274 dot11rate(rt
, sn
->static_rix
),
1275 dot11rate_label(rt
, sn
->static_rix
),
1276 (uintmax_t)sn
->ratemask
);
1277 for (y
= 0; y
< NUM_PACKET_SIZE_BINS
; y
++) {
1278 kprintf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n",
1279 bin_to_size(y
), sn
->current_rix
[y
],
1280 dot11rate(rt
, sn
->current_rix
[y
]),
1281 dot11rate_label(rt
, sn
->current_rix
[y
]),
1282 sn
->packets_since_switch
[y
], sn
->ticks_since_switch
[y
]);
1283 kprintf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n",
1285 dot11rate(rt
, sn
->last_sample_rix
[y
]),
1286 dot11rate_label(rt
, sn
->last_sample_rix
[y
]),
1287 dot11rate(rt
, sn
->current_sample_rix
[y
]),
1288 dot11rate_label(rt
, sn
->current_sample_rix
[y
]),
1289 sn
->packets_sent
[y
]);
1290 kprintf("[%4u] packets since sample %d sample tt %u\n",
1291 bin_to_size(y
), sn
->packets_since_sample
[y
],
1294 for (mask
= sn
->ratemask
, rix
= 0; mask
!= 0; mask
>>= 1, rix
++) {
1295 if ((mask
& 1) == 0)
1297 for (y
= 0; y
< NUM_PACKET_SIZE_BINS
; y
++) {
1298 if (sn
->stats
[y
][rix
].total_packets
== 0)
1300 kprintf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n",
1301 dot11rate(rt
, rix
), dot11rate_label(rt
, rix
),
1303 (uintmax_t) sn
->stats
[y
][rix
].total_packets
,
1304 (uintmax_t) sn
->stats
[y
][rix
].packets_acked
,
1305 (int) ((sn
->stats
[y
][rix
].packets_acked
* 100ULL) /
1306 sn
->stats
[y
][rix
].total_packets
),
1307 sn
->stats
[y
][rix
].ewma_pct
/ 10,
1308 sn
->stats
[y
][rix
].ewma_pct
% 10,
1309 (uintmax_t) sn
->stats
[y
][rix
].tries
,
1310 sn
->stats
[y
][rix
].successive_failures
,
1311 sn
->stats
[y
][rix
].average_tx_time
,
1312 ticks
- sn
->stats
[y
][rix
].last_tx
);
1318 ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS
)
1320 struct ath_softc
*sc
= arg1
;
1321 struct ieee80211com
*ic
= &sc
->sc_ic
;
1325 error
= sysctl_handle_int(oidp
, &v
, 0, req
);
1326 if (error
|| !req
->newptr
)
1328 ieee80211_iterate_nodes(&ic
->ic_sta
, sample_stats
, sc
);
1333 ath_rate_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS
)
1335 struct sample_softc
*ssc
= arg1
;
1338 rate
= ssc
->smoothing_rate
;
1339 error
= sysctl_handle_int(oidp
, &rate
, 0, req
);
1340 if (error
|| !req
->newptr
)
1342 if (!(0 <= rate
&& rate
< 100))
1344 ssc
->smoothing_rate
= rate
;
1345 ssc
->smoothing_minpackets
= 100 / (100 - rate
);
1350 ath_rate_sysctl_sample_rate(SYSCTL_HANDLER_ARGS
)
1352 struct sample_softc
*ssc
= arg1
;
1355 rate
= ssc
->sample_rate
;
1356 error
= sysctl_handle_int(oidp
, &rate
, 0, req
);
1357 if (error
|| !req
->newptr
)
1359 if (!(2 <= rate
&& rate
<= 100))
1361 ssc
->sample_rate
= rate
;
1366 ath_rate_sysctlattach(struct ath_softc
*sc
, struct sample_softc
*ssc
)
1368 struct sysctl_ctx_list
*ctx
= device_get_sysctl_ctx(sc
->sc_dev
);
1369 struct sysctl_oid
*tree
= device_get_sysctl_tree(sc
->sc_dev
);
1371 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(tree
), OID_AUTO
,
1372 "smoothing_rate", CTLTYPE_INT
| CTLFLAG_RW
, ssc
, 0,
1373 ath_rate_sysctl_smoothing_rate
, "I",
1374 "sample: smoothing rate for avg tx time (%%)");
1375 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(tree
), OID_AUTO
,
1376 "sample_rate", CTLTYPE_INT
| CTLFLAG_RW
, ssc
, 0,
1377 ath_rate_sysctl_sample_rate
, "I",
1378 "sample: percent air time devoted to sampling new rates (%%)");
1379 /* XXX max_successive_failures, stale_failure_timeout, min_switch */
1380 SYSCTL_ADD_PROC(ctx
, SYSCTL_CHILDREN(tree
), OID_AUTO
,
1381 "sample_stats", CTLTYPE_INT
| CTLFLAG_RW
, sc
, 0,
1382 ath_rate_sysctl_stats
, "I", "sample: print statistics");
1385 struct ath_ratectrl
*
1386 ath_rate_attach(struct ath_softc
*sc
)
1388 struct sample_softc
*ssc
;
1390 #if defined(__DragonFly__)
1391 ssc
= kmalloc(sizeof(struct sample_softc
), M_DEVBUF
, M_INTWAIT
|M_ZERO
);
1393 ssc
= malloc(sizeof(struct sample_softc
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
1397 ssc
->arc
.arc_space
= sizeof(struct sample_node
);
1398 ssc
->smoothing_rate
= 75; /* ewma percentage ([0..99]) */
1399 ssc
->smoothing_minpackets
= 100 / (100 - ssc
->smoothing_rate
);
1400 ssc
->sample_rate
= 10; /* %time to try diff tx rates */
1401 ssc
->max_successive_failures
= 3; /* threshold for rate sampling*/
1402 ssc
->stale_failure_timeout
= 10 * hz
; /* 10 seconds */
1403 ssc
->min_switch
= hz
; /* 1 second */
1404 ath_rate_sysctlattach(sc
, ssc
);
1409 ath_rate_detach(struct ath_ratectrl
*arc
)
1411 struct sample_softc
*ssc
= (struct sample_softc
*) arc
;
1413 kfree(ssc
, M_DEVBUF
);
1416 #if defined(__DragonFly__)
1422 sample_modevent(module_t mod
, int type
, void *unused
)
1426 wlan_serialize_enter();
1431 kprintf("ath_rate: <SampleRate bit-rate "
1432 "selection algorithm>\n");
1443 wlan_serialize_exit();
1448 static moduledata_t sample_mod
= {
1454 DECLARE_MODULE(ath_rate
, sample_mod
, SI_SUB_DRIVERS
, SI_ORDER_FIRST
);
1455 MODULE_VERSION(ath_rate
, 1);
1456 MODULE_DEPEND(ath_rate
, ath_hal
, 1, 1, 1);
1457 MODULE_DEPEND(ath_rate
, wlan
, 1, 1, 1);