sample.c revision 144307
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 144307 2005-03-29 21:00:50Z 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 if (!sn->packets_sent[size_bin]) { 267 /* no packets sent */ 268 if (best_ndx == -1) { 269 ndx = sn->num_rates - 1; 270 if (sc->sc_curmode != IEEE80211_MODE_11B) { 271 for (; ndx >= 0 && sn->rates[ndx].rate > 72; ndx--) 272 ; 273 274 } 275 } else { 276 ndx = best_ndx; 277 } 278 } else if (best_ndx == -1) { 279 /* no packet has succeeded yet */ 280 if (mrr) { 281 /* 282 * no packet has succeeded, try the 283 * highest bitrate that hasn't failed 284 */ 285 for (ndx = sn->num_rates-1; ndx >= 0; ndx--) { 286 if (sn->stats[size_bin][ndx].successive_failures == 0) { 287 break; 288 } 289 } 290 } else { 291 ndx = 0; 292 } 293 } else if (sn->sample_tt[size_bin] < (sn->packets_since_sample[size_bin]*ssc->ath_sample_rate/100) * average_tx_time && 294 sn->packets_since_sample[size_bin] > 15) { 295 /* 296 * we want to limit the time measuring the performance 297 * of other bit-rates to ath_sample_rate% of the 298 * total transmission time. 299 */ 300 ndx = pick_sample_ndx(sn, size_bin); 301 if (ndx != sn->current_rate[size_bin]) { 302 if (0) { 303 DPRINTF(sc, "%s: %s size %d last sample tt %d sampling %d packets since %d\n", 304 __func__, 305 ether_sprintf(an->an_node.ni_macaddr), 306 packet_size_bins[size_bin], 307 sn->sample_tt[size_bin], 308 sn->rates[ndx].rate, 309 sn->packets_since_sample[size_bin]); 310 } 311 sn->current_sample_ndx[size_bin] = ndx; 312 } else { 313 sn->current_sample_ndx[size_bin] = -1; 314 } 315 sn->packets_since_sample[size_bin] = 0; 316 317 } else { 318 sn->packets_since_sample[size_bin]++; 319 /* 320 * don't switch bit-rates every packet. only 321 * switch during the first few packets we send 322 * or after 100 packets, or if the current 323 * bit-rate begins to perform twice as bad as 324 * another one. 325 */ 326 if (sn->packets_sent[size_bin] < 20 || 327 ticks - ((hz*2000)/1000) > sn->jiffies_since_switch[size_bin] || 328 average_tx_time * 2 < sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time ) { 329 if (sn->packets_sent[size_bin] > 20) { 330 DPRINTF(sc, "%s: %s size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mmr %d\n", 331 __func__, 332 ether_sprintf(an->an_node.ni_macaddr), 333 packet_size_bins[size_bin], 334 sn->rates[sn->current_rate[size_bin]].rate, 335 sn->stats[size_bin][sn->current_rate[size_bin]].average_tx_time, 336 sn->stats[size_bin][sn->current_rate[size_bin]].perfect_tx_time, 337 sn->rates[best_ndx].rate, 338 sn->stats[size_bin][best_ndx].average_tx_time, 339 sn->stats[size_bin][best_ndx].perfect_tx_time, 340 sn->packets_since_switch[size_bin], 341 mrr); 342 } 343 sn->packets_since_switch[size_bin] = 0; 344 sn->current_rate[size_bin] = best_ndx; 345 sn->jiffies_since_switch[size_bin] = ticks; 346 } 347 ndx = sn->current_rate[size_bin]; 348 sn->packets_since_switch[size_bin]++; 349 } 350 351 } 352 353 if (ndx < 0) { 354 ndx = 0; 355 } 356 *rix = sn->rates[ndx].rix; 357 if (shortPreamble) { 358 *txrate = sn->rates[ndx].shortPreambleRateCode; 359 } else { 360 *txrate = sn->rates[ndx].rateCode; 361 } 362 sn->packets_sent[size_bin]++; 363 an->an_node.ni_txrate = ndx; 364} 365 366void 367ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 368 struct ath_desc *ds, HAL_BOOL shortPreamble, u_int8_t rix) 369{ 370 struct sample_node *sn = ATH_NODE_SAMPLE(an); 371 int rateCode = -1; 372 int frame_size, size_bin, best_ndx, ndx; 373 374 frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ 375 KASSERT(frame_size != 0, ("no frame size")); 376 size_bin = size_to_bin(frame_size); 377 best_ndx = best_rate_ndx(sn, size_bin, 0); 378 379 if (best_ndx == -1 || !sn->stats[size_bin][best_ndx].packets_acked) { 380 /* 381 * no packet has succeeded, so also try at the 382 * lowest bitate. 383 */ 384 ndx = 0; 385 } else { 386 /* 387 * we're trying a different bit-rate, and it could be lossy, 388 * so if it fails try at the best bit-rate. 389 */ 390 ndx = best_ndx; 391 } 392 KASSERT(0 <= ndx && ndx < IEEE80211_RATE_MAXSIZE, 393 ("invalid ndx %d", ndx)); 394 if (shortPreamble) { 395 rateCode = sn->rates[ndx].shortPreambleRateCode; 396 } else { 397 rateCode = sn->rates[ndx].rateCode; 398 } 399 ath_hal_setupxtxdesc(sc->sc_ah, ds 400 , rateCode, 3 /* series 1 */ 401 , sn->rates[0].rateCode, 3 /* series 2 */ 402 , 0, 0 /* series 3 */ 403 ); 404} 405 406static void 407update_stats(struct ath_softc *sc, struct ath_node *an, 408 int frame_size, 409 int ndx0, int tries0, 410 int ndx1, int tries1, 411 int ndx2, int tries2, 412 int ndx3, int tries3, 413 int short_tries, int tries, int status) 414{ 415 struct sample_node *sn = ATH_NODE_SAMPLE(an); 416 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 417 int tt = 0; 418 int tries_so_far = 0; 419 int size_bin = 0; 420 int size = 0; 421 int rate = 0; 422 423 size_bin = size_to_bin(frame_size); 424 size = bin_to_size(size_bin); 425 rate = sn->rates[ndx0].rate; 426 427 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx0].rix, 428 short_tries-1, 429 MIN(tries0, tries) - 1); 430 tries_so_far += tries0; 431 if (tries1 && tries0 < tries) { 432 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx1].rix, 433 short_tries-1, 434 MIN(tries1 + tries_so_far, tries) - tries_so_far - 1); 435 } 436 tries_so_far += tries1; 437 438 if (tries2 && tries0 + tries1 < tries) { 439 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx2].rix, 440 short_tries-1, 441 MIN(tries2 + tries_so_far, tries) - tries_so_far - 1); 442 } 443 444 tries_so_far += tries2; 445 446 if (tries3 && tries0 + tries1 + tries2 < tries) { 447 tt += calc_usecs_unicast_packet(sc, size, sn->rates[ndx3].rix, 448 short_tries-1, 449 MIN(tries3 + tries_so_far, tries) - tries_so_far - 1); 450 } 451 452 if (0 && (short_tries + tries > 3 || status)) { 453 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", 454 __func__, ether_sprintf(an->an_node.ni_macaddr), 455 size, 456 rate, ndx0, short_tries, tries, tries0, tt, 457 sn->stats[size_bin][ndx0].average_tx_time, 458 sn->stats[size_bin][ndx0].perfect_tx_time, 459 status); 460 } 461 462 if (sn->stats[size_bin][ndx0].total_packets < (100 / (100 - ssc->ath_smoothing_rate))) { 463 /* just average the first few packets */ 464 int avg_tx = sn->stats[size_bin][ndx0].average_tx_time; 465 int packets = sn->stats[size_bin][ndx0].total_packets; 466 sn->stats[size_bin][ndx0].average_tx_time = (tt+(avg_tx*packets))/(packets+1); 467 } else { 468 /* use a ewma */ 469 sn->stats[size_bin][ndx0].average_tx_time = 470 ((sn->stats[size_bin][ndx0].average_tx_time * ssc->ath_smoothing_rate) + 471 (tt * (100 - ssc->ath_smoothing_rate))) / 100; 472 } 473 474 if (status) { 475 /* 476 * this packet failed - count this as a failure 477 * for larger packets also, since we assume 478 * if a small packet fails at a lower bit-rate 479 * then a larger one will also. 480 */ 481 int y; 482 for (y = size_bin; y < NUM_PACKET_SIZE_BINS; y++) { 483 sn->stats[y][ndx0].successive_failures++; 484 sn->stats[y][ndx0].last_tx = ticks; 485 } 486 } else { 487 sn->stats[size_bin][ndx0].packets_acked++; 488 sn->stats[size_bin][ndx0].successive_failures = 0; 489 } 490 sn->stats[size_bin][ndx0].tries += tries; 491 sn->stats[size_bin][ndx0].last_tx = ticks; 492 sn->stats[size_bin][ndx0].total_packets++; 493 494 495 if (ndx0 == sn->current_sample_ndx[size_bin]) { 496 DPRINTF(sc, "%s: %s size %d sample rate %d tries (%d/%d) tt %d avg_tt (%d/%d) status %d\n", 497 __func__, ether_sprintf(an->an_node.ni_macaddr), 498 size, rate, short_tries, tries, tt, 499 sn->stats[size_bin][ndx0].average_tx_time, 500 sn->stats[size_bin][ndx0].perfect_tx_time, 501 status); 502 sn->sample_tt[size_bin] = tt; 503 sn->current_sample_ndx[size_bin] = -1; 504 } 505} 506 507void 508ath_rate_tx_complete(struct ath_softc *sc, 509 struct ath_node *an, const struct ath_desc *ds) 510{ 511 struct sample_node *sn = ATH_NODE_SAMPLE(an); 512 const struct ar5212_desc *ads = (const struct ar5212_desc *)&ds->ds_ctl0; 513 int final_rate, short_tries, long_tries, frame_size; 514 int ndx = -1; 515 516 final_rate = sc->sc_hwmap[ds->ds_txstat.ts_rate &~ HAL_TXSTAT_ALTRATE].ieeerate; 517 short_tries = ds->ds_txstat.ts_shortretry + 1; 518 long_tries = ds->ds_txstat.ts_longretry + 1; 519 frame_size = ds->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */ 520 if (frame_size == 0) 521 frame_size = 1500; 522 523 if (sn->num_rates <= 0) { 524 DPRINTF(sc, "%s: %s %s no rates yet\n", __func__, 525 ether_sprintf(an->an_node.ni_macaddr), __func__); 526 return; 527 } 528 529 if (sc->sc_mrretry && ds->ds_txstat.ts_status) { 530 /* this packet failed */ 531 DPRINTF(sc, "%s: %s size %d rate/try %d/%d %d/%d %d/%d %d/%d status %s retries (%d/%d)\n", 532 __func__, 533 ether_sprintf(an->an_node.ni_macaddr), 534 bin_to_size(size_to_bin(frame_size)), 535 sc->sc_hwmap[ads->xmit_rate0].ieeerate, 536 ads->xmit_tries0, 537 sc->sc_hwmap[ads->xmit_rate1].ieeerate, 538 ads->xmit_tries1, 539 sc->sc_hwmap[ads->xmit_rate2].ieeerate, 540 ads->xmit_tries2, 541 sc->sc_hwmap[ads->xmit_rate3].ieeerate, 542 ads->xmit_tries3, 543 ds->ds_txstat.ts_status ? "FAIL" : "OK", 544 short_tries, 545 long_tries); 546 } 547 548 if (!(ds->ds_txstat.ts_rate & HAL_TXSTAT_ALTRATE)) { 549 /* only one rate was used */ 550 ndx = rate_to_ndx(sn, final_rate); 551 if (ndx >= 0 && ndx < sn->num_rates) { 552 update_stats(sc, an, frame_size, 553 ndx, long_tries, 554 0, 0, 555 0, 0, 556 0, 0, 557 short_tries, long_tries, ds->ds_txstat.ts_status); 558 } 559 } else { 560 int rate0, tries0, ndx0; 561 int rate1, tries1, ndx1; 562 int rate2, tries2, ndx2; 563 int rate3, tries3, ndx3; 564 int finalTSIdx = ads->final_ts_index; 565 566 /* 567 * Process intermediate rates that failed. 568 */ 569 570 rate0 = sc->sc_hwmap[ads->xmit_rate0].ieeerate; 571 tries0 = ads->xmit_tries0; 572 ndx0 = rate_to_ndx(sn, rate0); 573 574 rate1 = sc->sc_hwmap[ads->xmit_rate1].ieeerate; 575 tries1 = ads->xmit_tries1; 576 ndx1 = rate_to_ndx(sn, rate1); 577 578 rate2 = sc->sc_hwmap[ads->xmit_rate2].ieeerate; 579 tries2 = ads->xmit_tries2; 580 ndx2 = rate_to_ndx(sn, rate2); 581 582 rate3 = sc->sc_hwmap[ads->xmit_rate3].ieeerate; 583 tries3 = ads->xmit_tries3; 584 ndx3 = rate_to_ndx(sn, rate3); 585 586#if 0 587 DPRINTF(sc, "%s: %s size %d finaltsidx %d tries %d status %d rate/try %d/%d %d/%d %d/%d %d/%d\n", 588 __func__, ether_sprintf(an->an_node.ni_macaddr), 589 bin_to_size(size_to_bin(frame_size)), 590 finalTSIdx, 591 long_tries, 592 ds->ds_txstat.ts_status, 593 rate0, tries0, 594 rate1, tries1, 595 rate2, tries2, 596 rate3, tries3); 597#endif 598 599 if (tries0) { 600 update_stats(sc, an, frame_size, 601 ndx0, tries0, 602 ndx1, tries1, 603 ndx2, tries2, 604 ndx3, tries3, 605 short_tries, ds->ds_txstat.ts_longretry + 1, 606 ds->ds_txstat.ts_status); 607 } 608 609 if (tries1 && finalTSIdx > 0) { 610 update_stats(sc, an, frame_size, 611 ndx1, tries1, 612 ndx2, tries2, 613 ndx3, tries3, 614 0, 0, 615 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0, 616 ds->ds_txstat.ts_status); 617 } 618 619 if (tries2 && finalTSIdx > 1) { 620 update_stats(sc, an, frame_size, 621 ndx2, tries2, 622 ndx3, tries3, 623 0, 0, 624 0, 0, 625 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1, 626 ds->ds_txstat.ts_status); 627 } 628 629 if (tries3 && finalTSIdx > 2) { 630 update_stats(sc, an, frame_size, 631 ndx3, tries3, 632 0, 0, 633 0, 0, 634 0, 0, 635 short_tries, ds->ds_txstat.ts_longretry + 1 - tries0 - tries1 - tries2, 636 ds->ds_txstat.ts_status); 637 } 638 } 639} 640 641void 642ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 643{ 644 DPRINTF(sc, "%s:\n", __func__); 645 if (isnew) 646 ath_rate_ctl_reset(sc, &an->an_node); 647} 648 649/* 650 * Initialize the tables for a node. 651 */ 652static void 653ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 654{ 655#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 656 struct ieee80211com *ic = &sc->sc_ic; 657 struct ath_node *an = ATH_NODE(ni); 658 struct sample_node *sn = ATH_NODE_SAMPLE(an); 659 const HAL_RATE_TABLE *rt = sc->sc_currates; 660 int x, y, srate; 661 662 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 663 sn->static_rate_ndx = -1; 664 if (ic->ic_fixed_rate != -1) { 665 /* 666 * A fixed rate is to be used; ic_fixed_rate is an 667 * index into the supported rate set. Convert this 668 * to the index into the negotiated rate set for 669 * the node. We know the rate is there because the 670 * rate set is checked when the station associates. 671 */ 672 const struct ieee80211_rateset *rs = 673 &ic->ic_sup_rates[ic->ic_curmode]; 674 int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 675 /* NB: the rate set is assumed sorted */ 676 srate = ni->ni_rates.rs_nrates - 1; 677 for (; srate >= 0 && RATE(srate) != r; srate--) 678 ; 679 KASSERT(srate >= 0, 680 ("fixed rate %d not in rate set", ic->ic_fixed_rate)); 681 sn->static_rate_ndx = srate; 682 } 683 684 DPRINTF(sc, "%s: %s size 1600 rate/tt", __func__, ether_sprintf(ni->ni_macaddr)); 685 686 sn->num_rates = ni->ni_rates.rs_nrates; 687 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 688 sn->rates[x].rate = ni->ni_rates.rs_rates[x] & IEEE80211_RATE_VAL; 689 sn->rates[x].rix = sc->sc_rixmap[sn->rates[x].rate]; 690 sn->rates[x].rateCode = rt->info[sn->rates[x].rix].rateCode; 691 sn->rates[x].shortPreambleRateCode = 692 rt->info[sn->rates[x].rix].rateCode | 693 rt->info[sn->rates[x].rix].shortPreamble; 694 695 DPRINTF(sc, " %d/%d", sn->rates[x].rate, 696 calc_usecs_unicast_packet(sc, 1600, sn->rates[x].rix, 697 0,0)); 698 } 699 DPRINTF(sc, "%s\n", ""); 700 701 /* set the visible bit-rate to the lowest one available */ 702 ni->ni_txrate = 0; 703 sn->num_rates = ni->ni_rates.rs_nrates; 704 705 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { 706 int size = bin_to_size(y); 707 sn->packets_sent[y] = 0; 708 sn->current_sample_ndx[y] = -1; 709 sn->last_sample_ndx[y] = 0; 710 711 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 712 sn->stats[y][x].successive_failures = 0; 713 sn->stats[y][x].tries = 0; 714 sn->stats[y][x].total_packets = 0; 715 sn->stats[y][x].packets_acked = 0; 716 sn->stats[y][x].last_tx = 0; 717 718 sn->stats[y][x].perfect_tx_time = 719 calc_usecs_unicast_packet(sc, size, 720 sn->rates[x].rix, 721 0, 0); 722 sn->stats[y][x].average_tx_time = sn->stats[y][x].perfect_tx_time; 723 } 724 } 725#undef RATE 726} 727 728static void 729rate_cb(void *arg, struct ieee80211_node *ni) 730{ 731 struct ath_softc *sc = arg; 732 733 ath_rate_newassoc(sc, ATH_NODE(ni), 1); 734} 735 736/* 737 * Reset the rate control state for each 802.11 state transition. 738 */ 739void 740ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state) 741{ 742 struct ieee80211com *ic = &sc->sc_ic; 743 744 if (state == IEEE80211_S_RUN) { 745 if (ic->ic_opmode != IEEE80211_M_STA) { 746 /* 747 * Sync rates for associated stations and neighbors. 748 */ 749 ieee80211_iterate_nodes(&ic->ic_sta, rate_cb, sc); 750 } 751 ath_rate_newassoc(sc, ATH_NODE(ic->ic_bss), 1); 752 } 753} 754 755static void 756ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *osc) 757{ 758 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 759 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 760 761 /* XXX bounds check [0..100] */ 762 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 763 "smoothing_rate", CTLFLAG_RW, &osc->ath_smoothing_rate, 0, 764 "rate control: retry threshold to credit rate raise (%%)"); 765 /* XXX bounds check [2..100] */ 766 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 767 "sample_rate", CTLFLAG_RW, &osc->ath_sample_rate,0, 768 "rate control: # good periods before raising rate"); 769} 770 771struct ath_ratectrl * 772ath_rate_attach(struct ath_softc *sc) 773{ 774 struct sample_softc *osc; 775 776 DPRINTF(sc, "%s:\n", __func__); 777 osc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 778 if (osc == NULL) 779 return NULL; 780 osc->arc.arc_space = sizeof(struct sample_node); 781 osc->ath_smoothing_rate = 95; /* ewma percentage (out of 100) */ 782 osc->ath_sample_rate = 10; /* send a different bit-rate 1/X packets */ 783 ath_rate_sysctlattach(sc, osc); 784 return &osc->arc; 785} 786 787void 788ath_rate_detach(struct ath_ratectrl *arc) 789{ 790 struct sample_softc *osc = (struct sample_softc *) arc; 791 792 free(osc, M_DEVBUF); 793} 794 795/* 796 * Module glue. 797 */ 798static int 799sample_modevent(module_t mod, int type, void *unused) 800{ 801 switch (type) { 802 case MOD_LOAD: 803 if (bootverbose) 804 printf("ath_rate: version 1.1 <SampleRate bit-rate selection algorithm>\n"); 805 return 0; 806 case MOD_UNLOAD: 807 return 0; 808 } 809 return EINVAL; 810} 811 812static moduledata_t sample_mod = { 813 "ath_rate", 814 sample_modevent, 815 0 816}; 817DECLARE_MODULE(ath_rate, sample_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 818MODULE_VERSION(ath_rate, 1); 819MODULE_DEPEND(ath_rate, ath_hal, 1, 1, 1); /* Atheros HAL */ 820MODULE_DEPEND(ath_rate, wlan, 1, 1, 1); 821