xref: /netbsd-src/sys/dev/ic/athrate-sample.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: athrate-sample.c,v 1.13 2007/10/19 11:59:47 ad 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.13 2007/10/19 11:59:47 ad 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 <sys/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/ath/ah_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  * Also, this implementation tracks the average transmission time for
116  * a few different packet sizes independently for each link.
117  */
118 
119 #define STALE_FAILURE_TIMEOUT_MS 10000
120 #define MIN_SWITCH_MS 1000
121 
122 static void	ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
123 
124 static inline int
125 size_to_bin(int size)
126 {
127 	int x = 0;
128 	for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) {
129 		if (size <= packet_size_bins[x]) {
130 			return x;
131 		}
132 	}
133 	return NUM_PACKET_SIZE_BINS-1;
134 }
135 static inline int bin_to_size(int index) {
136 	return packet_size_bins[index];
137 }
138 
139 static inline int
140 rate_to_ndx(struct sample_node *sn, int rate) {
141 	int x = 0;
142 	for (x = 0; x < sn->num_rates; x++) {
143 		if (sn->rates[x].rate == rate) {
144 			return x;
145 		}
146 	}
147 	return -1;
148 }
149 
150 void
151 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
152 {
153 	DPRINTF(sc, "%s:\n", __func__);
154 	/* NB: assumed to be zero'd by caller */
155 }
156 
157 void
158 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
159 {
160 	DPRINTF(sc, "%s:\n", __func__);
161 }
162 
163 
164 /*
165  * returns the ndx with the lowest average_tx_time,
166  * or -1 if all the average_tx_times are 0.
167  */
168 static inline int best_rate_ndx(struct sample_node *sn, int size_bin,
169 				  int require_acked_before)
170 {
171 	int x = 0;
172         int best_ndx = 0;
173         int best_rate_tt = 0;
174         for (x = 0; x < sn->num_rates; x++) {
175 		int tt = sn->stats[size_bin][x].average_tx_time;
176 		if (tt <= 0 || (require_acked_before &&
177 				!sn->stats[size_bin][x].packets_acked)) {
178 			continue;
179 		}
180 
181 		/* 9 megabits never works better than 12 */
182 		if (sn->rates[x].rate == 18)
183 			continue;
184 
185 		/* don't use a bit-rate that has been failing */
186 		if (sn->stats[size_bin][x].successive_failures > 3)
187 			continue;
188 
189 		if (!best_rate_tt || best_rate_tt > tt) {
190 			best_rate_tt = tt;
191 			best_ndx = x;
192 		}
193         }
194         return (best_rate_tt) ? best_ndx : -1;
195 }
196 
197 /*
198  * pick a good "random" bit-rate to sample other than the current one
199  */
200 static inline int
201 pick_sample_ndx(struct sample_node *sn, int size_bin)
202 {
203 	int x = 0;
204 	int current_ndx = 0;
205 	unsigned current_tt = 0;
206 
207 	current_ndx = sn->current_rate[size_bin];
208 	if (current_ndx < 0) {
209 		/* no successes yet, send at the lowest bit-rate */
210 		return 0;
211 	}
212 
213 	current_tt = sn->stats[size_bin][current_ndx].average_tx_time;
214 
215 	for (x = 0; x < sn->num_rates; x++) {
216 		int ndx = (sn->last_sample_ndx[size_bin]+1+x) % sn->num_rates;
217 
218 	        /* don't sample the current bit-rate */
219 		if (ndx == current_ndx)
220 			continue;
221 
222 		/* this bit-rate is always worse than the current one */
223 		if (sn->stats[size_bin][ndx].perfect_tx_time > current_tt)
224 			continue;
225 
226 		/* rarely sample bit-rates that fail a lot */
227 		if (ticks - sn->stats[size_bin][ndx].last_tx < ((hz * STALE_FAILURE_TIMEOUT_MS)/1000) &&
228 		    sn->stats[size_bin][ndx].successive_failures > 3)
229 			continue;
230 
231 		/* don't sample more than 2 indexes higher
232 		 * for rates higher than 11 megabits
233 		 */
234 		if (sn->rates[ndx].rate > 22 && ndx > current_ndx + 2)
235 			continue;
236 
237 		/* 9 megabits never works better than 12 */
238 		if (sn->rates[ndx].rate == 18)
239 			continue;
240 
241 		/* if we're using 11 megabits, only sample up to 12 megabits
242 		 */
243 		if (sn->rates[current_ndx].rate == 22 && ndx > current_ndx + 1)
244 			continue;
245 
246 		sn->last_sample_ndx[size_bin] = ndx;
247 		return ndx;
248 	}
249 	return current_ndx;
250 }
251 
252 void
253 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
254 		  int shortPreamble, size_t frameLen,
255 		  u_int8_t *rix, int *try0, u_int8_t *txrate)
256 {
257 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
258 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
259 	struct ieee80211com *ic = &sc->sc_ic;
260 	int ndx, size_bin, mrr, best_ndx, change_rates;
261 	unsigned average_tx_time;
262 
263 	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
264 	size_bin = size_to_bin(frameLen);
265 	best_ndx = best_rate_ndx(sn, size_bin, !mrr);
266 
267 	if (best_ndx >= 0) {
268 		average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time;
269 	} else {
270 		average_tx_time = 0;
271 	}
272 
273 	if (sn->static_rate_ndx != -1) {
274 		ndx = sn->static_rate_ndx;
275 		*try0 = ATH_TXMAXTRY;
276 	} else {
277 		*try0 = mrr ? 2 : ATH_TXMAXTRY;
278 
279 		if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100)) {
280 			/*
281 			 * we want to limit the time measuring the performance
282 			 * of other bit-rates to ath_sample_rate% of the
283 			 * total transmission time.
284 			 */
285 			ndx = pick_sample_ndx(sn, size_bin);
286 			if (ndx != sn->current_rate[size_bin]) {
287 				sn->current_sample_ndx[size_bin] = ndx;
288 			} else {
289 				sn->current_sample_ndx[size_bin] = -1;
290 			}
291 			sn->packets_since_sample[size_bin] = 0;
292 
293 		} else {
294 			change_rates = 0;
295 			if (!sn->packets_sent[size_bin] || best_ndx == -1) {
296 				/* no packet has been sent successfully yet */
297 				for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
298 					/*
299 					 * pick the highest rate <= 36 Mbps
300 					 * that hasn't failed.
301 					 */
302 					if (sn->rates[ndx].rate <= 72 &&
303 					    sn->stats[size_bin][ndx].successive_failures == 0) {
304 						break;
305 					}
306 				}
307 				change_rates = 1;
308 				best_ndx = ndx;
309 			} else if (sn->packets_sent[size_bin] < 20) {
310 				/* let the bit-rate switch quickly during the first few packets */
311 				change_rates = 1;
312 			} else if (ticks - ((hz*MIN_SWITCH_MS)/1000) > sn->ticks_since_switch[size_bin]) {
313 				/* 2 seconds have gone by */
314 				change_rates = 1;
315 			} else if (average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time) {
316 				/* the current bit-rate is twice as slow as the best one */
317 				change_rates = 1;
318 			}
319 
320 			sn->packets_since_sample[size_bin]++;
321 
322 			if (change_rates) {
323 				if (best_ndx != sn->current_rate[size_bin]) {
324 					DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n",
325 						__func__,
326 						ether_sprintf(an->an_node.ni_macaddr),
327 						packet_size_bins[size_bin],
328 						sn->rates[sn->current_rate[size_bin]].rate,
329 						sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time,
330 						sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time,
331 						sn->rates[best_ndx].rate,
332 						sn->stats[size_bin][best_ndx].average_tx_time,
333 						sn->stats[size_bin][best_ndx].perfect_tx_time,
334 						sn->packets_since_switch[size_bin],
335 						mrr);
336 				}
337 				sn->packets_since_switch[size_bin] = 0;
338 				sn->current_rate[size_bin] = best_ndx;
339 				sn->ticks_since_switch[size_bin] = ticks;
340 			}
341 			ndx = sn->current_rate[size_bin];
342 			sn->packets_since_switch[size_bin]++;
343 			if (size_bin == 0) {
344 	    			/*
345 	    			 * set the visible txrate for this node
346 			         * to the rate of small packets
347 			         */
348 				an->an_node.ni_txrate = ndx;
349 			}
350 		}
351 	}
352 
353 	KASSERT(ndx >= 0 && ndx < sn->num_rates, ("ndx is %d", ndx));
354 
355 	*rix = sn->rates[ndx].rix;
356 	if (shortPreamble) {
357 		*txrate = sn->rates[ndx].shortPreambleRateCode;
358 	} else {
359 		*txrate = sn->rates[ndx].rateCode;
360 	}
361 	sn->packets_sent[size_bin]++;
362 }
363 
364 void
365 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
366     struct ath_desc *ds, int shortPreamble, u_int8_t rix)
367 {
368 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
369 	int rateCode = -1;
370 	int frame_size = 0;
371 	int size_bin = 0;
372 	int ndx = 0;
373 
374 	size_bin = size_to_bin(frame_size);	// TODO: it's correct that frame_size alway 0 ?
375 	ndx = sn->current_rate[size_bin]; /* retry at the current bit-rate */
376 
377 	if (!sn->stats[size_bin][ndx].packets_acked) {
378 		ndx = 0;  /* use the lowest bit-rate */
379 	}
380 
381 	if (shortPreamble) {
382 		rateCode = sn->rates[ndx].shortPreambleRateCode;
383 	} else {
384 		rateCode = sn->rates[ndx].rateCode;
385 	}
386 	ath_hal_setupxtxdesc(sc->sc_ah, ds
387 			     , rateCode, 3	        /* series 1 */
388 			     , sn->rates[0].rateCode, 3	/* series 2 */
389 			     , 0, 0	                /* series 3 */
390 			     );
391 }
392 
393 static void
394 update_stats(struct ath_softc *sc, struct ath_node *an,
395 		  int frame_size,
396 		  int ndx0, int tries0,
397 		  int ndx1, int tries1,
398 		  int ndx2, int tries2,
399 		  int ndx3, int tries3,
400 		  int short_tries, int tries, int status)
401 {
402 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
403 	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
404 	int tt = 0;
405 	int tries_so_far = 0;
406 	int size_bin;
407 	int size;
408 	int rate;
409 
410 	if (ndx0 == -1)
411 		return;
412 
413 	size_bin = size_to_bin(frame_size);
414 	size = bin_to_size(size_bin);
415 	rate = sn->rates[ndx0].rate;
416 
417 	tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix,
418 	    short_tries - 1, MIN(tries0, tries) - 1);
419 	tries_so_far += tries0;
420 	if (tries1 && tries0 < tries) {
421 		tt += calc_usecs_unicast_packet(sc, size,
422 		    ndx1 == -1 ? 0 : sn->rates[ndx1].rix, short_tries - 1,
423 		    MIN(tries1 + tries_so_far, tries) - tries_so_far - 1);
424 	}
425 	tries_so_far += tries1;
426 
427 	if (tries2 && tries0 + tries1 < tries) {
428 		tt += calc_usecs_unicast_packet(sc, size,
429 		    ndx2 == -1 ? 0 : sn->rates[ndx2].rix, short_tries - 1,
430 		    MIN(tries2 + tries_so_far, tries) - tries_so_far - 1);
431 	}
432 
433 	tries_so_far += tries2;
434 
435 	if (tries3 && tries0 + tries1 + tries2 < tries) {
436 		tt += calc_usecs_unicast_packet(sc, size,
437 		    ndx3 == -1 ? 0 : sn->rates[ndx3].rix, short_tries - 1,
438 		    MIN(tries3 + tries_so_far, tries) - tries_so_far - 1);
439 	}
440 
441 	if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) {
442 		/* just average the first few packets */
443 		int avg_tx = sn->stats[size_bin][ndx0].average_tx_time;
444 		int packets = sn->stats[size_bin][ndx0].total_packets;
445 		sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1);
446 	} else {
447 		/* use a ewma */
448 		sn->stats[size_bin][ndx0].average_tx_time =
449 			((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) +
450 			 (tt * (100 - ssc->ath_smoothing_rate))) / 100;
451 	}
452 
453 	if (status) {
454 		int y;
455 		sn->stats[size_bin][ndx0].successive_failures++;
456 		for (y = size_bin+1; y < NUM_PACKET_SIZE_BINS; y++) {
457 			/* also say larger packets failed since we
458 			 * assume if a small packet fails at a lower
459 			 * bit-rate then a larger one will also.
460 			 */
461 			sn->stats[y][ndx0].successive_failures++;
462 			sn->stats[y][ndx0].last_tx = ticks;
463 			sn->stats[y][ndx0].tries += tries;
464 			sn->stats[y][ndx0].total_packets++;
465 		}
466 	} else {
467 		sn->stats[size_bin][ndx0].packets_acked++;
468 		sn->stats[size_bin][ndx0].successive_failures = 0;
469 	}
470 	sn->stats[size_bin][ndx0].tries += tries;
471 	sn->stats[size_bin][ndx0].last_tx = ticks;
472 	sn->stats[size_bin][ndx0].total_packets++;
473 
474 
475 	if (ndx0 == sn->current_sample_ndx[size_bin]) {
476 		DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n",
477 			__func__, ether_sprintf(an->an_node.ni_macaddr),
478 			size, rate, short_tries, tries, tt,
479 			sn->stats[size_bin][ndx0].average_tx_time,
480 			sn->stats[size_bin][ndx0].perfect_tx_time,
481 			status);
482 		sn->sample_tt[size_bin] = tt;
483 		sn->current_sample_ndx[size_bin] = -1;
484 	}
485 }
486 
487 void
488 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
489 	const struct ath_desc *ds, const struct ath_desc *ds0)
490 {
491 	struct ieee80211com *ic = &sc->sc_ic;
492 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
493 	const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0;
494 	int final_rate, short_tries, long_tries, frame_size;
495 	int ndx = -1;
496 	int mrr;
497 
498 	final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
499 	short_tries = ds->ds_txstat.ts_shortretry + 1;
500 	long_tries = ds->ds_txstat.ts_longretry + 1;
501 	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
502 	if (frame_size == 0)		    /* NB: should not happen */
503 		frame_size = 1500;
504 
505 	if (sn->num_rates <= 0) {
506 		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d "
507 			"no rates yet\n",
508 			__func__, ether_sprintf(an->an_node.ni_macaddr),
509 			bin_to_size(size_to_bin(frame_size)),
510 			ds->ds_txstat.ts_status,
511 			short_tries, long_tries);
512 		return;
513 	}
514 
515 	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
516 
517 	if (sc->sc_mrretry && ds->ds_txstat.ts_status) {
518 		/* this packet failed */
519 		DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n",
520 			__func__,
521 			ether_sprintf(an->an_node.ni_macaddr),
522 			bin_to_size(size_to_bin(frame_size)),
523 			sc->sc_hwmap[ads->xmit_rate0].ieeerate,
524 				ads->xmit_tries0,
525 			sc->sc_hwmap[ads->xmit_rate1].ieeerate,
526 				ads->xmit_tries1,
527 			sc->sc_hwmap[ads->xmit_rate2].ieeerate,
528 				ads->xmit_tries2,
529 			sc->sc_hwmap[ads->xmit_rate3].ieeerate,
530 				ads->xmit_tries3,
531 			ds->ds_txstat.ts_status ? "FAIL" : "OK",
532 			short_tries,
533 			long_tries);
534 	}
535 
536 	if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) {
537 		/* only one rate was used */
538 		ndx = rate_to_ndx(sn, final_rate);
539 		DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n",
540 			__func__, ether_sprintf(an->an_node.ni_macaddr),
541 			bin_to_size(size_to_bin(frame_size)),
542 			ds->ds_txstat.ts_status,
543 			ndx, short_tries, long_tries);
544 		if (ndx >= 0 && ndx < sn->num_rates) {
545 			update_stats(sc, an, frame_size,
546 				     ndx, long_tries,
547 				     0, 0,
548 				     0, 0,
549 				     0, 0,
550 				     short_tries, long_tries, ds->ds_txstat.ts_status);
551 		}
552 	} else {
553 		int rate0, tries0, ndx0;
554 		int rate1, tries1, ndx1;
555 		int rate2, tries2, ndx2;
556 		int rate3, tries3, ndx3;
557 		int finalTSIdx = ads->final_ts_index;
558 
559 		/*
560 		 * Process intermediate rates that failed.
561 		 */
562 
563 		rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate;
564 		tries0 = ads->xmit_tries0;
565 		ndx0 = rate_to_ndx(sn, rate0);
566 
567 		rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate;
568 		tries1 = ads->xmit_tries1;
569 		ndx1 = rate_to_ndx(sn, rate1);
570 
571 		rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate;
572 		tries2 = ads->xmit_tries2;
573 		ndx2 = rate_to_ndx(sn, rate2);
574 
575 		rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate;
576 		tries3 = ads->xmit_tries3;
577 		ndx3 = rate_to_ndx(sn, rate3);
578 
579 #if 1
580 		DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n",
581 			__func__, ether_sprintf(an->an_node.ni_macaddr),
582 			bin_to_size(size_to_bin(frame_size)),
583 			finalTSIdx,
584 			long_tries,
585 			ds->ds_txstat.ts_status,
586 			rate0, tries0,
587 			rate1, tries1,
588 			rate2, tries2,
589 			rate3, tries3);
590 #endif
591 
592 		if (tries0) {
593 			update_stats(sc, an, frame_size,
594 				     ndx0, tries0,
595 				     ndx1, tries1,
596 				     ndx2, tries2,
597 				     ndx3, tries3,
598 				     short_tries, ds->ds_txstat.ts_longretry + 1,
599 				     long_tries > tries0);
600 		}
601 
602 		if (tries1 && finalTSIdx > 0) {
603 			update_stats(sc, an, frame_size,
604 				     ndx1, tries1,
605 				     ndx2, tries2,
606 				     ndx3, tries3,
607 				     0, 0,
608 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0,
609 				     ds->ds_txstat.ts_status);
610 		}
611 
612 		if (tries2 && finalTSIdx > 1) {
613 			update_stats(sc, an, frame_size,
614 				     ndx2, tries2,
615 				     ndx3, tries3,
616 				     0, 0,
617 				     0, 0,
618 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1,
619 				     ds->ds_txstat.ts_status);
620 		}
621 
622 		if (tries3 && finalTSIdx > 2) {
623 			update_stats(sc, an, frame_size,
624 				     ndx3, tries3,
625 				     0, 0,
626 				     0, 0,
627 				     0, 0,
628 				     short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2,
629 				     ds->ds_txstat.ts_status);
630 		}
631 	}
632 }
633 
634 void
635 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
636 {
637 	DPRINTF(sc, "%s: %s isnew %d\n", __func__,
638 		ether_sprintf(an->an_node.ni_macaddr), isnew);
639 	if (isnew)
640 		ath_rate_ctl_reset(sc, &an->an_node);
641 }
642 
643 /*
644  * Initialize the tables for a node.
645  */
646 static void
647 ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
648 {
649 #define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
650 	struct ieee80211com *ic = &sc->sc_ic;
651 	struct ath_node *an = ATH_NODE(ni);
652 	struct sample_node *sn = ATH_NODE_SAMPLE(an);
653 	const HAL_RATE_TABLE *rt = sc->sc_currates;
654 	int x, y, srate;
655 
656 	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
657         sn->static_rate_ndx = -1;
658 	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
659 		/*
660 		 * A fixed rate is to be used; ic_fixed_rate is an
661 		 * index into the supported rate set.  Convert this
662 		 * to the index into the negotiated rate set for
663 		 * the node.  We know the rate is there because the
664 		 * rate set is checked when the station associates.
665 		 */
666 		const struct ieee80211_rateset *rs =
667 			&ic->ic_sup_rates[ic->ic_curmode];
668 		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
669 		/* NB: the rate set is assumed sorted */
670 		srate = ni->ni_rates.rs_nrates - 1;
671 		for (; srate >= 0 && RATE(srate) != r; srate--)
672 			;
673 		KASSERT(srate >= 0,
674 			("fixed rate %d not in rate set", ic->ic_fixed_rate));
675                 sn->static_rate_ndx = srate;
676 	}
677 
678         DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr));
679 
680 	sn->num_rates = ni->ni_rates.rs_nrates;
681         for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
682 		sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
683 		sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
684 		sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
685 		sn->rates[x].shortPreambleRateCode =
686 			rt->info[sn->rates[x].rix].rateCode |
687 			rt->info[sn->rates[x].rix].shortPreamble;
688 
689 		DPRINTF(sc, " %d/%d", sn->rates[x].rate,
690 			calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix,
691 						  0,0));
692 	}
693 	DPRINTF(sc, "%s\n", "");
694 
695 	/* set the visible bit-rate to the lowest one available */
696 	ni->ni_txrate = 0;
697 	sn->num_rates = ni->ni_rates.rs_nrates;
698 
699 	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
700 		int size = bin_to_size(y);
701 		int ndx = 0;
702 		sn->packets_sent[y] = 0;
703 		sn->current_sample_ndx[y] = -1;
704 		sn->last_sample_ndx[y] = 0;
705 
706 		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
707 			sn->stats[y][x].successive_failures = 0;
708 			sn->stats[y][x].tries = 0;
709 			sn->stats[y][x].total_packets = 0;
710 			sn->stats[y][x].packets_acked = 0;
711 			sn->stats[y][x].last_tx = 0;
712 
713 			sn->stats[y][x].perfect_tx_time =
714 				calc_usecs_unicast_packet(sc, size,
715 							  sn->rates[x].rix,
716 							  0, 0);
717 			sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
718 		}
719 
720 		/* set the initial rate */
721 		for (ndx = sn->num_rates-1; ndx > 0; ndx--) {
722 			if (sn->rates[ndx].rate <= 72) {
723 				break;
724 			}
725 		}
726 		sn->current_rate[y] = ndx;
727 	}
728 
729 	DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n",
730 		__func__, ether_sprintf(ni->ni_macaddr),
731 		sn->num_rates,
732 		sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "",
733 		sn->stats[1][0].perfect_tx_time,
734 		sn->rates[sn->num_rates-1].rate/2,
735 			sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "",
736 		sn->stats[1][sn->num_rates-1].perfect_tx_time
737 	);
738 
739 	ni->ni_txrate = sn->current_rate[0];
740 #undef RATE
741 }
742 
743 static void
744 rate_cb(void *arg, struct ieee80211_node *ni)
745 {
746 	struct ath_softc *sc = arg;
747 
748 	ath_rate_newassoc(sc, ATH_NODE(ni), 1);
749 }
750 
751 /*
752  * Reset the rate control state for each 802.11 state transition.
753  */
754 void
755 ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
756 {
757 	struct ieee80211com *ic = &sc->sc_ic;
758 
759 	if (state == IEEE80211_S_RUN) {
760 		if (ic->ic_opmode != IEEE80211_M_STA) {
761 			/*
762 			 * Sync rates for associated stations and neighbors.
763 			 */
764 			ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc);
765 		}
766 		ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
767 	}
768 }
769 
770 static void
771 ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc)
772 {
773 	int rc;
774 	struct sysctllog **log = &sc->sc_sysctllog;
775 	const struct sysctlnode *cnode, *rnode;
776 
777 	if ((rnode = ath_sysctl_instance(sc->sc_dev.dv_xname, log)) == NULL)
778 		return;
779 
780 	/* XXX bounds check [0..100] */
781 	if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, smoothing_rate,
782 	    "rate control: retry threshold to credit rate raise (%%)")) != 0)
783 		goto err;
784 
785 	/* XXX bounds check [2..100] */
786 	if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, sample_rate,
787 	    "rate control: # good periods before raising rate")) != 0)
788 		goto err;
789 
790 	return;
791 err:
792 	printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc);
793 }
794 
795 struct ath_ratectrl *
796 ath_rate_attach(struct ath_softc *sc)
797 {
798 	struct sample_softc *osc;
799 
800 	DPRINTF(sc, "%s:\n", __func__);
801 	osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
802 	if (osc == NULL)
803 		return NULL;
804 	osc->arc.arc_space = sizeof(struct sample_node);
805 	osc->ath_smoothing_rate = 95;	/* ewma percentage (out of 100) */
806 	osc->ath_sample_rate = 10;	/* send a different bit-rate 1/X packets */
807 	ath_rate_sysctlattach(sc, osc);
808 	return &osc->arc;
809 }
810 
811 void
812 ath_rate_detach(struct ath_ratectrl *arc)
813 {
814 	struct sample_softc *osc = (struct sample_softc *) arc;
815 
816 	free(osc, M_DEVBUF);
817 }
818