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