xref: /openbsd-src/sys/net80211/ieee80211_ra.c (revision 4e1ee0786f11cc571bd0be17d38e46f635c719fc)
1 /*	$OpenBSD: ieee80211_ra.c,v 1.4 2021/10/11 09:01:06 stsp Exp $	*/
2 
3 /*
4  * Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>
5  * Copyright (c) 2016, 2021 Stefan Sperling <stsp@openbsd.org>
6  * Copyright (c) 2016 Theo Buehler <tb@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/socket.h>
24 
25 #include <net/if.h>
26 #include <net/if_media.h>
27 
28 #include <netinet/in.h>
29 #include <netinet/if_ether.h>
30 
31 #include <net80211/ieee80211_var.h>
32 #include <net80211/ieee80211_ra.h>
33 
34 int	ieee80211_ra_next_intra_rate(struct ieee80211_ra_node *,
35 	    struct ieee80211_node *);
36 const struct ieee80211_ht_rateset * ieee80211_ra_next_rateset(
37 		    struct ieee80211_ra_node *, struct ieee80211_node *);
38 int	ieee80211_ra_best_mcs_in_rateset(struct ieee80211_ra_node *,
39 	    const struct ieee80211_ht_rateset *);
40 void	ieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *,
41 	    struct ieee80211_node *, const struct ieee80211_ht_rateset *);
42 int	ieee80211_ra_next_mcs(struct ieee80211_ra_node *,
43 	    struct ieee80211_node *);
44 void	ieee80211_ra_probe_done(struct ieee80211_ra_node *);
45 int	ieee80211_ra_intra_mode_ra_finished(
46 	    struct ieee80211_ra_node *, struct ieee80211_node *);
47 void	ieee80211_ra_trigger_next_rateset(struct ieee80211_ra_node *,
48 	    struct ieee80211_node *);
49 int	ieee80211_ra_inter_mode_ra_finished(
50 	    struct ieee80211_ra_node *, struct ieee80211_node *);
51 int	ieee80211_ra_best_rate(struct ieee80211_ra_node *,
52 	    struct ieee80211_node *);
53 void	ieee80211_ra_probe_next_rate(struct ieee80211_ra_node *,
54 	    struct ieee80211_node *);
55 int	ieee80211_ra_valid_tx_mcs(struct ieee80211com *, int);
56 uint32_t ieee80211_ra_valid_rates(struct ieee80211com *,
57 	    struct ieee80211_node *);
58 int	ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *);
59 
60 /* We use fixed point arithmetic with 64 bit integers. */
61 #define RA_FP_SHIFT	21
62 #define RA_FP_INT(x)	(x ## ULL << RA_FP_SHIFT) /* the integer x */
63 #define RA_FP_1	RA_FP_INT(1)
64 
65 /* Multiply two fixed point numbers. */
66 #define RA_FP_MUL(a, b) \
67 	(((a) * (b)) >> RA_FP_SHIFT)
68 
69 /* Divide two fixed point numbers. */
70 #define RA_FP_DIV(a, b) \
71 	(b == 0 ? (uint64_t)-1 : (((a) << RA_FP_SHIFT) / (b)))
72 
73 #define RA_DEBUG
74 #ifdef RA_DEBUG
75 #define DPRINTF(x)	do { if (ra_debug > 0) printf x; } while (0)
76 #define DPRINTFN(n, x)	do { if (ra_debug >= (n)) printf x; } while (0)
77 int ra_debug = 0;
78 #else
79 #define DPRINTF(x)	do { ; } while (0)
80 #define DPRINTFN(n, x)	do { ; } while (0)
81 #endif
82 
83 #ifdef RA_DEBUG
84 void
85 ra_fixedp_split(uint32_t *i, uint32_t *f, uint64_t fp)
86 {
87 	uint64_t tmp;
88 
89 	/* integer part */
90 	*i = (fp >> RA_FP_SHIFT);
91 
92  	/* fractional part */
93 	tmp = (fp & ((uint64_t)-1 >> (64 - RA_FP_SHIFT)));
94 	tmp *= 100;
95 	*f = (uint32_t)(tmp >> RA_FP_SHIFT);
96 }
97 
98 char *
99 ra_fp_sprintf(uint64_t fp)
100 {
101 	uint32_t i, f;
102 	static char buf[64];
103 	int ret;
104 
105 	ra_fixedp_split(&i, &f, fp);
106 	ret = snprintf(buf, sizeof(buf), "%u.%02u", i, f);
107 	if (ret == -1 || ret >= sizeof(buf))
108 		return "ERR";
109 
110 	return buf;
111 }
112 #endif /* RA_DEBUG */
113 
114 const struct ieee80211_ht_rateset *
115 ieee80211_ra_get_ht_rateset(int mcs, int chan40, int sgi)
116 {
117 	const struct ieee80211_ht_rateset *rs;
118 	int i;
119 
120 	for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {
121 		rs = &ieee80211_std_ratesets_11n[i];
122 		if (chan40 == rs->chan40 && sgi == rs->sgi &&
123 		    mcs >= rs->min_mcs && mcs <= rs->max_mcs)
124 			return rs;
125 	}
126 
127 	panic("MCS %d is not part of any rateset", mcs);
128 }
129 
130 int
131 ieee80211_ra_use_ht_sgi(struct ieee80211_node *ni)
132 {
133 	if ((ni->ni_chan->ic_flags & IEEE80211_CHAN_40MHZ) &&
134 	    ieee80211_node_supports_ht_chan40(ni)) {
135 		if (ni->ni_flags & IEEE80211_NODE_HT_SGI40)
136 			return 1;
137 	} else if (ni->ni_flags & IEEE80211_NODE_HT_SGI20)
138 		return 1;
139 
140 	return 0;
141 }
142 
143 /*
144  * Update goodput statistics.
145  */
146 
147 uint64_t
148 ieee80211_ra_get_txrate(int mcs, int chan40, int sgi)
149 {
150 	const struct ieee80211_ht_rateset *rs;
151 	uint64_t txrate;
152 
153 	rs = ieee80211_ra_get_ht_rateset(mcs, chan40, sgi);
154 	txrate = rs->rates[mcs - rs->min_mcs];
155 	txrate <<= RA_FP_SHIFT; /* convert to fixed-point */
156 	txrate *= 500; /* convert to kbit/s */
157 	txrate /= 1000; /* convert to mbit/s */
158 
159 	return txrate;
160 }
161 
162 /*
163  * Rate selection.
164  */
165 
166 /* A rate's goodput has to be at least this much larger to be "better". */
167 #define IEEE80211_RA_RATE_THRESHOLD	(RA_FP_1 / 64) /* ~ 0.015 */
168 
169 int
170 ieee80211_ra_next_lower_intra_rate(struct ieee80211_ra_node *rn,
171     struct ieee80211_node *ni)
172 {
173 	const struct ieee80211_ht_rateset *rs;
174 	int i, next;
175 
176 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
177 	    ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
178 	if (ni->ni_txmcs == rs->min_mcs)
179 		return rs->min_mcs;
180 
181 	next = ni->ni_txmcs;
182 	for (i = rs->nrates - 1; i >= 0; i--) {
183 		if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)
184 			continue;
185 		if (i + rs->min_mcs < ni->ni_txmcs) {
186 			next = i + rs->min_mcs;
187 			break;
188 		}
189 	}
190 
191 	return next;
192 }
193 
194 int
195 ieee80211_ra_next_intra_rate(struct ieee80211_ra_node *rn,
196     struct ieee80211_node *ni)
197 {
198 	const struct ieee80211_ht_rateset *rs;
199 	int i, next;
200 
201 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
202 	    ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
203 	if (ni->ni_txmcs == rs->max_mcs)
204 		return rs->max_mcs;
205 
206 	next = ni->ni_txmcs;
207 	for (i = 0; i < rs->nrates; i++) {
208 		if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)
209 			continue;
210 		if (i + rs->min_mcs > ni->ni_txmcs) {
211 			next = i + rs->min_mcs;
212 			break;
213 		}
214 	}
215 
216 	return next;
217 }
218 
219 const struct ieee80211_ht_rateset *
220 ieee80211_ra_next_rateset(struct ieee80211_ra_node *rn,
221     struct ieee80211_node *ni)
222 {
223 	const struct ieee80211_ht_rateset *rs, *rsnext;
224 	int next;
225 	int chan40 = ieee80211_node_supports_ht_chan40(ni);
226 	int sgi = ieee80211_ra_use_ht_sgi(ni);
227 	int mcs = ni->ni_txmcs;
228 
229 	rs = ieee80211_ra_get_ht_rateset(mcs, chan40, sgi);
230 	if (rn->probing & IEEE80211_RA_PROBING_UP) {
231 		if (rs->max_mcs == 7) {	/* MCS 0-7 */
232 			if (chan40)
233 				next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI40 :
234 				    IEEE80211_HT_RATESET_MIMO2_40;
235 			else
236 				next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
237 				    IEEE80211_HT_RATESET_MIMO2;
238 		} else if (rs->max_mcs == 15) {	/* MCS 8-15 */
239 			if (chan40)
240 				next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI40 :
241 				    IEEE80211_HT_RATESET_MIMO3_40;
242 			else
243 				next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
244 				    IEEE80211_HT_RATESET_MIMO3;
245 		} else if (rs->max_mcs == 23) {	/* MCS 16-23 */
246 			if (chan40)
247 				next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI40 :
248 				    IEEE80211_HT_RATESET_MIMO4_40;
249 			else
250 				next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI :
251 				    IEEE80211_HT_RATESET_MIMO4;
252 		} else				/* MCS 24-31 */
253 			return NULL;
254 	} else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
255 		if (rs->min_mcs == 24) {	/* MCS 24-31 */
256 			if (chan40)
257 				next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI40 :
258 				    IEEE80211_HT_RATESET_MIMO3_40;
259 			else
260 				next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
261 				    IEEE80211_HT_RATESET_MIMO3;
262 		} else if (rs->min_mcs == 16) {	/* MCS 16-23 */
263 			if (chan40)
264 				next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI40 :
265 				    IEEE80211_HT_RATESET_MIMO2_40;
266 			else
267 				next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
268 				    IEEE80211_HT_RATESET_MIMO2;
269 		} else if (rs->min_mcs == 8) {	/* MCS 8-15 */
270 			if (chan40)
271 				next = sgi ? IEEE80211_HT_RATESET_SISO_SGI40 :
272 				    IEEE80211_HT_RATESET_SISO_40;
273 			else
274 				next = sgi ? IEEE80211_HT_RATESET_SISO_SGI :
275 				    IEEE80211_HT_RATESET_SISO;
276 		} else				/* MCS 0-7 */
277 			return NULL;
278 	} else
279 		panic("%s: invalid probing mode %d", __func__, rn->probing);
280 
281 	rsnext = &ieee80211_std_ratesets_11n[next];
282 	if ((rsnext->mcs_mask & rn->valid_rates) == 0)
283 		return NULL;
284 
285 	return rsnext;
286 }
287 
288 int
289 ieee80211_ra_best_mcs_in_rateset(struct ieee80211_ra_node *rn,
290     const struct ieee80211_ht_rateset *rs)
291 {
292 	uint64_t gmax = 0;
293 	int i, best_mcs = rs->min_mcs;
294 
295 	for (i = 0; i < rs->nrates; i++) {
296 		int mcs = rs->min_mcs + i;
297 		struct ieee80211_ra_goodput_stats *g = &rn->g[mcs];
298 		if (((1 << mcs) & rn->valid_rates) == 0)
299 			continue;
300 		if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {
301 			gmax = g->measured;
302 			best_mcs = mcs;
303 		}
304 	}
305 
306 	return best_mcs;
307 }
308 
309 void
310 ieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *rn,
311     struct ieee80211_node *ni, const struct ieee80211_ht_rateset *rsnext)
312 {
313 	const struct ieee80211_ht_rateset *rs;
314 	struct ieee80211_ra_goodput_stats *g;
315 	int best_mcs, i;
316 
317 	/* Find most recently measured best MCS from the current rateset. */
318 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
319 	    ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
320 	best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);
321 
322 	/* Switch to the next rateset. */
323 	ni->ni_txmcs = rsnext->min_mcs;
324 	if ((rn->valid_rates & (1 << rsnext->min_mcs)) == 0)
325 		ni->ni_txmcs = ieee80211_ra_next_intra_rate(rn, ni);
326 
327 	/* Select the lowest rate from the next rateset with loss-free
328 	 * goodput close to the current best measurement. */
329 	g = &rn->g[best_mcs];
330 	for (i = 0; i < rsnext->nrates; i++) {
331 		int mcs = rsnext->min_mcs + i;
332 		uint64_t txrate = rsnext->rates[i];
333 
334 		if ((rn->valid_rates & (1 << mcs)) == 0)
335 			continue;
336 
337 		txrate = txrate * 500; /* convert to kbit/s */
338 		txrate <<= RA_FP_SHIFT; /* convert to fixed-point */
339 		txrate /= 1000; /* convert to mbit/s */
340 
341 		if (txrate > g->measured + IEEE80211_RA_RATE_THRESHOLD) {
342 			ni->ni_txmcs = mcs;
343 			break;
344 		}
345 	}
346 	/* If all rates are lower the maximum rate is the closest match. */
347 	if (i == rsnext->nrates)
348 		ni->ni_txmcs = rsnext->max_mcs;
349 
350 	/* Add rates from the next rateset as candidates. */
351 	rn->candidate_rates |= (1 << ni->ni_txmcs);
352 	if (rn->probing & IEEE80211_RA_PROBING_UP) {
353 		rn->candidate_rates |=
354 		  (1 << ieee80211_ra_next_intra_rate(rn, ni));
355 	} else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
356 		rn->candidate_rates |=
357 		    (1 << ieee80211_ra_next_lower_intra_rate(rn, ni));
358 	} else
359 		panic("%s: invalid probing mode %d", __func__, rn->probing);
360 }
361 
362 int
363 ieee80211_ra_next_mcs(struct ieee80211_ra_node *rn,
364     struct ieee80211_node *ni)
365 {
366 	int next;
367 
368 	if (rn->probing & IEEE80211_RA_PROBING_DOWN)
369 		next = ieee80211_ra_next_lower_intra_rate(rn, ni);
370 	else if (rn->probing & IEEE80211_RA_PROBING_UP)
371 		next = ieee80211_ra_next_intra_rate(rn, ni);
372 	else
373 		panic("%s: invalid probing mode %d", __func__, rn->probing);
374 
375 	return next;
376 }
377 
378 void
379 ieee80211_ra_probe_clear(struct ieee80211_ra_node *rn,
380     struct ieee80211_node *ni)
381 {
382 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
383 
384 	g->nprobe_pkts = 0;
385 	g->nprobe_fail = 0;
386 }
387 
388 void
389 ieee80211_ra_probe_done(struct ieee80211_ra_node *rn)
390 {
391 	rn->probing = IEEE80211_RA_NOT_PROBING;
392 	rn->probed_rates = 0;
393 	rn->valid_probes = 0;
394 	rn->candidate_rates = 0;
395 }
396 
397 int
398 ieee80211_ra_intra_mode_ra_finished(struct ieee80211_ra_node *rn,
399     struct ieee80211_node *ni)
400 {
401 	const struct ieee80211_ht_rateset *rs;
402 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
403 	int next_mcs, best_mcs;
404 	uint64_t next_rate;
405 	int chan40 = ieee80211_node_supports_ht_chan40(ni);
406 	int sgi = ieee80211_ra_use_ht_sgi(ni);
407 
408 	rn->probed_rates = (rn->probed_rates | (1 << ni->ni_txmcs));
409 
410 	/* Check if the min/max MCS in this rateset has been probed. */
411 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, chan40, sgi);
412 	if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
413 		if (ni->ni_txmcs == rs->min_mcs ||
414 		    rn->probed_rates & (1 << rs->min_mcs)) {
415 			ieee80211_ra_trigger_next_rateset(rn, ni);
416 			return 1;
417 		}
418 	} else if (rn->probing & IEEE80211_RA_PROBING_UP) {
419 		if (ni->ni_txmcs == rs->max_mcs ||
420 		    rn->probed_rates & (1 << rs->max_mcs)) {
421 			ieee80211_ra_trigger_next_rateset(rn, ni);
422 			return 1;
423 		}
424 	}
425 
426 	/*
427 	 * Check if the measured goodput is loss-free and better than the
428 	 * loss-free goodput of the candidate rate.
429 	 */
430 	next_mcs = ieee80211_ra_next_mcs(rn, ni);
431 	if (next_mcs == ni->ni_txmcs) {
432 		ieee80211_ra_trigger_next_rateset(rn, ni);
433 		return 1;
434 	}
435 	next_rate = ieee80211_ra_get_txrate(next_mcs, chan40, sgi);
436 	if (g->loss == 0 &&
437 	    g->measured >= next_rate + IEEE80211_RA_RATE_THRESHOLD) {
438 		ieee80211_ra_trigger_next_rateset(rn, ni);
439 		return 1;
440 	}
441 
442 	/* Check if we had a better measurement at a previously probed MCS. */
443 	best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);
444 	if (best_mcs != ni->ni_txmcs && (rn->probed_rates & (1 << best_mcs))) {
445 		if ((rn->probing & IEEE80211_RA_PROBING_UP) &&
446 		    best_mcs < ni->ni_txmcs) {
447 			ieee80211_ra_trigger_next_rateset(rn, ni);
448 			return 1;
449 		}
450 		if ((rn->probing & IEEE80211_RA_PROBING_DOWN) &&
451 		    best_mcs > ni->ni_txmcs) {
452 			ieee80211_ra_trigger_next_rateset(rn, ni);
453 			return 1;
454 		}
455 	}
456 
457 	/* Check if all rates in the set of candidate rates have been probed. */
458 	if ((rn->candidate_rates & rn->probed_rates) == rn->candidate_rates) {
459 		/* Remain in the current rateset until above checks trigger. */
460 		rn->probing &= ~IEEE80211_RA_PROBING_INTER;
461 		return 1;
462 	}
463 
464 	return 0;
465 }
466 
467 void
468 ieee80211_ra_trigger_next_rateset(struct ieee80211_ra_node *rn,
469     struct ieee80211_node *ni)
470 {
471 	const struct ieee80211_ht_rateset *rsnext;
472 
473 	rsnext = ieee80211_ra_next_rateset(rn, ni);
474 	if (rsnext) {
475 		ieee80211_ra_probe_next_rateset(rn, ni, rsnext);
476 		rn->probing |= IEEE80211_RA_PROBING_INTER;
477 	} else
478 		rn->probing &= ~IEEE80211_RA_PROBING_INTER;
479 }
480 
481 int
482 ieee80211_ra_inter_mode_ra_finished(struct ieee80211_ra_node *rn,
483     struct ieee80211_node *ni)
484 {
485 	return ((rn->probing & IEEE80211_RA_PROBING_INTER) == 0);
486 }
487 
488 int
489 ieee80211_ra_best_rate(struct ieee80211_ra_node *rn,
490     struct ieee80211_node *ni)
491 {
492 	int i, best = rn->best_mcs;
493 	uint64_t gmax = rn->g[rn->best_mcs].measured;
494 
495 	for (i = 0; i < nitems(rn->g); i++) {
496 		struct ieee80211_ra_goodput_stats *g = &rn->g[i];
497 		if (((1 << i) & rn->valid_rates) == 0)
498 			continue;
499 		if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {
500 			gmax = g->measured;
501 			best = i;
502 		}
503 	}
504 
505 #ifdef RA_DEBUG
506 	if (rn->best_mcs != best) {
507 		DPRINTF(("MCS %d is best; MCS{cur|avg|loss}:", best));
508 		for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
509 			struct ieee80211_ra_goodput_stats *g = &rn->g[i];
510 			if ((rn->valid_rates & (1 << i)) == 0)
511 				continue;
512 			DPRINTF((" %d{%s|", i, ra_fp_sprintf(g->measured)));
513 			DPRINTF(("%s|", ra_fp_sprintf(g->average)));
514 			DPRINTF(("%s%%}", ra_fp_sprintf(g->loss)));
515 		}
516 		DPRINTF(("\n"));
517 	}
518 #endif
519 	return best;
520 }
521 
522 void
523 ieee80211_ra_probe_next_rate(struct ieee80211_ra_node *rn,
524     struct ieee80211_node *ni)
525 {
526 	/* Select the next rate to probe. */
527 	rn->probed_rates |= (1 << ni->ni_txmcs);
528 	ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
529 }
530 
531 int
532 ieee80211_ra_valid_tx_mcs(struct ieee80211com *ic, int mcs)
533 {
534 	uint32_t ntxstreams = 1;
535 	static const int max_mcs[] = { 7, 15, 23, 31 };
536 
537 	if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0)
538 		return isset(ic->ic_sup_mcs, mcs);
539 
540 	ntxstreams += ((ic->ic_tx_mcs_set & IEEE80211_TX_SPATIAL_STREAMS) >> 2);
541 	if (ntxstreams < 1 || ntxstreams > 4)
542 		panic("invalid number of Tx streams: %u", ntxstreams);
543 	return (mcs <= max_mcs[ntxstreams - 1] && isset(ic->ic_sup_mcs, mcs));
544 }
545 
546 uint32_t
547 ieee80211_ra_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)
548 {
549 	uint32_t valid_mcs = 0;
550 	int i;
551 
552 	for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
553 		if (!isset(ni->ni_rxmcs, i))
554 			continue;
555 		if (!ieee80211_ra_valid_tx_mcs(ic, i))
556 			continue;
557 		valid_mcs |= (1 << i);
558 	}
559 
560 	return valid_mcs;
561 }
562 
563 int
564 ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *g)
565 {
566 	/* 128 packets make up a valid probe in any case. */
567 	if (g->nprobe_pkts >= 128)
568 		return 1;
569 
570 	/* 8 packets with > 75% loss make a valid probe, too. */
571 	if (g->nprobe_pkts >= 8 &&
572 	    g->nprobe_pkts - g->nprobe_fail < g->nprobe_pkts / 4)
573 		return 1;
574 
575 	return 0;
576 }
577 
578 void
579 ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,
580     struct ieee80211com *ic, struct ieee80211_node *ni,
581     int mcs, uint32_t total, uint32_t fail)
582 {
583 	static const uint64_t alpha = RA_FP_1 / 8; /* 1/8 = 0.125 */
584 	static const uint64_t beta =  RA_FP_1 / 4; /* 1/4 = 0.25 */
585 	int s;
586 	struct ieee80211_ra_goodput_stats *g;
587 	uint64_t sfer, rate, delta;
588 
589 	/*
590 	 * Ignore invalid values. These values may come from hardware
591 	 * so asserting valid values via panic is not appropriate.
592 	 */
593 	if (mcs < 0 || mcs >= IEEE80211_HT_RATESET_NUM_MCS)
594 		return;
595 	if (total == 0)
596 		return;
597 
598 	s = splnet();
599 
600 	g = &rn->g[mcs];
601 	g->nprobe_pkts += total;
602 	g->nprobe_fail += fail;
603 
604 	if (!ieee80211_ra_probe_valid(g)) {
605 		splx(s);
606 		return;
607 	}
608 	rn->valid_probes |= 1U << mcs;
609 
610 	if (g->nprobe_fail > g->nprobe_pkts) {
611 		DPRINTF(("%s fail %u > pkts %u\n",
612 		    ether_sprintf(ni->ni_macaddr),
613 		    g->nprobe_fail, g->nprobe_pkts));
614 		g->nprobe_fail = g->nprobe_pkts;
615 	}
616 
617 	sfer = g->nprobe_fail << RA_FP_SHIFT;
618 	sfer /= g->nprobe_pkts;
619 	g->nprobe_fail = 0;
620 	g->nprobe_pkts = 0;
621 
622 	rate = ieee80211_ra_get_txrate(mcs,
623 	    ieee80211_node_supports_ht_chan40(ni),
624 	    ieee80211_ra_use_ht_sgi(ni));
625 
626 	g->loss = sfer * 100;
627 	g->measured = RA_FP_MUL(RA_FP_1 - sfer, rate);
628 	g->average = RA_FP_MUL(RA_FP_1 - alpha, g->average);
629 	g->average += RA_FP_MUL(alpha, g->measured);
630 
631 	g->stddeviation = RA_FP_MUL(RA_FP_1 - beta, g->stddeviation);
632 	if (g->average > g->measured)
633 		delta = g->average - g->measured;
634 	else
635 		delta = g->measured - g->average;
636 	g->stddeviation += RA_FP_MUL(beta, delta);
637 
638 	splx(s);
639 }
640 
641 void
642 ieee80211_ra_choose(struct ieee80211_ra_node *rn, struct ieee80211com *ic,
643     struct ieee80211_node *ni)
644 {
645 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
646 	int s;
647 	int chan40 = ieee80211_node_supports_ht_chan40(ni);
648 	int sgi = ieee80211_ra_use_ht_sgi(ni);
649 	const struct ieee80211_ht_rateset *rs, *rsnext;
650 
651 	s = splnet();
652 
653 	if (rn->valid_rates == 0)
654 		rn->valid_rates = ieee80211_ra_valid_rates(ic, ni);
655 
656 	if (rn->probing) {
657 		/* Probe another rate or settle at the best rate. */
658 		if (!(rn->valid_probes & (1UL << ni->ni_txmcs))) {
659 			splx(s);
660 			return;
661 		}
662 		ieee80211_ra_probe_clear(rn, ni);
663 		if (!ieee80211_ra_intra_mode_ra_finished(rn, ni)) {
664 			ieee80211_ra_probe_next_rate(rn, ni);
665 			DPRINTFN(3, ("probing MCS %d\n", ni->ni_txmcs));
666 		} else if (ieee80211_ra_inter_mode_ra_finished(rn, ni)) {
667 			rn->best_mcs = ieee80211_ra_best_rate(rn, ni);
668 			ni->ni_txmcs = rn->best_mcs;
669 			ieee80211_ra_probe_done(rn);
670 		}
671 
672 		splx(s);
673 		return;
674 	} else {
675 		rn->valid_probes = 0;
676 	}
677 
678 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, chan40, sgi);
679 	if ((g->measured >> RA_FP_SHIFT) == 0LL ||
680 	    (g->average >= 3 * g->stddeviation &&
681 	    g->measured < g->average - 3 * g->stddeviation)) {
682 		/* Channel becomes bad. Probe downwards. */
683 		rn->probing = IEEE80211_RA_PROBING_DOWN;
684 		rn->probed_rates = 0;
685 		if (ni->ni_txmcs == rs->min_mcs) {
686 			rsnext = ieee80211_ra_next_rateset(rn, ni);
687 			if (rsnext) {
688 				ieee80211_ra_probe_next_rateset(rn, ni,
689 				    rsnext);
690 			} else {
691 				/* Cannot probe further down. */
692 				rn->probing = IEEE80211_RA_NOT_PROBING;
693 			}
694 		} else {
695 			ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
696 			rn->candidate_rates = (1 << ni->ni_txmcs);
697 		}
698 	} else if (g->loss < 2 * RA_FP_1 ||
699 	    g->measured > g->average + 3 * g->stddeviation) {
700 		/* Channel becomes good. */
701 		rn->probing = IEEE80211_RA_PROBING_UP;
702 		rn->probed_rates = 0;
703 		if (ni->ni_txmcs == rs->max_mcs) {
704 			rsnext = ieee80211_ra_next_rateset(rn, ni);
705 			if (rsnext) {
706 				ieee80211_ra_probe_next_rateset(rn, ni,
707 				    rsnext);
708 			} else {
709 				/* Cannot probe further up. */
710 				rn->probing = IEEE80211_RA_NOT_PROBING;
711 			}
712 		} else {
713 			ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
714 			rn->candidate_rates = (1 << ni->ni_txmcs);
715 		}
716 	} else {
717 		/* Remain at current rate. */
718 		rn->probing = IEEE80211_RA_NOT_PROBING;
719 		rn->probed_rates = 0;
720 		rn->candidate_rates = 0;
721 	}
722 
723 	splx(s);
724 
725 	if (rn->probing) {
726 		if (rn->probing & IEEE80211_RA_PROBING_UP)
727 			DPRINTFN(2, ("channel becomes good; probe up\n"));
728 		else
729 			DPRINTFN(2, ("channel becomes bad; probe down\n"));
730 
731 		DPRINTFN(3, ("measured: %s Mbit/s\n",
732 		    ra_fp_sprintf(g->measured)));
733 		DPRINTFN(3, ("average: %s Mbit/s\n",
734 		    ra_fp_sprintf(g->average)));
735 		DPRINTFN(3, ("stddeviation: %s\n",
736 		    ra_fp_sprintf(g->stddeviation)));
737 		DPRINTFN(3, ("loss: %s%%\n", ra_fp_sprintf(g->loss)));
738 	}
739 }
740 
741 void
742 ieee80211_ra_node_init(struct ieee80211_ra_node *rn)
743 {
744 	memset(rn, 0, sizeof(*rn));
745 }
746