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