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