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