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