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