sample.c revision 143392
1/*-
2 * Copyright (c) 2005 John Bicket
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
18 *
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.
22 *
23 * NO WARRANTY
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.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 143392 2005-03-11 01:39:57Z sam $");
39
40/*
41 * John Bicket's SampleRate control algorithm.
42 */
43#include "opt_inet.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/sysctl.h>
48#include <sys/module.h>
49#include <sys/kernel.h>
50#include <sys/lock.h>
51#include <sys/mutex.h>
52#include <sys/errno.h>
53
54#include <machine/bus.h>
55#include <machine/resource.h>
56#include <sys/bus.h>
57
58#include <sys/socket.h>
59
60#include <net/if.h>
61#include <net/if_media.h>
62#include <net/if_arp.h>
63#include <net/ethernet.h>		/* XXX for ether_sprintf */
64
65#include <net80211/ieee80211_var.h>
66
67#include <net/bpf.h>
68
69#ifdef INET
70#include <netinet/in.h>
71#include <netinet/if_ether.h>
72#endif
73
74#include <dev/ath/if_athvar.h>
75#include <dev/ath/ath_rate/sample/sample.h>
76#include <contrib/dev/ath/ah_desc.h>
77
78#define	SAMPLE_DEBUG
79#ifdef SAMPLE_DEBUG
80enum {
81	ATH_DEBUG_RATE		= 0x00000010,	/* rate control */
82};
83#define	DPRINTF(sc, _fmt, ...) do {				\
84	if (sc->sc_debug & ATH_DEBUG_RATE)			\
85		printf(_fmt, __VA_ARGS__);			\
86} while (0)
87#else
88#define	DPRINTF(sc, _fmt, ...)
89#endif
90
91/*
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)
95 *
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.
107 *
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.
110 *
111 */
112
113static void	ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *);
114
115static __inline int size_to_bin(int size)
116{
117	int x = 0;
118	for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) {
119		if (size < packet_size_bins[x]) {
120			return x;
121		}
122	}
123	return NUM_PACKET_SIZE_BINS-1;
124}
125static __inline int bin_to_size(int index) {
126	return packet_size_bins[index];
127}
128
129/*
130 * Setup rate codes for management/control frames.  We force
131 * all such frames to the lowest rate.
132 */
133static void
134ath_rate_setmgtrates(struct ath_softc *sc, struct ath_node *an)
135{
136	const HAL_RATE_TABLE *rt = sc->sc_currates;
137
138	/* setup rates for management frames */
139	/* XXX management/control frames always go at lowest speed */
140	an->an_tx_mgtrate = rt->info[0].rateCode;
141	an->an_tx_mgtratesp = an->an_tx_mgtrate
142			    | rt->info[0].shortPreamble;
143}
144
145void
146ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
147{
148	DPRINTF(sc, "%s:\n", __func__);
149	/* NB: assumed to be zero'd by caller */
150	ath_rate_setmgtrates(sc, an);
151}
152
153void
154ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
155{
156	DPRINTF(sc, "%s:\n", __func__);
157}
158
159
160/*
161 * returns the ndx with the lowest average_tx_time,
162 * or -1 if all the average_tx_times are 0.
163 */
164static __inline int best_rate_ndx(struct sample_node *sn, int size_bin)
165{
166	int x = 0;
167        int best_rate_ndx = 0;
168        int best_rate_tt = 0;
169        for (x = 0; x < sn->num_rates; x++) {
170		int tt = sn->stats[size_bin][x].average_tx_time;
171		if (tt > 0) {
172			if (!best_rate_tt || best_rate_tt > tt) {
173				best_rate_tt = tt;
174				best_rate_ndx = x;
175			}
176		}
177        }
178        return (best_rate_tt) ? best_rate_ndx : -1;
179}
180
181/*
182 * pick a ndx s.t. the perfect_tx_time
183 * is less than the best bit-rate's average_tx_time
184 * and the ndx has not had four successive failures.
185 */
186static __inline int pick_sample_ndx(struct sample_node *sn, int size_bin)
187{
188	int x = 0;
189	int best_ndx = best_rate_ndx(sn, size_bin);
190	int best_tt = 0;
191	int num_eligible = 0;
192
193	if (best_ndx < 0) {
194		/* no successes yet, send at the lowest bit-rate */
195		return 0;
196	}
197
198	best_tt = sn->stats[size_bin][best_ndx].average_tx_time;
199	sn->sample_num[size_bin]++;
200
201	/*
202	 * first, find the number of bit-rates we could potentially
203	 * sample. we assume this list doesn't change a lot, so
204	 * we will just cycle through them.
205	 */
206	for (x = 0; x < sn->num_rates; x++) {
207		if (x != best_ndx &&
208		    sn->stats[size_bin][x].perfect_tx_time < best_tt &&
209		    sn->stats[size_bin][x].successive_failures < 4) {
210			num_eligible++;
211		}
212	}
213
214	if (num_eligible > 0) {
215		int pick = sn->sample_num[size_bin] % num_eligible;
216		for (x = 0; x < sn->num_rates; x++) {
217			if (x != best_ndx &&
218			    sn->stats[size_bin][x].perfect_tx_time < best_tt &&
219			    sn->stats[size_bin][x].successive_failures < 4) {
220				if (pick == 0) {
221					return x;
222				}
223				pick--;
224			}
225		}
226	}
227	return best_ndx;
228}
229
230void
231ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
232		  HAL_BOOL shortPreamble, size_t frameLen,
233		  u_int8_t *rix, int *try0, u_int8_t *txrate)
234{
235	struct sample_node *sn = ATH_NODE_SAMPLE(an);
236	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
237	int x;
238	int ndx = 0;
239	int size_bin = size_to_bin(frameLen);
240	int best_ndx = best_rate_ndx(sn, size_bin);
241
242	if (sn->static_rate_ndx != -1) {
243		*try0 = 4;
244		*rix = sn->rates[sn->static_rate_ndx].rix;
245		*txrate = sn->rates[sn->static_rate_ndx].rateCode;
246		return;
247	}
248
249	*try0 = 2;
250
251	best_ndx = best_rate_ndx(sn, size_bin);
252	if (!sn->packets_sent[size_bin] ||
253	    sn->packets_sent[size_bin] % ssc->ath_sample_rate > 0) {
254		/*
255		 * for most packets, send the packet at the bit-rate with
256		 * the lowest estimated transmission time.
257		 */
258		if (best_ndx != -1) {
259			ndx = best_ndx;
260		} else {
261			/*
262			 * no packet has succeeded, try the highest bitrate
263			 * that hasn't failed.
264			 */
265			for (ndx = sn->num_rates-1; ndx >= 0; ndx--) {
266				if (sn->stats[size_bin][ndx].successive_failures == 0) {
267					break;
268				}
269			}
270		}
271		if (size_bin == 0) {
272			/* update the visible txrate for this node */
273			an->an_node.ni_txrate = ndx;
274		}
275	} else {
276		/*
277		 * before we pick a bit-rate to "sample", clear any
278		 * stale stuff out.
279		 */
280		for (x = 0; x < sn->num_rates; x++) {
281			if (ticks - sn->stats[size_bin][x].last_tx > ((hz * 10000)/1000)) {
282				sn->stats[size_bin][x].average_tx_time = sn->stats[size_bin][x].perfect_tx_time;
283				sn->stats[size_bin][x].successive_failures = 0;
284				sn->stats[size_bin][x].tries = 0;
285				sn->stats[size_bin][x].total_packets = 0;
286				sn->stats[size_bin][x].packets_acked = 0;
287			}
288		}
289
290		/* send the packet at a different bit-rate */
291		ndx = pick_sample_ndx(sn, size_bin);
292	}
293
294
295	*rix = sn->rates[ndx].rix;
296	if (shortPreamble) {
297		*txrate = sn->rates[ndx].shortPreambleRateCode;
298	} else {
299
300		*txrate = sn->rates[ndx].rateCode;
301	}
302
303	sn->packets_sent[size_bin]++;
304}
305
306void
307ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an,
308		      struct ath_desc *ds, HAL_BOOL shortPreamble, u_int8_t rix)
309{
310	struct sample_node *sn = ATH_NODE_SAMPLE(an);
311	int rateCode = -1;
312	int frame_size;
313	int size_bin;
314	int best_ndx;
315
316	frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
317	if (frame_size == 0)
318		frame_size = 1500;
319	size_bin = size_to_bin(frame_size);
320	best_ndx = best_rate_ndx(sn, size_bin);
321
322	if (best_ndx == -1 || !sn->stats[size_bin][best_ndx].packets_acked) {
323		/*
324		 * no packet has succeeded, so also try twice at the lowest bitate.
325		 */
326		if (shortPreamble) {
327			rateCode = sn->rates[0].shortPreambleRateCode;
328		} else {
329			rateCode = sn->rates[0].rateCode;
330		}
331	} else if (sn->rates[best_ndx].rix != rix) {
332		/*
333		 * we're trying a different bit-rate, and it could be lossy,
334		 * so if it fails try at the best bit-rate.
335		 */
336		if (shortPreamble) {
337			rateCode = sn->rates[MAX(0,best_ndx-1)].shortPreambleRateCode;
338		} else {
339			rateCode = sn->rates[MAX(0,best_ndx-1)].rateCode;
340		}
341	}
342	if (rateCode != -1) {
343		ath_hal_setupxtxdesc(sc->sc_ah, ds
344				     , rateCode, 1	/* series 1 */
345				     , rateCode, 1	        /* series 2 */
346				     , rateCode, 1	        /* series 3 */
347				     );
348	}
349
350}
351
352void
353ath_rate_tx_complete(struct ath_softc *sc,
354		     struct ath_node *an, const struct ath_desc *ds)
355{
356	struct sample_node *sn = ATH_NODE_SAMPLE(an);
357	struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
358	int rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate;
359	int retries = ds->ds_txstat.ts_longretry;
360	int initial_rate_failed = ((ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)
361				   || ds->ds_txstat.ts_status != 0 ||
362				   retries > 3);
363	int tt = 0;
364	int rix = -1;
365	int x = 0;
366	int frame_size; /* low-order 12 bits of ds_ctl0 */
367	int size_bin;
368	int size;
369
370	if (!sn->num_rates) {
371		DPRINTF(sc, "%s: no rates yet\n", __func__);
372		return;
373	}
374	for (x = 0; x < sn->num_rates; x++) {
375		if (sn->rates[x].rate == rate) {
376			rix = x;
377			break;
378		}
379	}
380
381	if (rix < 0 || rix > sn->num_rates) {
382		/* maybe a management packet */
383		return;
384	}
385
386	frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
387	if (frame_size == 0)
388		frame_size = 1500;
389	size_bin = size_to_bin(frame_size);
390	size = bin_to_size(size_bin);
391	tt = calc_usecs_unicast_packet(sc, size, sn->rates[rix].rix,
392				       retries);
393
394	DPRINTF(sc, "%s: rate %d rix %d frame_size %d (%d) retries %d status %d tt %d avg_tt %d perfect_tt %d ts-rate %d\n",
395		__func__, rate, rix, frame_size, size, retries, initial_rate_failed, tt,
396		sn->stats[size_bin][rix].average_tx_time,
397		sn->stats[size_bin][rix].perfect_tx_time,
398		ds->ds_txstat.ts_rate);
399
400	if (sn->stats[size_bin][rix].total_packets < 7) {
401		/* just average the first few packets */
402		int avg_tx = sn->stats[size_bin][rix].average_tx_time;
403		int packets = sn->stats[size_bin][rix].total_packets;
404		sn->stats[size_bin][rix].average_tx_time = (tt+(avg_tx*packets))/(packets+1);
405	} else {
406		/* use a ewma */
407		sn->stats[size_bin][rix].average_tx_time =
408			((sn->stats[size_bin][rix].average_tx_time * ssc->ath_smoothing_rate) +
409			 (tt * (100 - ssc->ath_smoothing_rate))) / 100;
410	}
411
412	if (initial_rate_failed) {
413		/*
414		 * this packet failed - count this as a failure
415		 * for larger packets also, since we assume
416		 * if a small packet fails at a lower bit-rate
417		 * then a larger one will also.
418		 */
419		int y;
420		for (y = size_bin; y < NUM_PACKET_SIZE_BINS; y++) {
421			sn->stats[y][rix].successive_failures++;
422			sn->stats[y][rix].last_tx = ticks;
423		}
424	} else {
425		sn->stats[size_bin][rix].packets_acked++;
426		sn->stats[size_bin][rix].successive_failures = 0;
427	}
428	sn->stats[size_bin][rix].tries += (1+retries);
429	sn->stats[size_bin][rix].last_tx = ticks;
430	sn->stats[size_bin][rix].total_packets++;
431}
432
433void
434ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew)
435{
436	DPRINTF(sc, "%s:\n", __func__);
437	if (isnew)
438		ath_rate_ctl_start(sc, &an->an_node);
439}
440
441static void
442ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
443{
444	struct ath_node *an = ATH_NODE(ni);
445	struct sample_node *sn = ATH_NODE_SAMPLE(an);
446	int x = 0;
447	int y = 0;
448
449	for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
450		int size = bin_to_size(y);
451		sn->packets_sent[y] = 0;
452		sn->sample_num[y] = 0;
453
454		for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
455			sn->stats[y][x].successive_failures = 0;
456			sn->stats[y][x].tries = 0;
457			sn->stats[y][x].total_packets = 0;
458			sn->stats[y][x].packets_acked = 0;
459			sn->stats[y][x].last_tx = 0;
460			sn->stats[y][x].perfect_tx_time = calc_usecs_unicast_packet(sc, size,
461									      sn->rates[x].rix,
462									      0);
463			sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time;
464
465
466			DPRINTF(sc, "%s: %d rate %d rix %d rateCode %d perfect_tx_time %d \n", __func__,
467				x, sn->rates[x].rate,
468				sn->rates[x].rix, sn->rates[x].rateCode,
469				sn->stats[0][x].perfect_tx_time);
470		}
471
472	}
473
474	/* set the visible bit-rate to the lowest one available */
475	ni->ni_txrate = 0;
476
477}
478
479/*
480 * Initialize the tables for a node.
481 */
482static void
483ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni)
484{
485#define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
486	struct ieee80211com *ic = &sc->sc_ic;
487	struct ath_node *an = ATH_NODE(ni);
488	struct sample_node *sn = ATH_NODE_SAMPLE(an);
489	const HAL_RATE_TABLE *rt = sc->sc_currates;
490
491	int x;
492	int srate;
493
494        DPRINTF(sc, "%s:\n", __func__);
495	KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
496	KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates"));
497        sn->static_rate_ndx = -1;
498	if (ic->ic_fixed_rate != -1) {
499		/*
500		 * A fixed rate is to be used; ic_fixed_rate is an
501		 * index into the supported rate set.  Convert this
502		 * to the index into the negotiated rate set for
503		 * the node.  We know the rate is there because the
504		 * rate set is checked when the station associates.
505		 */
506		const struct ieee80211_rateset *rs =
507			&ic->ic_sup_rates[ic->ic_curmode];
508		int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
509		/* NB: the rate set is assumed sorted */
510		srate = ni->ni_rates.rs_nrates - 1;
511		for (; srate >= 0 && RATE(srate) != r; srate--)
512			;
513		KASSERT(srate >= 0,
514			("fixed rate %d not in rate set", ic->ic_fixed_rate));
515                sn->static_rate_ndx = srate;
516
517	}
518	sn->num_rates = ni->ni_rates.rs_nrates;
519        for (x = 0; x < ni->ni_rates.rs_nrates; x++) {
520          sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL;
521          sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate];
522          sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode;
523          sn->rates[x].shortPreambleRateCode =
524		  rt->info[sn->rates[x].rix].rateCode |
525		  rt->info[sn->rates[x].rix].shortPreamble;
526	}
527	ath_rate_ctl_reset(sc, ni);
528
529#undef RATE
530}
531
532/*
533 * Reset the rate control state for each 802.11 state transition.
534 */
535void
536ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state)
537{
538	struct ieee80211com *ic = &sc->sc_ic;
539
540	if (state == IEEE80211_S_RUN)
541		ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1);
542}
543
544static void
545ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc)
546{
547	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
548	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
549
550	/* XXX bounds check [0..100] */
551	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
552		"smoothing_rate", CTLFLAG_RW, &osc->ath_smoothing_rate, 0,
553		"rate control: retry threshold to credit rate raise (%%)");
554	/* XXX bounds check [2..100] */
555	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
556		"sample_rate", CTLFLAG_RW, &osc->ath_sample_rate,0,
557		"rate control: # good periods before raising rate");
558}
559
560struct ath_ratectrl *
561ath_rate_attach(struct ath_softc *sc)
562{
563	struct sample_softc *osc;
564
565	DPRINTF(sc, "%s:\n", __func__);
566	osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO);
567	if (osc == NULL)
568		return NULL;
569	osc->arc.arc_space = sizeof(struct sample_node);
570	osc->ath_smoothing_rate = 95;	/* ewma percentage (out of 100) */
571	osc->ath_sample_rate = 10;	/* send a different bit-rate 1/X packets */
572	ath_rate_sysctlattach(sc, osc);
573	return &osc->arc;
574}
575
576void
577ath_rate_detach(struct ath_ratectrl *arc)
578{
579	struct sample_softc *osc = (struct sample_softc *) arc;
580
581	free(osc, M_DEVBUF);
582}
583
584/*
585 * Module glue.
586 */
587static int
588sample_modevent(module_t mod, int type, void *unused)
589{
590	switch (type) {
591	case MOD_LOAD:
592		if (bootverbose)
593			printf("ath_rate: <SampleRate bit-rate selection algorithm>\n");
594		return 0;
595	case MOD_UNLOAD:
596		return 0;
597	}
598	return EINVAL;
599}
600
601static moduledata_t sample_mod = {
602	"ath_rate",
603	sample_modevent,
604	0
605};
606DECLARE_MODULE(ath_rate, sample_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
607MODULE_VERSION(ath_rate, 1);
608MODULE_DEPEND(ath_rate, wlan, 1, 1, 1);
609