athrate-sample.c revision 1.7 1 /* $NetBSD: athrate-sample.c,v 1.7 2006/02/05 06:03:26 xtraeme Exp $ */
2
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 #include <sys/cdefs.h>
40 #ifdef __FreeBSD__
41 __FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.9 2005/07/22 16:50:17 sam Exp $");
42 #endif
43 #ifdef __NetBSD__
44 __KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.7 2006/02/05 06:03:26 xtraeme Exp $");
45 #endif
46
47
48 /*
49 * John Bicket's SampleRate control algorithm.
50 */
51 #include "opt_inet.h"
52
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/sysctl.h>
56 #include <sys/kernel.h>
57 #include <sys/lock.h>
58 #include <sys/errno.h>
59 #include <sys/device.h>
60
61 #include <machine/bus.h>
62
63 #include <sys/socket.h>
64
65 #include <net/if.h>
66 #include <net/if_media.h>
67 #include <net/if_arp.h>
68 #include <net/if_ether.h> /* XXX for ether_sprintf */
69
70 #include <net80211/ieee80211_var.h>
71
72 #include <net/bpf.h>
73
74 #ifdef INET
75 #include <netinet/in.h>
76 #endif
77
78 #include <dev/ic/athvar.h>
79 #include <dev/ic/athrate-sample.h>
80 #include <contrib/dev/ic/athhal_desc.h>
81
82 #define SAMPLE_DEBUG
83 #ifdef SAMPLE_DEBUG
84 enum {
85 ATH_DEBUG_RATE = 0x00000010, /* rate control */
86 };
87 #define DPRINTF(sc, _fmt, ...) do { \
88 if (sc->sc_debug & ATH_DEBUG_RATE) \
89 printf(_fmt, __VA_ARGS__); \
90 } while (0)
91 #else
92 #define DPRINTF(sc, _fmt, ...)
93 #endif
94
95 /*
96 * This file is an implementation of the SampleRate algorithm
97 * in "Bit-rate Selection in Wireless Networks"
98 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps)
99 *
100 * SampleRate chooses the bit-rate it predicts will provide the most
101 * throughput based on estimates of the expected per-packet
102 * transmission time for each bit-rate. SampleRate periodically sends
103 * packets at bit-rates other than the current one to estimate when
104 * another bit-rate will provide better performance. SampleRate
105 * switches to another bit-rate when its estimated per-packet
106 * transmission time becomes smaller than the current bit-rate's.
107 * SampleRate reduces the number of bit-rates it must sample by
108 * eliminating those that could not perform better than the one
109 * currently being used. SampleRate also stops probing at a bit-rate
110 * if it experiences several successive losses.
111 *
112 * The difference between the algorithm in the thesis and the one in this
113 * file is that the one in this file uses a ewma instead of a window.
114 *
115 */
116
117 #define STALE_FAILURE_TIMEOUT_MS 10000
118
119 static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
120
121 static inline int size_to_bin(int size)
122 {
123 int x = 0;
124 for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) {
125 if (size <= packet_size_bins[x]) {
126 return x;
127 }
128 }
129 return NUM_PACKET_SIZE_BINS-1;
130 }
131 static inline int bin_to_size(int index) {
132 return packet_size_bins[index];
133 }
134
135 static inline int rate_to_ndx(struct sample_node *sn, int rate) {
136 int x = 0;
137 for (x = 0; x < sn->num_rates; x++) {
138 if (sn->rates[x].rate == rate) {
139 return x;
140 }
141 }
142 return -1;
143 }
144
145 /*
146 * Setup rate codes for management/control frames. We force
147 * all such frames to the lowest rate.
148 */
149 static void
150 ath_rate_setmgtrates(struct ath_softc *sc, struct ath_node *an)
151 {
152 const HAL_RATE_TABLE *rt = sc->sc_currates;
153
154 /* setup rates for management frames */
155 /* XXX management/control frames always go at lowest speed */
156 an->an_tx_mgtrate = rt->info[0].rateCode;
157 an->an_tx_mgtratesp = an->an_tx_mgtrate
158 | rt->info[0].shortPreamble;
159 }
160
161 void
162 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
163 {
164 DPRINTF(sc, "%s:\n", __func__);
165 /* NB: assumed to be zero'd by caller */
166 ath_rate_setmgtrates(sc, an);
167 }
168
169 void
170 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
171 {
172 DPRINTF(sc, "%s:\n", __func__);
173 }
174
175
176 /*
177 * returns the ndx with the lowest average_tx_time,
178 * or -1 if all the average_tx_times are 0.
179 */
180 static inline int best_rate_ndx(struct sample_node *sn, int size_bin,
181 int require_acked_before)
182 {
183 int x = 0;
184 int best_ndx = 0;
185 int best_rate_tt = 0;
186 for (x = 0; x < sn->num_rates; x++) {
187 int tt = sn->stats[size_bin][x].average_tx_time;
188 if (tt <= 0 || (require_acked_before &&
189 !sn->stats[size_bin][x].packets_acked)) {
190 continue;
191 }
192 if (!best_rate_tt || best_rate_tt > tt) {
193 best_rate_tt = tt;
194 best_ndx = x;
195 }
196 }
197 return (best_rate_tt) ? best_ndx : -1;
198 }
199
200 /*
201 * pick a ndx s.t. the perfect_tx_time
202 * is less than the best bit-rate's average_tx_time
203 * and the ndx has not had four successive failures.
204 */
205 static inline int pick_sample_ndx(struct sample_node *sn, int size_bin)
206 {
207 int x = 0;
208 int current_ndx = 0;
209 unsigned current_tt = 0;
210
211 current_ndx = sn->current_rate[size_bin];
212 if (current_ndx < 0) {
213 /* no successes yet, send at the lowest bit-rate */
214 return 0;
215 }
216
217 current_tt = sn->stats[size_bin][current_ndx].average_tx_time;
218
219 for (x = 0; x < sn->num_rates; x++) {
220 int ndx = (sn->last_sample_ndx[size_bin] + 1 + x) % sn->num_rates;
221 /*
222 * clear any stale stuff out.
223 */
224 if (ticks - sn->stats[size_bin][ndx].last_tx > ((hz * STALE_FAILURE_TIMEOUT_MS)/1000)) {
225 sn->stats[size_bin][ndx].average_tx_time = sn->stats[size_bin][ndx].perfect_tx_time;
226 sn->stats[size_bin][ndx].successive_failures = 0;
227 sn->stats[size_bin][ndx].tries = 0;
228 sn->stats[size_bin][ndx].total_packets = 0;
229 sn->stats[size_bin][ndx].packets_acked = 0;
230 }
231
232 if (ndx != current_ndx &&
233 sn->stats[size_bin][ndx].perfect_tx_time < current_tt &&
234 sn->stats[size_bin][ndx].successive_failures < 4) {
235 sn->last_sample_ndx[size_bin] = ndx;
236 return ndx;
237 }
238 }
239 return current_ndx;
240 }
241
242 void
243 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
244 int shortPreamble, size_t frameLen,
245 u_int8_t *rix, int *try0, u_int8_t *txrate)
246 {
247 struct sample_node *sn = ATH_NODE_SAMPLE(an);
248 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
249 struct ieee80211com *ic = &sc->sc_ic;
250 int ndx, size_bin, mrr, best_ndx;
251 unsigned average_tx_time;
252
253 mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT) &&
254 !(frameLen > ic->ic_rtsthreshold);
255 size_bin = size_to_bin(frameLen);
256 best_ndx = best_rate_ndx(sn, size_bin, !mrr);
257
258 if (best_ndx >= 0) {
259 average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time;
260 } else {
261 average_tx_time = 0;
262 }
263 if (sn->static_rate_ndx != -1) {
264 ndx = sn->static_rate_ndx;
265 *try0 = ATH_TXMAXTRY;
266 } else {
267 ndx = 0;
268 *try0 = mrr ? 2 : ATH_TXMAXTRY;
269
270 DPRINTF(sc, "%s: %s size %d mrr %d packets_sent %d best_ndx %d "
271 "sample tt %d packets since %d\n"
272 , __func__, ether_sprintf(an->an_node.ni_macaddr)
273 , packet_size_bins[size_bin]
274 , mrr
275 , sn->packets_sent[size_bin]
276 , best_ndx
277 , sn->sample_tt[size_bin]
278 , sn->packets_since_sample[size_bin]
279 );
280 if (!sn->packets_sent[size_bin]) {
281 /* no packets sent */
282 if (best_ndx == -1) {
283 ndx = sn->num_rates - 1;
284 if (sc->sc_curmode != IEEE80211_MODE_11B) {
285 for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--)
286 ;
287
288 }
289 } else {
290 ndx = best_ndx;
291 }
292 } else if (best_ndx == -1) {
293 /* no packet has succeeded yet */
294 if (mrr) {
295 /*
296 * no packet has succeeded, try the
297 * highest bitrate that hasn't failed
298 */
299 for (ndx = sn->num_rates-1; ndx >= 0; ndx--) {
300 if (sn->stats[size_bin][ndx].successive_failures == 0) {
301 break;
302 }
303 }
304 } else {
305 ndx = sn->num_rates - 1;
306 if (sc->sc_curmode != IEEE80211_MODE_11B) {
307 for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--)
308 ;
309
310 }
311 }
312 } else if (sn->sample_tt[size_bin] < (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100) * average_tx_time &&
313 sn->packets_since_sample[size_bin] > 15) {
314 /*
315 * we want to limit the time measuring the performance
316 * of other bit-rates to ath_sample_rate% of the
317 * total transmission time.
318 */
319 ndx = pick_sample_ndx(sn, size_bin);
320 if (ndx != sn->current_rate[size_bin]) {
321 DPRINTF(sc, "%s: %s size %d last sample tt %d sampling %d packets since %d\n",
322 __func__,
323 ether_sprintf(an->an_node.ni_macaddr),
324 packet_size_bins[size_bin],
325 sn->sample_tt[size_bin],
326 sn->rates[ndx].rate,
327 sn->packets_since_sample[size_bin]);
328 sn->current_sample_ndx[size_bin] = ndx;
329 } else {
330 sn->current_sample_ndx[size_bin] = -1;
331 }
332 sn->packets_since_sample[size_bin] = 0;
333
334 } else {
335 sn->packets_since_sample[size_bin]++;
336 /*
337 * don't switch bit-rates every packet. only
338 * switch during the first few packets we send
339 * or after 100 packets, or if the current
340 * bit-rate begins to perform twice as bad as
341 * another one.
342 */
343 if (sn->packets_sent[size_bin] < 20 ||
344 ticks - ((hz*2000)/1000) > sn->jiffies_since_switch[size_bin] ||
345 average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time ) {
346 if (sn->packets_sent[size_bin] > 20) {
347 DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mmr %d\n",
348 __func__,
349 ether_sprintf(an->an_node.ni_macaddr),
350 packet_size_bins[size_bin],
351 sn->rates[sn->current_rate[size_bin]].rate,
352 sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
353 sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
354 sn->rates[best_ndx].rate,
355 sn->stats[size_bin][best_ndx].average_tx_time,
356 sn->stats[size_bin][best_ndx].perfect_tx_time,
357 sn->packets_since_switch[size_bin],
358 mrr);
359 }
360 sn->packets_since_switch[size_bin] = 0;
361 sn->current_rate[size_bin] = best_ndx;
362 sn->jiffies_since_switch[size_bin] = ticks;
363 }
364 ndx = sn->current_rate[size_bin];
365 sn->packets_since_switch[size_bin]++;
366 }
367
368 }
369
370 if (ndx < 0) {
371 ndx = 0;
372 }
373 *rix = sn->rates[ndx].rix;
374 if (shortPreamble) {
375 *txrate = sn->rates[ndx].shortPreambleRateCode;
376 } else {
377 *txrate = sn->rates[ndx].rateCode;
378 }
379 sn->packets_sent[size_bin]++;
380 an->an_node.ni_txrate = ndx;
381 }
382
383 void
384 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
385 struct ath_desc *ds, int shortPreamble, u_int8_t rix)
386 {
387 struct sample_node *sn = ATH_NODE_SAMPLE(an);
388 int rateCode = -1;
389 int frame_size, size_bin, best_ndx, ndx;
390
391 frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
392 KASSERT(frame_size != 0, ("no frame size"));
393 size_bin = size_to_bin(frame_size);
394 best_ndx = best_rate_ndx(sn, size_bin, 0);
395
396 if (best_ndx == -1 || !sn->stats[size_bin][best_ndx].packets_acked) {
397 /*
398 * no packet has succeeded, so also try at the
399 * lowest bitate.
400 */
401 ndx = 0;
402 } else {
403 /*
404 * we're trying a different bit-rate, and it could be lossy,
405 * so if it fails try at the best bit-rate.
406 */
407 ndx = best_ndx;
408 }
409 KASSERT(0 <= ndx && ndx < IEEE80211_RATE_MAXSIZE,
410 ("invalid ndx %d", ndx));
411 if (shortPreamble) {
412 rateCode = sn->rates[ndx].shortPreambleRateCode;
413 } else {
414 rateCode = sn->rates[ndx].rateCode;
415 }
416 ath_hal_setupxtxdesc(sc->sc_ah, ds
417 , rateCode, 3 /* series 1 */
418 , sn->rates[0].rateCode, 3 /* series 2 */
419 , 0, 0 /* series 3 */
420 );
421 }
422
423 static void
424 update_stats(struct ath_softc *sc, struct ath_node *an,
425 int frame_size,
426 int ndx0, int tries0,
427 int ndx1, int tries1,
428 int ndx2, int tries2,
429 int ndx3, int tries3,
430 int short_tries, int tries, int status)
431 {
432 struct sample_node *sn = ATH_NODE_SAMPLE(an);
433 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
434 int tt = 0;
435 int tries_so_far = 0;
436 int size_bin = 0;
437 int size = 0;
438 int rate = 0;
439
440 size_bin = size_to_bin(frame_size);
441 size = bin_to_size(size_bin);
442 rate = sn->rates[ndx0].rate;
443
444 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix,
445 short_tries-1,
446 MIN(tries0, tries) - 1);
447 tries_so_far += tries0;
448 if (tries1 && tries0 < tries) {
449 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix,
450 short_tries-1,
451 MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
452 }
453 tries_so_far += tries1;
454
455 if (tries2 && tries0 + tries1 < tries) {
456 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix,
457 short_tries-1,
458 MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
459 }
460
461 tries_so_far += tries2;
462
463 if (tries3 && tries0 + tries1 + tries2 < tries) {
464 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix,
465 short_tries-1,
466 MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
467 }
468 #ifdef SAMPLE_DEBUG
469 if (short_tries + tries > 3 || status) {
470 DPRINTF(sc, "%s: %s size %d rate %d ndx %d tries (%d/%d) tries0 %d tt %d avg_tt %d perfect_tt %d status %d\n",
471 __func__, ether_sprintf(an->an_node.ni_macaddr),
472 size,
473 rate, ndx0, short_tries, tries, tries0, tt,
474 sn->stats[size_bin][ndx0].average_tx_time,
475 sn->stats[size_bin][ndx0].perfect_tx_time,
476 status);
477 }
478 #endif /* SAMPLE_DEBUG */
479 if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
480 /* just average the first few packets */
481 int avg_tx = sn->stats[size_bin][ndx0].average_tx_time;
482 int packets = sn->stats[size_bin][ndx0].total_packets;
483 sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1);
484 } else {
485 /* use a ewma */
486 sn->stats[size_bin][ndx0].average_tx_time =
487 ((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) +
488 (tt * (100 - ssc->ath_smoothing_rate))) / 100;
489 }
490
491 if (status) {
492 /*
493 * this packet failed - count this as a failure
494 * for larger packets also, since we assume
495 * if a small packet fails at a lower bit-rate
496 * then a larger one will also.
497 */
498 int y;
499 for (y = size_bin; y < NUM_PACKET_SIZE_BINS; y++) {
500 sn->stats[y][ndx0].successive_failures++;
501 sn->stats[y][ndx0].last_tx = ticks;
502 }
503 } else {
504 sn->stats[size_bin][ndx0].packets_acked++;
505 sn->stats[size_bin][ndx0].successive_failures = 0;
506 }
507 sn->stats[size_bin][ndx0].tries += tries;
508 sn->stats[size_bin][ndx0].last_tx = ticks;
509 sn->stats[size_bin][ndx0].total_packets++;
510
511
512 if (ndx0 == sn->current_sample_ndx[size_bin]) {
513 DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n",
514 __func__, ether_sprintf(an->an_node.ni_macaddr),
515 size, rate, short_tries, tries, tt,
516 sn->stats[size_bin][ndx0].average_tx_time,
517 sn->stats[size_bin][ndx0].perfect_tx_time,
518 status);
519 sn->sample_tt[size_bin] = tt;
520 sn->current_sample_ndx[size_bin] = -1;
521 }
522 }
523
524 void
525 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
526 const struct ath_desc *ds, const struct ath_desc *ds0)
527 {
528 struct sample_node *sn = ATH_NODE_SAMPLE(an);
529 const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
530 int final_rate, short_tries, long_tries, frame_size;
531 int ndx = -1;
532
533 final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
534 short_tries = ds->ds_txstat.ts_shortretry + 1;
535 long_tries = ds->ds_txstat.ts_longretry + 1;
536 frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
537 if (frame_size == 0) /* NB: should not happen */
538 frame_size = 1500;
539
540 if (sn->num_rates <= 0) {
541 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
542 "no rates yet\n",
543 __func__, ether_sprintf(an->an_node.ni_macaddr),
544 bin_to_size(size_to_bin(frame_size)),
545 ds->ds_txstat.ts_status,
546 short_tries, long_tries);
547 return;
548 }
549
550 if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
551 /* this packet failed */
552 DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n",
553 __func__,
554 ether_sprintf(an->an_node.ni_macaddr),
555 bin_to_size(size_to_bin(frame_size)),
556 sc->sc_hwmap[ads->xmit_rate0].ieeerate,
557 ads->xmit_tries0,
558 sc->sc_hwmap[ads->xmit_rate1].ieeerate,
559 ads->xmit_tries1,
560 sc->sc_hwmap[ads->xmit_rate2].ieeerate,
561 ads->xmit_tries2,
562 sc->sc_hwmap[ads->xmit_rate3].ieeerate,
563 ads->xmit_tries3,
564 ds->ds_txstat.ts_status ? "FAIL" : "OK",
565 short_tries,
566 long_tries);
567 }
568
569 if (!(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
570 /* only one rate was used */
571 ndx = rate_to_ndx(sn, final_rate);
572 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n",
573 __func__, ether_sprintf(an->an_node.ni_macaddr),
574 bin_to_size(size_to_bin(frame_size)),
575 ds->ds_txstat.ts_status,
576 ndx, short_tries, long_tries);
577 if (ndx >= 0 && ndx < sn->num_rates) {
578 update_stats(sc, an, frame_size,
579 ndx, long_tries,
580 0, 0,
581 0, 0,
582 0, 0,
583 short_tries, long_tries, ds->ds_txstat.ts_status);
584 }
585 } else {
586 int rate0, tries0, ndx0;
587 int rate1, tries1, ndx1;
588 int rate2, tries2, ndx2;
589 int rate3, tries3, ndx3;
590 int finalTSIdx = ads->final_ts_index;
591
592 /*
593 * Process intermediate rates that failed.
594 */
595
596 rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
597 tries0 = ads->xmit_tries0;
598 ndx0 = rate_to_ndx(sn, rate0);
599
600 rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
601 tries1 = ads->xmit_tries1;
602 ndx1 = rate_to_ndx(sn, rate1);
603
604 rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
605 tries2 = ads->xmit_tries2;
606 ndx2 = rate_to_ndx(sn, rate2);
607
608 rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
609 tries3 = ads->xmit_tries3;
610 ndx3 = rate_to_ndx(sn, rate3);
611
612 #if 1
613 DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n",
614 __func__, ether_sprintf(an->an_node.ni_macaddr),
615 bin_to_size(size_to_bin(frame_size)),
616 finalTSIdx,
617 long_tries,
618 ds->ds_txstat.ts_status,
619 rate0, tries0,
620 rate1, tries1,
621 rate2, tries2,
622 rate3, tries3);
623 #endif
624
625 if (tries0) {
626 update_stats(sc, an, frame_size,
627 ndx0, tries0,
628 ndx1, tries1,
629 ndx2, tries2,
630 ndx3, tries3,
631 short_tries, ds->ds_txstat.ts_longretry + 1,
632 ds->ds_txstat.ts_status);
633 }
634
635 if (tries1 && finalTSIdx > 0) {
636 update_stats(sc, an, frame_size,
637 ndx1, tries1,
638 ndx2, tries2,
639 ndx3, tries3,
640 0, 0,
641 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0,
642 ds->ds_txstat.ts_status);
643 }
644
645 if (tries2 && finalTSIdx > 1) {
646 update_stats(sc, an, frame_size,
647 ndx2, tries2,
648 ndx3, tries3,
649 0, 0,
650 0, 0,
651 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1,
652 ds->ds_txstat.ts_status);
653 }
654
655 if (tries3 && finalTSIdx > 2) {
656 update_stats(sc, an, frame_size,
657 ndx3, tries3,
658 0, 0,
659 0, 0,
660 0, 0,
661 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2,
662 ds->ds_txstat.ts_status);
663 }
664 }
665 }
666
667 void
668 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
669 {
670 DPRINTF(sc, "%s: %s isnew %d\n", __func__,
671 ether_sprintf(an->an_node.ni_macaddr), isnew);
672 if (isnew)
673 ath_rate_ctl_reset(sc, &an->an_node);
674 }
675
676 /*
677 * Initialize the tables for a node.
678 */
679 static void
680 ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
681 {
682 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
683 struct ieee80211com *ic = &sc->sc_ic;
684 struct ath_node *an = ATH_NODE(ni);
685 struct sample_node *sn = ATH_NODE_SAMPLE(an);
686 const HAL_RATE_TABLE *rt = sc->sc_currates;
687 int x, y, srate;
688
689 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
690 sn->static_rate_ndx = -1;
691 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
692 /*
693 * A fixed rate is to be used; ic_fixed_rate is an
694 * index into the supported rate set. Convert this
695 * to the index into the negotiated rate set for
696 * the node. We know the rate is there because the
697 * rate set is checked when the station associates.
698 */
699 const struct ieee80211_rateset *rs =
700 &ic->ic_sup_rates[ic->ic_curmode];
701 int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
702 /* NB: the rate set is assumed sorted */
703 srate = ni->ni_rates.rs_nrates - 1;
704 for (; srate >= 0 && RATE(srate) != r; srate--)
705 ;
706 KASSERT(srate >= 0,
707 ("fixed rate %d not in rate set", ic->ic_fixed_rate));
708 sn->static_rate_ndx = srate;
709 }
710
711 DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
712
713 sn->num_rates = ni->ni_rates.rs_nrates;
714 for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
715 sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
716 sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
717 sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
718 sn->rates[x].shortPreambleRateCode =
719 rt->info[sn->rates[x].rix].rateCode |
720 rt->info[sn->rates[x].rix].shortPreamble;
721
722 DPRINTF(sc, " %d/%d", sn->rates[x].rate,
723 calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix,
724 0,0));
725 }
726 DPRINTF(sc, "%s\n", "");
727
728 /* set the visible bit-rate to the lowest one available */
729 ni->ni_txrate = 0;
730 sn->num_rates = ni->ni_rates.rs_nrates;
731
732 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
733 int size = bin_to_size(y);
734 sn->packets_sent[y] = 0;
735 sn->current_sample_ndx[y] = -1;
736 sn->last_sample_ndx[y] = 0;
737
738 for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
739 sn->stats[y][x].successive_failures = 0;
740 sn->stats[y][x].tries = 0;
741 sn->stats[y][x].total_packets = 0;
742 sn->stats[y][x].packets_acked = 0;
743 sn->stats[y][x].last_tx = 0;
744
745 sn->stats[y][x].perfect_tx_time =
746 calc_usecs_unicast_packet(sc, size,
747 sn->rates[x].rix,
748 0, 0);
749 sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
750 }
751 }
752 #undef RATE
753 }
754
755 static void
756 rate_cb(void *arg, struct ieee80211_node *ni)
757 {
758 struct ath_softc *sc = arg;
759
760 ath_rate_newassoc(sc, ATH_NODE(ni), 1);
761 }
762
763 /*
764 * Reset the rate control state for each 802.11 state transition.
765 */
766 void
767 ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
768 {
769 struct ieee80211com *ic = &sc->sc_ic;
770
771 if (state == IEEE80211_S_RUN) {
772 if (ic->ic_opmode != IEEE80211_M_STA) {
773 /*
774 * Sync rates for associated stations and neighbors.
775 */
776 ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc);
777 }
778 ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
779 }
780 }
781
782 static void
783 ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc)
784 {
785 int rc;
786 struct sysctllog **log = &sc->sc_sysctllog;
787 const struct sysctlnode *cnode, *rnode;
788
789 if ((rnode = ath_sysctl_instance(sc->sc_dev.dv_xname, log)) == NULL)
790 return;
791
792 /* XXX bounds check [0..100] */
793 if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, smoothing_rate,
794 "rate control: retry threshold to credit rate raise (%%)")) != 0)
795 goto err;
796
797 /* XXX bounds check [2..100] */
798 if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, sample_rate,
799 "rate control: # good periods before raising rate")) != 0)
800 goto err;
801
802 return;
803 err:
804 printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
805 }
806
807 struct ath_ratectrl *
808 ath_rate_attach(struct ath_softc *sc)
809 {
810 struct sample_softc *osc;
811
812 DPRINTF(sc, "%s:\n", __func__);
813 osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
814 if (osc == NULL)
815 return NULL;
816 osc->arc.arc_space = sizeof(struct sample_node);
817 osc->ath_smoothing_rate = 95; /* ewma percentage (out of 100) */
818 osc->ath_sample_rate = 10; /* send a different bit-rate 1/X packets */
819 ath_rate_sysctlattach(sc, osc);
820 return &osc->arc;
821 }
822
823 void
824 ath_rate_detach(struct ath_ratectrl *arc)
825 {
826 struct sample_softc *osc = (struct sample_softc *) arc;
827
828 free(osc, M_DEVBUF);
829 }
830