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