xref: /openbsd-src/sys/net80211/ieee80211_ra.c (revision f1dd7b858388b4a23f4f67a4957ec5ff656ebbe8)
1 /*	$OpenBSD: ieee80211_ra.c,v 1.3 2021/05/03 08:46:28 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 sgi20)
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 (sgi20 != rs->sgi)
123 			continue;
124 		if (mcs >= rs->min_mcs && mcs <= rs->max_mcs)
125 			return rs;
126 	}
127 
128 	panic("MCS %d is not part of any rateset", mcs);
129 }
130 
131 /*
132  * Update goodput statistics.
133  */
134 
135 uint64_t
136 ieee80211_ra_get_txrate(int mcs, int sgi20)
137 {
138 	const struct ieee80211_ht_rateset *rs;
139 	uint64_t txrate;
140 
141 	rs = ieee80211_ra_get_ht_rateset(mcs, sgi20);
142 	txrate = rs->rates[mcs - rs->min_mcs];
143 	txrate <<= RA_FP_SHIFT; /* convert to fixed-point */
144 	txrate *= 500; /* convert to kbit/s */
145 	txrate /= 1000; /* convert to mbit/s */
146 
147 	return txrate;
148 }
149 
150 /*
151  * Rate selection.
152  */
153 
154 /* A rate's goodput has to be at least this much larger to be "better". */
155 #define IEEE80211_RA_RATE_THRESHOLD	(RA_FP_1 / 64) /* ~ 0.015 */
156 
157 int
158 ieee80211_ra_next_lower_intra_rate(struct ieee80211_ra_node *rn,
159     struct ieee80211_node *ni)
160 {
161 	const struct ieee80211_ht_rateset *rs;
162 	int i, next;
163 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
164 
165 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
166 	if (ni->ni_txmcs == rs->min_mcs)
167 		return rs->min_mcs;
168 
169 	next = ni->ni_txmcs;
170 	for (i = rs->nrates - 1; i >= 0; i--) {
171 		if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)
172 			continue;
173 		if (i + rs->min_mcs < ni->ni_txmcs) {
174 			next = i + rs->min_mcs;
175 			break;
176 		}
177 	}
178 
179 	return next;
180 }
181 
182 int
183 ieee80211_ra_next_intra_rate(struct ieee80211_ra_node *rn,
184     struct ieee80211_node *ni)
185 {
186 	const struct ieee80211_ht_rateset *rs;
187 	int i, next;
188 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
189 
190 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
191 	if (ni->ni_txmcs == rs->max_mcs)
192 		return rs->max_mcs;
193 
194 	next = ni->ni_txmcs;
195 	for (i = 0; i < rs->nrates; i++) {
196 		if ((rn->valid_rates & (1 << (i + rs->min_mcs))) == 0)
197 			continue;
198 		if (i + rs->min_mcs > ni->ni_txmcs) {
199 			next = i + rs->min_mcs;
200 			break;
201 		}
202 	}
203 
204 	return next;
205 }
206 
207 const struct ieee80211_ht_rateset *
208 ieee80211_ra_next_rateset(struct ieee80211_ra_node *rn,
209     struct ieee80211_node *ni)
210 {
211 	const struct ieee80211_ht_rateset *rs, *rsnext;
212 	int next;
213 	int mcs = ni->ni_txmcs;
214 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
215 
216 	rs = ieee80211_ra_get_ht_rateset(mcs, sgi20);
217 	if (rn->probing & IEEE80211_RA_PROBING_UP) {
218 		if (rs->max_mcs == 7)	/* MCS 0-7 */
219 			next = sgi20 ? IEEE80211_HT_RATESET_MIMO2_SGI :
220 			    IEEE80211_HT_RATESET_MIMO2;
221 		else if (rs->max_mcs == 15)	/* MCS 8-15 */
222 			next = sgi20 ? IEEE80211_HT_RATESET_MIMO3_SGI :
223 			    IEEE80211_HT_RATESET_MIMO3;
224 		else if (rs->max_mcs == 23)	/* MCS 16-23 */
225 			next = sgi20 ? IEEE80211_HT_RATESET_MIMO4_SGI :
226 			    IEEE80211_HT_RATESET_MIMO4;
227 		else				/* MCS 24-31 */
228 			return NULL;
229 	} else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
230 		if (rs->min_mcs == 24)	/* MCS 24-31 */
231 			next = sgi20 ? IEEE80211_HT_RATESET_MIMO3_SGI :
232 			    IEEE80211_HT_RATESET_MIMO3;
233 		else if (rs->min_mcs == 16)	/* MCS 16-23 */
234 			next = sgi20 ? IEEE80211_HT_RATESET_MIMO2_SGI :
235 			    IEEE80211_HT_RATESET_MIMO2;
236 		else if (rs->min_mcs == 8)	/* MCS 8-15 */
237 			next = sgi20 ? IEEE80211_HT_RATESET_SISO_SGI :
238 			    IEEE80211_HT_RATESET_SISO;
239 		else				/* MCS 0-7 */
240 			return NULL;
241 	} else
242 		panic("%s: invalid probing mode %d", __func__, rn->probing);
243 
244 	rsnext = &ieee80211_std_ratesets_11n[next];
245 	if ((rsnext->mcs_mask & rn->valid_rates) == 0)
246 		return NULL;
247 
248 	return rsnext;
249 }
250 
251 int
252 ieee80211_ra_best_mcs_in_rateset(struct ieee80211_ra_node *rn,
253     const struct ieee80211_ht_rateset *rs)
254 {
255 	uint64_t gmax = 0;
256 	int i, best_mcs = rs->min_mcs;
257 
258 	for (i = 0; i < rs->nrates; i++) {
259 		int mcs = rs->min_mcs + i;
260 		struct ieee80211_ra_goodput_stats *g = &rn->g[mcs];
261 		if (((1 << mcs) & rn->valid_rates) == 0)
262 			continue;
263 		if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {
264 			gmax = g->measured;
265 			best_mcs = mcs;
266 		}
267 	}
268 
269 	return best_mcs;
270 }
271 
272 void
273 ieee80211_ra_probe_next_rateset(struct ieee80211_ra_node *rn,
274     struct ieee80211_node *ni, const struct ieee80211_ht_rateset *rsnext)
275 {
276 	const struct ieee80211_ht_rateset *rs;
277 	struct ieee80211_ra_goodput_stats *g;
278 	int best_mcs, i;
279 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
280 
281 	/* Find most recently measured best MCS from the current rateset. */
282 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
283 	best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);
284 
285 	/* Switch to the next rateset. */
286 	ni->ni_txmcs = rsnext->min_mcs;
287 	if ((rn->valid_rates & (1 << rsnext->min_mcs)) == 0)
288 		ni->ni_txmcs = ieee80211_ra_next_intra_rate(rn, ni);
289 
290 	/* Select the lowest rate from the next rateset with loss-free
291 	 * goodput close to the current best measurement. */
292 	g = &rn->g[best_mcs];
293 	for (i = 0; i < rsnext->nrates; i++) {
294 		int mcs = rsnext->min_mcs + i;
295 		uint64_t txrate = rsnext->rates[i];
296 
297 		if ((rn->valid_rates & (1 << mcs)) == 0)
298 			continue;
299 
300 		txrate = txrate * 500; /* convert to kbit/s */
301 		txrate <<= RA_FP_SHIFT; /* convert to fixed-point */
302 		txrate /= 1000; /* convert to mbit/s */
303 
304 		if (txrate > g->measured + IEEE80211_RA_RATE_THRESHOLD) {
305 			ni->ni_txmcs = mcs;
306 			break;
307 		}
308 	}
309 	/* If all rates are lower the maximum rate is the closest match. */
310 	if (i == rsnext->nrates)
311 		ni->ni_txmcs = rsnext->max_mcs;
312 
313 	/* Add rates from the next rateset as candidates. */
314 	rn->candidate_rates |= (1 << ni->ni_txmcs);
315 	if (rn->probing & IEEE80211_RA_PROBING_UP) {
316 		rn->candidate_rates |=
317 		  (1 << ieee80211_ra_next_intra_rate(rn, ni));
318 	} else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
319 		rn->candidate_rates |=
320 		    (1 << ieee80211_ra_next_lower_intra_rate(rn, ni));
321 	} else
322 		panic("%s: invalid probing mode %d", __func__, rn->probing);
323 }
324 
325 int
326 ieee80211_ra_next_mcs(struct ieee80211_ra_node *rn,
327     struct ieee80211_node *ni)
328 {
329 	int next;
330 
331 	if (rn->probing & IEEE80211_RA_PROBING_DOWN)
332 		next = ieee80211_ra_next_lower_intra_rate(rn, ni);
333 	else if (rn->probing & IEEE80211_RA_PROBING_UP)
334 		next = ieee80211_ra_next_intra_rate(rn, ni);
335 	else
336 		panic("%s: invalid probing mode %d", __func__, rn->probing);
337 
338 	return next;
339 }
340 
341 void
342 ieee80211_ra_probe_clear(struct ieee80211_ra_node *rn,
343     struct ieee80211_node *ni)
344 {
345 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
346 
347 	g->nprobe_pkts = 0;
348 	g->nprobe_fail = 0;
349 }
350 
351 void
352 ieee80211_ra_probe_done(struct ieee80211_ra_node *rn)
353 {
354 	rn->probing = IEEE80211_RA_NOT_PROBING;
355 	rn->probed_rates = 0;
356 	rn->valid_probes = 0;
357 	rn->candidate_rates = 0;
358 }
359 
360 int
361 ieee80211_ra_intra_mode_ra_finished(struct ieee80211_ra_node *rn,
362     struct ieee80211_node *ni)
363 {
364 	const struct ieee80211_ht_rateset *rs;
365 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
366 	int next_mcs, best_mcs;
367 	uint64_t next_rate;
368 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
369 
370 	rn->probed_rates = (rn->probed_rates | (1 << ni->ni_txmcs));
371 
372 	/* Check if the min/max MCS in this rateset has been probed. */
373 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
374 	if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
375 		if (ni->ni_txmcs == rs->min_mcs ||
376 		    rn->probed_rates & (1 << rs->min_mcs)) {
377 			ieee80211_ra_trigger_next_rateset(rn, ni);
378 			return 1;
379 		}
380 	} else if (rn->probing & IEEE80211_RA_PROBING_UP) {
381 		if (ni->ni_txmcs == rs->max_mcs ||
382 		    rn->probed_rates & (1 << rs->max_mcs)) {
383 			ieee80211_ra_trigger_next_rateset(rn, ni);
384 			return 1;
385 		}
386 	}
387 
388 	/*
389 	 * Check if the measured goodput is loss-free and better than the
390 	 * loss-free goodput of the candidate rate.
391 	 */
392 	next_mcs = ieee80211_ra_next_mcs(rn, ni);
393 	if (next_mcs == ni->ni_txmcs) {
394 		ieee80211_ra_trigger_next_rateset(rn, ni);
395 		return 1;
396 	}
397 	next_rate = ieee80211_ra_get_txrate(next_mcs, sgi20);
398 	if (g->loss == 0 &&
399 	    g->measured >= next_rate + IEEE80211_RA_RATE_THRESHOLD) {
400 		ieee80211_ra_trigger_next_rateset(rn, ni);
401 		return 1;
402 	}
403 
404 	/* Check if we had a better measurement at a previously probed MCS. */
405 	best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);
406 	if (best_mcs != ni->ni_txmcs && (rn->probed_rates & (1 << best_mcs))) {
407 		if ((rn->probing & IEEE80211_RA_PROBING_UP) &&
408 		    best_mcs < ni->ni_txmcs) {
409 			ieee80211_ra_trigger_next_rateset(rn, ni);
410 			return 1;
411 		}
412 		if ((rn->probing & IEEE80211_RA_PROBING_DOWN) &&
413 		    best_mcs > ni->ni_txmcs) {
414 			ieee80211_ra_trigger_next_rateset(rn, ni);
415 			return 1;
416 		}
417 	}
418 
419 	/* Check if all rates in the set of candidate rates have been probed. */
420 	if ((rn->candidate_rates & rn->probed_rates) == rn->candidate_rates) {
421 		/* Remain in the current rateset until above checks trigger. */
422 		rn->probing &= ~IEEE80211_RA_PROBING_INTER;
423 		return 1;
424 	}
425 
426 	return 0;
427 }
428 
429 void
430 ieee80211_ra_trigger_next_rateset(struct ieee80211_ra_node *rn,
431     struct ieee80211_node *ni)
432 {
433 	const struct ieee80211_ht_rateset *rsnext;
434 
435 	rsnext = ieee80211_ra_next_rateset(rn, ni);
436 	if (rsnext) {
437 		ieee80211_ra_probe_next_rateset(rn, ni, rsnext);
438 		rn->probing |= IEEE80211_RA_PROBING_INTER;
439 	} else
440 		rn->probing &= ~IEEE80211_RA_PROBING_INTER;
441 }
442 
443 int
444 ieee80211_ra_inter_mode_ra_finished(struct ieee80211_ra_node *rn,
445     struct ieee80211_node *ni)
446 {
447 	return ((rn->probing & IEEE80211_RA_PROBING_INTER) == 0);
448 }
449 
450 int
451 ieee80211_ra_best_rate(struct ieee80211_ra_node *rn,
452     struct ieee80211_node *ni)
453 {
454 	int i, best = rn->best_mcs;
455 	uint64_t gmax = rn->g[rn->best_mcs].measured;
456 
457 	for (i = 0; i < nitems(rn->g); i++) {
458 		struct ieee80211_ra_goodput_stats *g = &rn->g[i];
459 		if (((1 << i) & rn->valid_rates) == 0)
460 			continue;
461 		if (g->measured > gmax + IEEE80211_RA_RATE_THRESHOLD) {
462 			gmax = g->measured;
463 			best = i;
464 		}
465 	}
466 
467 #ifdef RA_DEBUG
468 	if (rn->best_mcs != best) {
469 		DPRINTF(("MCS %d is best; MCS{cur|avg|loss}:", best));
470 		for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
471 			struct ieee80211_ra_goodput_stats *g = &rn->g[i];
472 			if ((rn->valid_rates & (1 << i)) == 0)
473 				continue;
474 			DPRINTF((" %d{%s|", i, ra_fp_sprintf(g->measured)));
475 			DPRINTF(("%s|", ra_fp_sprintf(g->average)));
476 			DPRINTF(("%s%%}", ra_fp_sprintf(g->loss)));
477 		}
478 		DPRINTF(("\n"));
479 	}
480 #endif
481 	return best;
482 }
483 
484 void
485 ieee80211_ra_probe_next_rate(struct ieee80211_ra_node *rn,
486     struct ieee80211_node *ni)
487 {
488 	/* Select the next rate to probe. */
489 	rn->probed_rates |= (1 << ni->ni_txmcs);
490 	ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
491 }
492 
493 int
494 ieee80211_ra_valid_tx_mcs(struct ieee80211com *ic, int mcs)
495 {
496 	uint32_t ntxstreams = 1;
497 	static const int max_mcs[] = { 7, 15, 23, 31 };
498 
499 	if ((ic->ic_tx_mcs_set & IEEE80211_TX_RX_MCS_NOT_EQUAL) == 0)
500 		return isset(ic->ic_sup_mcs, mcs);
501 
502 	ntxstreams += ((ic->ic_tx_mcs_set & IEEE80211_TX_SPATIAL_STREAMS) >> 2);
503 	if (ntxstreams < 1 || ntxstreams > 4)
504 		panic("invalid number of Tx streams: %u", ntxstreams);
505 	return (mcs <= max_mcs[ntxstreams - 1] && isset(ic->ic_sup_mcs, mcs));
506 }
507 
508 uint32_t
509 ieee80211_ra_valid_rates(struct ieee80211com *ic, struct ieee80211_node *ni)
510 {
511 	uint32_t valid_mcs = 0;
512 	int i;
513 
514 	for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
515 		if (!isset(ni->ni_rxmcs, i))
516 			continue;
517 		if (!ieee80211_ra_valid_tx_mcs(ic, i))
518 			continue;
519 		valid_mcs |= (1 << i);
520 	}
521 
522 	return valid_mcs;
523 }
524 
525 int
526 ieee80211_ra_probe_valid(struct ieee80211_ra_goodput_stats *g)
527 {
528 	/* 128 packets make up a valid probe in any case. */
529 	if (g->nprobe_pkts >= 128)
530 		return 1;
531 
532 	/* 8 packets with > 75% loss make a valid probe, too. */
533 	if (g->nprobe_pkts >= 8 &&
534 	    g->nprobe_pkts - g->nprobe_fail < g->nprobe_pkts / 4)
535 		return 1;
536 
537 	return 0;
538 }
539 
540 void
541 ieee80211_ra_add_stats_ht(struct ieee80211_ra_node *rn,
542     struct ieee80211com *ic, struct ieee80211_node *ni,
543     int mcs, uint32_t total, uint32_t fail)
544 {
545 	static const uint64_t alpha = RA_FP_1 / 8; /* 1/8 = 0.125 */
546 	static const uint64_t beta =  RA_FP_1 / 4; /* 1/4 = 0.25 */
547 	int s, sgi20;
548 	struct ieee80211_ra_goodput_stats *g;
549 	uint64_t sfer, rate, delta;
550 
551 	/*
552 	 * Ignore invalid values. These values may come from hardware
553 	 * so asserting valid values via panic is not appropriate.
554 	 */
555 	if (mcs < 0 || mcs >= IEEE80211_HT_RATESET_NUM_MCS)
556 		return;
557 	if (total == 0)
558 		return;
559 
560 	s = splnet();
561 
562 	g = &rn->g[mcs];
563 	g->nprobe_pkts += total;
564 	g->nprobe_fail += fail;
565 
566 	if (!ieee80211_ra_probe_valid(g)) {
567 		splx(s);
568 		return;
569 	}
570 	rn->valid_probes |= 1U << mcs;
571 
572 	if (g->nprobe_fail > g->nprobe_pkts) {
573 		DPRINTF(("%s fail %u > pkts %u\n",
574 		    ether_sprintf(ni->ni_macaddr),
575 		    g->nprobe_fail, g->nprobe_pkts));
576 		g->nprobe_fail = g->nprobe_pkts;
577 	}
578 
579 	sfer = g->nprobe_fail << RA_FP_SHIFT;
580 	sfer /= g->nprobe_pkts;
581 	g->nprobe_fail = 0;
582 	g->nprobe_pkts = 0;
583 
584 	sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
585 	rate = ieee80211_ra_get_txrate(mcs, sgi20);
586 
587 	g->loss = sfer * 100;
588 	g->measured = RA_FP_MUL(RA_FP_1 - sfer, rate);
589 	g->average = RA_FP_MUL(RA_FP_1 - alpha, g->average);
590 	g->average += RA_FP_MUL(alpha, g->measured);
591 
592 	g->stddeviation = RA_FP_MUL(RA_FP_1 - beta, g->stddeviation);
593 	if (g->average > g->measured)
594 		delta = g->average - g->measured;
595 	else
596 		delta = g->measured - g->average;
597 	g->stddeviation += RA_FP_MUL(beta, delta);
598 
599 	splx(s);
600 }
601 
602 void
603 ieee80211_ra_choose(struct ieee80211_ra_node *rn, struct ieee80211com *ic,
604     struct ieee80211_node *ni)
605 {
606 	struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
607 	int s;
608 	int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
609 	const struct ieee80211_ht_rateset *rs, *rsnext;
610 
611 	s = splnet();
612 
613 	if (rn->valid_rates == 0)
614 		rn->valid_rates = ieee80211_ra_valid_rates(ic, ni);
615 
616 	if (rn->probing) {
617 		/* Probe another rate or settle at the best rate. */
618 		if (!(rn->valid_probes & (1UL << ni->ni_txmcs))) {
619 			splx(s);
620 			return;
621 		}
622 		ieee80211_ra_probe_clear(rn, ni);
623 		if (!ieee80211_ra_intra_mode_ra_finished(rn, ni)) {
624 			ieee80211_ra_probe_next_rate(rn, ni);
625 			DPRINTFN(3, ("probing MCS %d\n", ni->ni_txmcs));
626 		} else if (ieee80211_ra_inter_mode_ra_finished(rn, ni)) {
627 			rn->best_mcs = ieee80211_ra_best_rate(rn, ni);
628 			ni->ni_txmcs = rn->best_mcs;
629 			ieee80211_ra_probe_done(rn);
630 		}
631 
632 		splx(s);
633 		return;
634 	} else {
635 		rn->valid_probes = 0;
636 	}
637 
638 	rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
639 	if ((g->measured >> RA_FP_SHIFT) == 0LL ||
640 	    (g->average >= 3 * g->stddeviation &&
641 	    g->measured < g->average - 3 * g->stddeviation)) {
642 		/* Channel becomes bad. Probe downwards. */
643 		rn->probing = IEEE80211_RA_PROBING_DOWN;
644 		rn->probed_rates = 0;
645 		if (ni->ni_txmcs == rs->min_mcs) {
646 			rsnext = ieee80211_ra_next_rateset(rn, ni);
647 			if (rsnext) {
648 				ieee80211_ra_probe_next_rateset(rn, ni,
649 				    rsnext);
650 			} else {
651 				/* Cannot probe further down. */
652 				rn->probing = IEEE80211_RA_NOT_PROBING;
653 			}
654 		} else {
655 			ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
656 			rn->candidate_rates = (1 << ni->ni_txmcs);
657 		}
658 	} else if (g->loss < 2 * RA_FP_1 ||
659 	    g->measured > g->average + 3 * g->stddeviation) {
660 		/* Channel becomes good. */
661 		rn->probing = IEEE80211_RA_PROBING_UP;
662 		rn->probed_rates = 0;
663 		if (ni->ni_txmcs == rs->max_mcs) {
664 			rsnext = ieee80211_ra_next_rateset(rn, ni);
665 			if (rsnext) {
666 				ieee80211_ra_probe_next_rateset(rn, ni,
667 				    rsnext);
668 			} else {
669 				/* Cannot probe further up. */
670 				rn->probing = IEEE80211_RA_NOT_PROBING;
671 			}
672 		} else {
673 			ni->ni_txmcs = ieee80211_ra_next_mcs(rn, ni);
674 			rn->candidate_rates = (1 << ni->ni_txmcs);
675 		}
676 	} else {
677 		/* Remain at current rate. */
678 		rn->probing = IEEE80211_RA_NOT_PROBING;
679 		rn->probed_rates = 0;
680 		rn->candidate_rates = 0;
681 	}
682 
683 	splx(s);
684 
685 	if (rn->probing) {
686 		if (rn->probing & IEEE80211_RA_PROBING_UP)
687 			DPRINTFN(2, ("channel becomes good; probe up\n"));
688 		else
689 			DPRINTFN(2, ("channel becomes bad; probe down\n"));
690 
691 		DPRINTFN(3, ("measured: %s Mbit/s\n",
692 		    ra_fp_sprintf(g->measured)));
693 		DPRINTFN(3, ("average: %s Mbit/s\n",
694 		    ra_fp_sprintf(g->average)));
695 		DPRINTFN(3, ("stddeviation: %s\n",
696 		    ra_fp_sprintf(g->stddeviation)));
697 		DPRINTFN(3, ("loss: %s%%\n", ra_fp_sprintf(g->loss)));
698 	}
699 }
700 
701 void
702 ieee80211_ra_node_init(struct ieee80211_ra_node *rn)
703 {
704 	memset(rn, 0, sizeof(*rn));
705 }
706