1 /* $NetBSD: athrate-sample.c,v 1.19 2012/11/08 20:43:55 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2005 John Bicket 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 15 * redistribution must be conditioned upon including a substantially 16 * similar Disclaimer requirement for further binary redistribution. 17 * 3. Neither the names of the above-listed copyright holders nor the names 18 * of any contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * Alternatively, this software may be distributed under the terms of the 22 * GNU General Public License ("GPL") version 2 as published by the Free 23 * Software Foundation. 24 * 25 * NO WARRANTY 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 30 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 31 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 34 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 36 * THE POSSIBILITY OF SUCH DAMAGES. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifdef __FreeBSD__ 41 __FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/sample/sample.c,v 1.9 2005/07/22 16:50:17 sam Exp $"); 42 #endif 43 #ifdef __NetBSD__ 44 __KERNEL_RCSID(0, "$NetBSD: athrate-sample.c,v 1.19 2012/11/08 20:43:55 dyoung Exp $"); 45 #endif 46 47 48 /* 49 * John Bicket's SampleRate control algorithm. 50 */ 51 #ifdef _KERNEL_OPT 52 #include "opt_inet.h" 53 #endif 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/sysctl.h> 58 #include <sys/kernel.h> 59 #include <sys/errno.h> 60 #include <sys/device.h> 61 62 #include <sys/bus.h> 63 64 #include <sys/socket.h> 65 66 #include <net/if.h> 67 #include <net/if_media.h> 68 #include <net/if_arp.h> 69 #include <net/if_ether.h> /* XXX for ether_sprintf */ 70 71 #include <net80211/ieee80211_var.h> 72 73 #include <net/bpf.h> 74 75 #ifdef INET 76 #include <netinet/in.h> 77 #endif 78 79 #include "ah_desc.h" 80 #include <dev/ic/athvar.h> 81 #include <dev/ic/athrate-sample.h> 82 83 #define SAMPLE_DEBUG 84 #ifdef SAMPLE_DEBUG 85 enum { 86 ATH_DEBUG_RATE = 0x00000010 /* rate control */ 87 }; 88 #define DPRINTF(sc, _fmt, ...) do { \ 89 if (sc->sc_debug & ATH_DEBUG_RATE) \ 90 printf(_fmt, __VA_ARGS__); \ 91 } while (0) 92 #else 93 #define DPRINTF(sc, _fmt, ...) 94 #endif 95 96 /* 97 * This file is an implementation of the SampleRate algorithm 98 * in "Bit-rate Selection in Wireless Networks" 99 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps) 100 * 101 * SampleRate chooses the bit-rate it predicts will provide the most 102 * throughput based on estimates of the expected per-packet 103 * transmission time for each bit-rate. SampleRate periodically sends 104 * packets at bit-rates other than the current one to estimate when 105 * another bit-rate will provide better performance. SampleRate 106 * switches to another bit-rate when its estimated per-packet 107 * transmission time becomes smaller than the current bit-rate's. 108 * SampleRate reduces the number of bit-rates it must sample by 109 * eliminating those that could not perform better than the one 110 * currently being used. SampleRate also stops probing at a bit-rate 111 * if it experiences several successive losses. 112 * 113 * The difference between the algorithm in the thesis and the one in this 114 * file is that the one in this file uses a ewma instead of a window. 115 * 116 * Also, this implementation tracks the average transmission time for 117 * a few different packet sizes independently for each link. 118 */ 119 120 #define STALE_FAILURE_TIMEOUT_MS 10000 121 #define MIN_SWITCH_MS 1000 122 123 static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *); 124 125 static inline int 126 size_to_bin(int size) 127 { 128 int x = 0; 129 for (x = 0; x < NUM_PACKET_SIZE_BINS; x++) { 130 if (size <= packet_size_bins[x]) { 131 return x; 132 } 133 } 134 return NUM_PACKET_SIZE_BINS-1; 135 } 136 static inline int bin_to_size(int index) { 137 return packet_size_bins[index]; 138 } 139 140 static inline int 141 rate_to_ndx(struct sample_node *sn, int rate) { 142 int x = 0; 143 for (x = 0; x < sn->num_rates; x++) { 144 if (sn->rates[x].rate == rate) { 145 return x; 146 } 147 } 148 return -1; 149 } 150 151 void 152 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) 153 { 154 DPRINTF(sc, "%s:\n", __func__); 155 /* NB: assumed to be zero'd by caller */ 156 } 157 158 void 159 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 160 { 161 DPRINTF(sc, "%s:\n", __func__); 162 } 163 164 165 /* 166 * returns the ndx with the lowest average_tx_time, 167 * or -1 if all the average_tx_times are 0. 168 */ 169 static inline int best_rate_ndx(struct sample_node *sn, int size_bin, 170 int require_acked_before) 171 { 172 int x = 0; 173 int best_ndx = 0; 174 int best_rate_tt = 0; 175 for (x = 0; x < sn->num_rates; x++) { 176 int tt = sn->stats[size_bin][x].average_tx_time; 177 if (tt <= 0 || (require_acked_before && 178 !sn->stats[size_bin][x].packets_acked)) { 179 continue; 180 } 181 182 /* 9 megabits never works better than 12 */ 183 if (sn->rates[x].rate == 18) 184 continue; 185 186 /* don't use a bit-rate that has been failing */ 187 if (sn->stats[size_bin][x].successive_failures > 3) 188 continue; 189 190 if (!best_rate_tt || best_rate_tt > tt) { 191 best_rate_tt = tt; 192 best_ndx = x; 193 } 194 } 195 return (best_rate_tt) ? best_ndx : -1; 196 } 197 198 /* 199 * pick a good "random" bit-rate to sample other than the current one 200 */ 201 static inline int 202 pick_sample_ndx(struct sample_node *sn, int size_bin) 203 { 204 int x = 0; 205 int current_ndx = 0; 206 unsigned current_tt = 0; 207 208 current_ndx = sn->current_rate[size_bin]; 209 if (current_ndx < 0) { 210 /* no successes yet, send at the lowest bit-rate */ 211 return 0; 212 } 213 214 current_tt = sn->stats[size_bin][current_ndx].average_tx_time; 215 216 for (x = 0; x < sn->num_rates; x++) { 217 int ndx = (sn->last_sample_ndx[size_bin]+1+x) % sn->num_rates; 218 219 /* don't sample the current bit-rate */ 220 if (ndx == current_ndx) 221 continue; 222 223 /* this bit-rate is always worse than the current one */ 224 if (sn->stats[size_bin][ndx].perfect_tx_time > current_tt) 225 continue; 226 227 /* rarely sample bit-rates that fail a lot */ 228 if (ticks - sn->stats[size_bin][ndx].last_tx < ((hz * STALE_FAILURE_TIMEOUT_MS)/1000) && 229 sn->stats[size_bin][ndx].successive_failures > 3) 230 continue; 231 232 /* don't sample more than 2 indexes higher 233 * for rates higher than 11 megabits 234 */ 235 if (sn->rates[ndx].rate > 22 && ndx > current_ndx + 2) 236 continue; 237 238 /* 9 megabits never works better than 12 */ 239 if (sn->rates[ndx].rate == 18) 240 continue; 241 242 /* if we're using 11 megabits, only sample up to 12 megabits 243 */ 244 if (sn->rates[current_ndx].rate == 22 && ndx > current_ndx + 1) 245 continue; 246 247 sn->last_sample_ndx[size_bin] = ndx; 248 return ndx; 249 } 250 return current_ndx; 251 } 252 253 void 254 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, 255 int shortPreamble, size_t frameLen, 256 u_int8_t *rix, int *try0, u_int8_t *txrate) 257 { 258 struct sample_node *sn = ATH_NODE_SAMPLE(an); 259 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 260 struct ieee80211com *ic = &sc->sc_ic; 261 int ndx, size_bin, mrr, best_ndx, change_rates; 262 unsigned average_tx_time; 263 264 mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); 265 size_bin = size_to_bin(frameLen); 266 best_ndx = best_rate_ndx(sn, size_bin, !mrr); 267 268 if (best_ndx >= 0) { 269 average_tx_time = sn->stats[size_bin][best_ndx].average_tx_time; 270 } else { 271 average_tx_time = 0; 272 } 273 274 if (sn->static_rate_ndx != -1) { 275 ndx = sn->static_rate_ndx; 276 *try0 = ATH_TXMAXTRY; 277 } else { 278 *try0 = mrr ? 2 : ATH_TXMAXTRY; 279 280 if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100)) { 281 /* 282 * we want to limit the time measuring the performance 283 * of other bit-rates to ath_sample_rate% of the 284 * total transmission time. 285 */ 286 ndx = pick_sample_ndx(sn, size_bin); 287 if (ndx != sn->current_rate[size_bin]) { 288 sn->current_sample_ndx[size_bin] = ndx; 289 } else { 290 sn->current_sample_ndx[size_bin] = -1; 291 } 292 sn->packets_since_sample[size_bin] = 0; 293 294 } else { 295 change_rates = 0; 296 if (!sn->packets_sent[size_bin] || best_ndx == -1) { 297 /* no packet has been sent successfully yet */ 298 for (ndx = sn->num_rates-1; ndx > 0; ndx--) { 299 /* 300 * pick the highest rate <= 36 Mbps 301 * that hasn't failed. 302 */ 303 if (sn->rates[ndx].rate <= 72 && 304 sn->stats[size_bin][ndx].successive_failures == 0) { 305 break; 306 } 307 } 308 change_rates = 1; 309 best_ndx = ndx; 310 } else if (sn->packets_sent[size_bin] < 20) { 311 /* let the bit-rate switch quickly during the first few packets */ 312 change_rates = 1; 313 } else if (ticks - ((hz*MIN_SWITCH_MS)/1000) > sn->ticks_since_switch[size_bin]) { 314 /* 2 seconds have gone by */ 315 change_rates = 1; 316 } else if (average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time) { 317 /* the current bit-rate is twice as slow as the best one */ 318 change_rates = 1; 319 } 320 321 sn->packets_since_sample[size_bin]++; 322 323 if (change_rates) { 324 if (best_ndx != sn->current_rate[size_bin]) { 325 DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d\n", 326 __func__, 327 ether_sprintf(an->an_node.ni_macaddr), 328 packet_size_bins[size_bin], 329 sn->rates[sn->current_rate[size_bin]].rate, 330 sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time, 331 sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time, 332 sn->rates[best_ndx].rate, 333 sn->stats[size_bin][best_ndx].average_tx_time, 334 sn->stats[size_bin][best_ndx].perfect_tx_time, 335 sn->packets_since_switch[size_bin], 336 mrr); 337 } 338 sn->packets_since_switch[size_bin] = 0; 339 sn->current_rate[size_bin] = best_ndx; 340 sn->ticks_since_switch[size_bin] = ticks; 341 } 342 ndx = sn->current_rate[size_bin]; 343 sn->packets_since_switch[size_bin]++; 344 if (size_bin == 0) { 345 /* 346 * set the visible txrate for this node 347 * to the rate of small packets 348 */ 349 an->an_node.ni_txrate = ndx; 350 } 351 } 352 } 353 354 KASSERTMSG(ndx >= 0 && ndx < sn->num_rates, "ndx is %d", ndx); 355 356 *rix = sn->rates[ndx].rix; 357 if (shortPreamble) { 358 *txrate = sn->rates[ndx].shortPreambleRateCode; 359 } else { 360 *txrate = sn->rates[ndx].rateCode; 361 } 362 sn->packets_sent[size_bin]++; 363 } 364 365 void 366 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 367 struct ath_desc *ds, int shortPreamble, u_int8_t rix) 368 { 369 struct sample_node *sn = ATH_NODE_SAMPLE(an); 370 int rateCode = -1; 371 int frame_size = 0; 372 int size_bin = 0; 373 int ndx = 0; 374 375 size_bin = size_to_bin(frame_size); // TODO: it's correct that frame_size alway 0 ? 376 ndx = sn->current_rate[size_bin]; /* retry at the current bit-rate */ 377 378 if (!sn->stats[size_bin][ndx].packets_acked) { 379 ndx = 0; /* use the lowest bit-rate */ 380 } 381 382 if (shortPreamble) { 383 rateCode = sn->rates[ndx].shortPreambleRateCode; 384 } else { 385 rateCode = sn->rates[ndx].rateCode; 386 } 387 ath_hal_setupxtxdesc(sc->sc_ah, ds 388 , rateCode, 3 /* series 1 */ 389 , sn->rates[0].rateCode, 3 /* series 2 */ 390 , 0, 0 /* series 3 */ 391 ); 392 } 393 394 static void 395 update_stats(struct ath_softc *sc, struct ath_node *an, 396 int frame_size, 397 int ndx0, int tries0, 398 int ndx1, int tries1, 399 int ndx2, int tries2, 400 int ndx3, int tries3, 401 int short_tries, int tries, int status) 402 { 403 struct sample_node *sn = ATH_NODE_SAMPLE(an); 404 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 405 int tt = 0; 406 int tries_so_far = 0; 407 int size_bin; 408 int size; 409 int rate; 410 411 if (ndx0 == -1) 412 return; 413 414 size_bin = size_to_bin(frame_size); 415 size = bin_to_size(size_bin); 416 rate = sn->rates[ndx0].rate; 417 418 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix, 419 short_tries - 1, MIN(tries0, tries) - 1); 420 tries_so_far += tries0; 421 if (tries1 && tries0 < tries) { 422 tt += calc_usecs_unicast_packet(sc, size, 423 ndx1 == -1 ? 0 : sn->rates[ndx1].rix, short_tries - 1, 424 MIN(tries1 + tries_so_far, tries) - tries_so_far - 1); 425 } 426 tries_so_far += tries1; 427 428 if (tries2 && tries0 + tries1 < tries) { 429 tt += calc_usecs_unicast_packet(sc, size, 430 ndx2 == -1 ? 0 : sn->rates[ndx2].rix, short_tries - 1, 431 MIN(tries2 + tries_so_far, tries) - tries_so_far - 1); 432 } 433 434 tries_so_far += tries2; 435 436 if (tries3 && tries0 + tries1 + tries2 < tries) { 437 tt += calc_usecs_unicast_packet(sc, size, 438 ndx3 == -1 ? 0 : sn->rates[ndx3].rix, short_tries - 1, 439 MIN(tries3 + tries_so_far, tries) - tries_so_far - 1); 440 } 441 442 if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) { 443 /* just average the first few packets */ 444 int avg_tx = sn->stats[size_bin][ndx0].average_tx_time; 445 int packets = sn->stats[size_bin][ndx0].total_packets; 446 sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1); 447 } else { 448 /* use a ewma */ 449 sn->stats[size_bin][ndx0].average_tx_time = 450 ((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) + 451 (tt * (100 - ssc->ath_smoothing_rate))) / 100; 452 } 453 454 if (status) { 455 int y; 456 sn->stats[size_bin][ndx0].successive_failures++; 457 for (y = size_bin+1; y < NUM_PACKET_SIZE_BINS; y++) { 458 /* also say larger packets failed since we 459 * assume if a small packet fails at a lower 460 * bit-rate then a larger one will also. 461 */ 462 sn->stats[y][ndx0].successive_failures++; 463 sn->stats[y][ndx0].last_tx = ticks; 464 sn->stats[y][ndx0].tries += tries; 465 sn->stats[y][ndx0].total_packets++; 466 } 467 } else { 468 sn->stats[size_bin][ndx0].packets_acked++; 469 sn->stats[size_bin][ndx0].successive_failures = 0; 470 } 471 sn->stats[size_bin][ndx0].tries += tries; 472 sn->stats[size_bin][ndx0].last_tx = ticks; 473 sn->stats[size_bin][ndx0].total_packets++; 474 475 476 if (ndx0 == sn->current_sample_ndx[size_bin]) { 477 DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n", 478 __func__, ether_sprintf(an->an_node.ni_macaddr), 479 size, rate, short_tries, tries, tt, 480 sn->stats[size_bin][ndx0].average_tx_time, 481 sn->stats[size_bin][ndx0].perfect_tx_time, 482 status); 483 sn->sample_tt[size_bin] = tt; 484 sn->current_sample_ndx[size_bin] = -1; 485 } 486 } 487 488 void 489 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, 490 const struct ath_desc *ds, const struct ath_desc *ds0) 491 { 492 struct ieee80211com *ic = &sc->sc_ic; 493 struct sample_node *sn = ATH_NODE_SAMPLE(an); 494 const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0; 495 int final_rate, short_tries, long_tries, frame_size; 496 int ndx = -1; 497 int mrr; 498 499 final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate; 500 short_tries = ds->ds_txstat.ts_shortretry + 1; 501 long_tries = ds->ds_txstat.ts_longretry + 1; 502 frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ 503 if (frame_size == 0) /* NB: should not happen */ 504 frame_size = 1500; 505 506 if (sn->num_rates <= 0) { 507 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d " 508 "no rates yet\n", 509 __func__, ether_sprintf(an->an_node.ni_macaddr), 510 bin_to_size(size_to_bin(frame_size)), 511 ds->ds_txstat.ts_status, 512 short_tries, long_tries); 513 return; 514 } 515 516 mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); 517 518 if (sc->sc_mrretry && ds->ds_txstat.ts_status) { 519 /* this packet failed */ 520 DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", 521 __func__, 522 ether_sprintf(an->an_node.ni_macaddr), 523 bin_to_size(size_to_bin(frame_size)), 524 sc->sc_hwmap[ads->xmit_rate0].ieeerate, 525 ads->xmit_tries0, 526 sc->sc_hwmap[ads->xmit_rate1].ieeerate, 527 ads->xmit_tries1, 528 sc->sc_hwmap[ads->xmit_rate2].ieeerate, 529 ads->xmit_tries2, 530 sc->sc_hwmap[ads->xmit_rate3].ieeerate, 531 ads->xmit_tries3, 532 ds->ds_txstat.ts_status ? "FAIL" : "OK", 533 short_tries, 534 long_tries); 535 } 536 537 if (!mrr || !(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) { 538 /* only one rate was used */ 539 ndx = rate_to_ndx(sn, final_rate); 540 DPRINTF(sc, "%s: %s size %d status %d rate/try %d/%d/%d\n", 541 __func__, ether_sprintf(an->an_node.ni_macaddr), 542 bin_to_size(size_to_bin(frame_size)), 543 ds->ds_txstat.ts_status, 544 ndx, short_tries, long_tries); 545 if (ndx >= 0 && ndx < sn->num_rates) { 546 update_stats(sc, an, frame_size, 547 ndx, long_tries, 548 0, 0, 549 0, 0, 550 0, 0, 551 short_tries, long_tries, ds->ds_txstat.ts_status); 552 } 553 } else { 554 int rate0, tries0, ndx0; 555 int rate1, tries1, ndx1; 556 int rate2, tries2, ndx2; 557 int rate3, tries3, ndx3; 558 int finalTSIdx = ads->final_ts_index; 559 560 /* 561 * Process intermediate rates that failed. 562 */ 563 564 rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate; 565 tries0 = ads->xmit_tries0; 566 ndx0 = rate_to_ndx(sn, rate0); 567 568 rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate; 569 tries1 = ads->xmit_tries1; 570 ndx1 = rate_to_ndx(sn, rate1); 571 572 rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate; 573 tries2 = ads->xmit_tries2; 574 ndx2 = rate_to_ndx(sn, rate2); 575 576 rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate; 577 tries3 = ads->xmit_tries3; 578 ndx3 = rate_to_ndx(sn, rate3); 579 580 #if 1 581 DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", 582 __func__, ether_sprintf(an->an_node.ni_macaddr), 583 bin_to_size(size_to_bin(frame_size)), 584 finalTSIdx, 585 long_tries, 586 ds->ds_txstat.ts_status, 587 rate0, tries0, 588 rate1, tries1, 589 rate2, tries2, 590 rate3, tries3); 591 #endif 592 593 if (tries0) { 594 update_stats(sc, an, frame_size, 595 ndx0, tries0, 596 ndx1, tries1, 597 ndx2, tries2, 598 ndx3, tries3, 599 short_tries, ds->ds_txstat.ts_longretry + 1, 600 long_tries > tries0); 601 } 602 603 if (tries1 && finalTSIdx > 0) { 604 update_stats(sc, an, frame_size, 605 ndx1, tries1, 606 ndx2, tries2, 607 ndx3, tries3, 608 0, 0, 609 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, 610 ds->ds_txstat.ts_status); 611 } 612 613 if (tries2 && finalTSIdx > 1) { 614 update_stats(sc, an, frame_size, 615 ndx2, tries2, 616 ndx3, tries3, 617 0, 0, 618 0, 0, 619 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, 620 ds->ds_txstat.ts_status); 621 } 622 623 if (tries3 && finalTSIdx > 2) { 624 update_stats(sc, an, frame_size, 625 ndx3, tries3, 626 0, 0, 627 0, 0, 628 0, 0, 629 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, 630 ds->ds_txstat.ts_status); 631 } 632 } 633 } 634 635 void 636 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 637 { 638 DPRINTF(sc, "%s: %s isnew %d\n", __func__, 639 ether_sprintf(an->an_node.ni_macaddr), isnew); 640 if (isnew) 641 ath_rate_ctl_reset(sc, &an->an_node); 642 } 643 644 /* 645 * Initialize the tables for a node. 646 */ 647 static void 648 ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 649 { 650 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 651 struct ieee80211com *ic = &sc->sc_ic; 652 struct ath_node *an = ATH_NODE(ni); 653 struct sample_node *sn = ATH_NODE_SAMPLE(an); 654 const HAL_RATE_TABLE *rt = sc->sc_currates; 655 int x, y, srate; 656 657 KASSERTMSG(rt != NULL, "no rate table, mode %u", sc->sc_curmode); 658 sn->static_rate_ndx = -1; 659 if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) { 660 /* 661 * A fixed rate is to be used; ic_fixed_rate is an 662 * index into the supported rate set. Convert this 663 * to the index into the negotiated rate set for 664 * the node. We know the rate is there because the 665 * rate set is checked when the station associates. 666 */ 667 const struct ieee80211_rateset *rs = 668 &ic->ic_sup_rates[ic->ic_curmode]; 669 int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 670 /* NB: the rate set is assumed sorted */ 671 srate = ni->ni_rates.rs_nrates - 1; 672 for (; srate >= 0 && RATE(srate) != r; srate--) 673 ; 674 KASSERTMSG(srate >= 0, 675 "fixed rate %d not in rate set", ic->ic_fixed_rate); 676 sn->static_rate_ndx = srate; 677 } 678 679 DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr)); 680 681 sn->num_rates = ni->ni_rates.rs_nrates; 682 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 683 sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; 684 sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; 685 sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; 686 sn->rates[x].shortPreambleRateCode = 687 rt->info[sn->rates[x].rix].rateCode | 688 rt->info[sn->rates[x].rix].shortPreamble; 689 690 DPRINTF(sc, " %d/%d", sn->rates[x].rate, 691 calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 692 0,0)); 693 } 694 DPRINTF(sc, "%s\n", ""); 695 696 /* set the visible bit-rate to the lowest one available */ 697 ni->ni_txrate = 0; 698 sn->num_rates = ni->ni_rates.rs_nrates; 699 700 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { 701 int size = bin_to_size(y); 702 int ndx = 0; 703 sn->packets_sent[y] = 0; 704 sn->current_sample_ndx[y] = -1; 705 sn->last_sample_ndx[y] = 0; 706 707 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 708 sn->stats[y][x].successive_failures = 0; 709 sn->stats[y][x].tries = 0; 710 sn->stats[y][x].total_packets = 0; 711 sn->stats[y][x].packets_acked = 0; 712 sn->stats[y][x].last_tx = 0; 713 714 sn->stats[y][x].perfect_tx_time = 715 calc_usecs_unicast_packet(sc, size, 716 sn->rates[x].rix, 717 0, 0); 718 sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time; 719 } 720 721 /* set the initial rate */ 722 for (ndx = sn->num_rates-1; ndx > 0; ndx--) { 723 if (sn->rates[ndx].rate <= 72) { 724 break; 725 } 726 } 727 sn->current_rate[y] = ndx; 728 } 729 730 DPRINTF(sc, "%s: %s %d rates %d%sMbps (%dus)- %d%sMbps (%dus)\n", 731 __func__, ether_sprintf(ni->ni_macaddr), 732 sn->num_rates, 733 sn->rates[0].rate/2, sn->rates[0].rate % 0x1 ? ".5" : "", 734 sn->stats[1][0].perfect_tx_time, 735 sn->rates[sn->num_rates-1].rate/2, 736 sn->rates[sn->num_rates-1].rate % 0x1 ? ".5" : "", 737 sn->stats[1][sn->num_rates-1].perfect_tx_time 738 ); 739 740 ni->ni_txrate = sn->current_rate[0]; 741 #undef RATE 742 } 743 744 static void 745 rate_cb(void *arg, struct ieee80211_node *ni) 746 { 747 struct ath_softc *sc = arg; 748 749 ath_rate_newassoc(sc, ATH_NODE(ni), 1); 750 } 751 752 /* 753 * Reset the rate control state for each 802.11 state transition. 754 */ 755 void 756 ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state) 757 { 758 struct ieee80211com *ic = &sc->sc_ic; 759 760 if (state == IEEE80211_S_RUN) { 761 if (ic->ic_opmode != IEEE80211_M_STA) { 762 /* 763 * Sync rates for associated stations and neighbors. 764 */ 765 ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc); 766 } 767 ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1); 768 } 769 } 770 771 static void 772 ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc) 773 { 774 int rc; 775 struct sysctllog **log = &sc->sc_sysctllog; 776 const struct sysctlnode *cnode, *rnode; 777 778 if ((rnode = ath_sysctl_instance(device_xname(sc->sc_dev), log)) == NULL) 779 return; 780 781 /* XXX bounds check [0..100] */ 782 if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, smoothing_rate, 783 "rate control: retry threshold to credit rate raise (%%)")) != 0) 784 goto err; 785 786 /* XXX bounds check [2..100] */ 787 if ((rc = SYSCTL_PFX_INT(osc->ath_, CTLFLAG_READWRITE, sample_rate, 788 "rate control: # good periods before raising rate")) != 0) 789 goto err; 790 791 return; 792 err: 793 printf("%s: sysctl_createv failed, rc = %d\n", __func__, rc); 794 } 795 796 struct ath_ratectrl * 797 ath_rate_attach(struct ath_softc *sc) 798 { 799 struct sample_softc *osc; 800 801 DPRINTF(sc, "%s:\n", __func__); 802 osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 803 if (osc == NULL) 804 return NULL; 805 osc->arc.arc_space = sizeof(struct sample_node); 806 osc->ath_smoothing_rate = 95; /* ewma percentage (out of 100) */ 807 osc->ath_sample_rate = 10; /* send a different bit-rate 1/X packets */ 808 ath_rate_sysctlattach(sc, osc); 809 return &osc->arc; 810 } 811 812 void 813 ath_rate_detach(struct ath_ratectrl *arc) 814 { 815 struct sample_softc *osc = (struct sample_softc *) arc; 816 817 free(osc, M_DEVBUF); 818 } 819