sample.c revision 237529
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 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/sys/dev/ath/ath_rate/sample/sample.c 237529 2012-06-24 08:47:19Z adrian $"); 40 41/* 42 * John Bicket's SampleRate control algorithm. 43 */ 44#include "opt_ath.h" 45#include "opt_inet.h" 46#include "opt_wlan.h" 47#include "opt_ah.h" 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/sysctl.h> 52#include <sys/kernel.h> 53#include <sys/lock.h> 54#include <sys/mutex.h> 55#include <sys/errno.h> 56 57#include <machine/bus.h> 58#include <machine/resource.h> 59#include <sys/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/ethernet.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#include <netinet/if_ether.h> 75#endif 76 77#include <dev/ath/if_athvar.h> 78#include <dev/ath/ath_rate/sample/sample.h> 79#include <dev/ath/ath_hal/ah_desc.h> 80#include <dev/ath/ath_rate/sample/tx_schedules.h> 81 82/* 83 * This file is an implementation of the SampleRate algorithm 84 * in "Bit-rate Selection in Wireless Networks" 85 * (http://www.pdos.lcs.mit.edu/papers/jbicket-ms.ps) 86 * 87 * SampleRate chooses the bit-rate it predicts will provide the most 88 * throughput based on estimates of the expected per-packet 89 * transmission time for each bit-rate. SampleRate periodically sends 90 * packets at bit-rates other than the current one to estimate when 91 * another bit-rate will provide better performance. SampleRate 92 * switches to another bit-rate when its estimated per-packet 93 * transmission time becomes smaller than the current bit-rate's. 94 * SampleRate reduces the number of bit-rates it must sample by 95 * eliminating those that could not perform better than the one 96 * currently being used. SampleRate also stops probing at a bit-rate 97 * if it experiences several successive losses. 98 * 99 * The difference between the algorithm in the thesis and the one in this 100 * file is that the one in this file uses a ewma instead of a window. 101 * 102 * Also, this implementation tracks the average transmission time for 103 * a few different packet sizes independently for each link. 104 */ 105 106static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *); 107 108static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600 }; 109 110static __inline int 111size_to_bin(int size) 112{ 113#if NUM_PACKET_SIZE_BINS > 1 114 if (size <= packet_size_bins[0]) 115 return 0; 116#endif 117#if NUM_PACKET_SIZE_BINS > 2 118 if (size <= packet_size_bins[1]) 119 return 1; 120#endif 121#if NUM_PACKET_SIZE_BINS > 3 122 if (size <= packet_size_bins[2]) 123 return 2; 124#endif 125#if NUM_PACKET_SIZE_BINS > 4 126#error "add support for more packet sizes" 127#endif 128 return NUM_PACKET_SIZE_BINS-1; 129} 130 131static __inline int 132bin_to_size(int index) 133{ 134 return packet_size_bins[index]; 135} 136 137void 138ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) 139{ 140 /* NB: assumed to be zero'd by caller */ 141} 142 143void 144ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 145{ 146} 147 148static int 149dot11rate(const HAL_RATE_TABLE *rt, int rix) 150{ 151 if (rix < 0) 152 return -1; 153 return rt->info[rix].phy == IEEE80211_T_HT ? 154 rt->info[rix].dot11Rate : (rt->info[rix].dot11Rate & IEEE80211_RATE_VAL) / 2; 155} 156 157static const char * 158dot11rate_label(const HAL_RATE_TABLE *rt, int rix) 159{ 160 if (rix < 0) 161 return ""; 162 return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb "; 163} 164 165/* 166 * Return the rix with the lowest average_tx_time, 167 * or -1 if all the average_tx_times are 0. 168 */ 169static __inline int 170pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, 171 int size_bin, int require_acked_before) 172{ 173 struct sample_node *sn = ATH_NODE_SAMPLE(an); 174 int best_rate_rix, best_rate_tt, best_rate_pct; 175 uint32_t mask; 176 int rix, tt, pct; 177 178 best_rate_rix = 0; 179 best_rate_tt = 0; 180 best_rate_pct = 0; 181 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { 182 if ((mask & 1) == 0) /* not a supported rate */ 183 continue; 184 185 /* Don't pick a non-HT rate for a HT node */ 186 if ((an->an_node.ni_flags & IEEE80211_NODE_HT) && 187 (rt->info[rix].phy != IEEE80211_T_HT)) { 188 continue; 189 } 190 191 tt = sn->stats[size_bin][rix].average_tx_time; 192 if (tt <= 0 || 193 (require_acked_before && 194 !sn->stats[size_bin][rix].packets_acked)) 195 continue; 196 197 /* Calculate percentage if possible */ 198 if (sn->stats[size_bin][rix].total_packets > 0) { 199 pct = sn->stats[size_bin][rix].ewma_pct; 200 } else { 201 /* XXX for now, assume 95% ok */ 202 pct = 95; 203 } 204 205 /* don't use a bit-rate that has been failing */ 206 if (sn->stats[size_bin][rix].successive_failures > 3) 207 continue; 208 209 /* 210 * For HT, Don't use a bit rate that is much more 211 * lossy than the best. 212 * 213 * XXX this isn't optimal; it's just designed to 214 * eliminate rates that are going to be obviously 215 * worse. 216 */ 217 if (an->an_node.ni_flags & IEEE80211_NODE_HT) { 218 if (best_rate_pct > (pct + 50)) 219 continue; 220 } 221 222 /* 223 * For non-MCS rates, use the current average txtime for 224 * comparison. 225 */ 226 if (! (an->an_node.ni_flags & IEEE80211_NODE_HT)) { 227 if (best_rate_tt == 0 || tt <= best_rate_tt) { 228 best_rate_tt = tt; 229 best_rate_rix = rix; 230 best_rate_pct = pct; 231 } 232 } 233 234 /* 235 * Since 2 stream rates have slightly higher TX times, 236 * allow a little bit of leeway. This should later 237 * be abstracted out and properly handled. 238 */ 239 if (an->an_node.ni_flags & IEEE80211_NODE_HT) { 240 if (best_rate_tt == 0 || (tt * 8 <= best_rate_tt * 10)) { 241 best_rate_tt = tt; 242 best_rate_rix = rix; 243 best_rate_pct = pct; 244 } 245 } 246 } 247 return (best_rate_tt ? best_rate_rix : -1); 248} 249 250/* 251 * Pick a good "random" bit-rate to sample other than the current one. 252 */ 253static __inline int 254pick_sample_rate(struct sample_softc *ssc , struct ath_node *an, 255 const HAL_RATE_TABLE *rt, int size_bin) 256{ 257#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) 258#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) 259 struct sample_node *sn = ATH_NODE_SAMPLE(an); 260 int current_rix, rix; 261 unsigned current_tt; 262 uint32_t mask; 263 264 current_rix = sn->current_rix[size_bin]; 265 if (current_rix < 0) { 266 /* no successes yet, send at the lowest bit-rate */ 267 /* XXX should return MCS0 if HT */ 268 return 0; 269 } 270 271 current_tt = sn->stats[size_bin][current_rix].average_tx_time; 272 273 rix = sn->last_sample_rix[size_bin]+1; /* next sample rate */ 274 mask = sn->ratemask &~ (1<<current_rix);/* don't sample current rate */ 275 while (mask != 0) { 276 if ((mask & (1<<rix)) == 0) { /* not a supported rate */ 277 nextrate: 278 if (++rix >= rt->rateCount) 279 rix = 0; 280 continue; 281 } 282 283 /* if the node is HT and the rate isn't HT, don't bother sample */ 284 if ((an->an_node.ni_flags & IEEE80211_NODE_HT) && 285 (rt->info[rix].phy != IEEE80211_T_HT)) { 286 mask &= ~(1<<rix); 287 goto nextrate; 288 } 289 290 /* this bit-rate is always worse than the current one */ 291 if (sn->stats[size_bin][rix].perfect_tx_time > current_tt) { 292 mask &= ~(1<<rix); 293 goto nextrate; 294 } 295 296 /* rarely sample bit-rates that fail a lot */ 297 if (sn->stats[size_bin][rix].successive_failures > ssc->max_successive_failures && 298 ticks - sn->stats[size_bin][rix].last_tx < ssc->stale_failure_timeout) { 299 mask &= ~(1<<rix); 300 goto nextrate; 301 } 302 303 /* 304 * When doing aggregation, successive failures don't happen 305 * as often, as sometimes some of the sub-frames get through. 306 * 307 * If the sample rix average tx time is greater than the 308 * average tx time of the current rix, don't immediately use 309 * the rate for sampling. 310 */ 311 if (an->an_node.ni_flags & IEEE80211_NODE_HT) { 312 if ((sn->stats[size_bin][rix].average_tx_time * 10 > 313 sn->stats[size_bin][current_rix].average_tx_time * 9) && 314 (ticks - sn->stats[size_bin][rix].last_tx < ssc->stale_failure_timeout)) { 315 mask &= ~(1<<rix); 316 goto nextrate; 317 } 318 } 319 320 /* 321 * XXX TODO 322 * For HT, limit sample somehow? 323 */ 324 325 /* Don't sample more than 2 rates higher for rates > 11M for non-HT rates */ 326 if (! (an->an_node.ni_flags & IEEE80211_NODE_HT)) { 327 if (DOT11RATE(rix) > 2*11 && rix > current_rix + 2) { 328 mask &= ~(1<<rix); 329 goto nextrate; 330 } 331 } 332 333 sn->last_sample_rix[size_bin] = rix; 334 return rix; 335 } 336 return current_rix; 337#undef DOT11RATE 338#undef MCS 339} 340 341static int 342ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni) 343{ 344#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 345#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) 346#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) 347 const struct ieee80211_txparam *tp = ni->ni_txparms; 348 int srate; 349 350 /* Check MCS rates */ 351 for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) { 352 if (MCS(srate) == tp->ucastrate) 353 return sc->sc_rixmap[tp->ucastrate]; 354 } 355 356 /* Check legacy rates */ 357 for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) { 358 if (RATE(srate) == tp->ucastrate) 359 return sc->sc_rixmap[tp->ucastrate]; 360 } 361 return -1; 362#undef RATE 363#undef DOT11RATE 364#undef MCS 365} 366 367static void 368ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni) 369{ 370 struct ath_node *an = ATH_NODE(ni); 371 const struct ieee80211_txparam *tp = ni->ni_txparms; 372 struct sample_node *sn = ATH_NODE_SAMPLE(an); 373 374 if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { 375 /* 376 * A fixed rate is to be used; ucastrate is the IEEE code 377 * for this rate (sans basic bit). Check this against the 378 * negotiated rate set for the node. Note the fixed rate 379 * may not be available for various reasons so we only 380 * setup the static rate index if the lookup is successful. 381 */ 382 sn->static_rix = ath_rate_get_static_rix(sc, ni); 383 } else { 384 sn->static_rix = -1; 385 } 386} 387 388/* 389 * Pick a non-HT rate to begin using. 390 */ 391static int 392ath_rate_pick_seed_rate_legacy(struct ath_softc *sc, struct ath_node *an, 393 int frameLen) 394{ 395#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) 396#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) 397#define RATE(ix) (DOT11RATE(ix) / 2) 398 int rix = -1; 399 const HAL_RATE_TABLE *rt = sc->sc_currates; 400 struct sample_node *sn = ATH_NODE_SAMPLE(an); 401 const int size_bin = size_to_bin(frameLen); 402 403 /* no packet has been sent successfully yet */ 404 for (rix = rt->rateCount-1; rix > 0; rix--) { 405 if ((sn->ratemask & (1<<rix)) == 0) 406 continue; 407 408 /* Skip HT rates */ 409 if (rt->info[rix].phy == IEEE80211_T_HT) 410 continue; 411 412 /* 413 * Pick the highest rate <= 36 Mbps 414 * that hasn't failed. 415 */ 416 if (DOT11RATE(rix) <= 72 && 417 sn->stats[size_bin][rix].successive_failures == 0) { 418 break; 419 } 420 } 421 return rix; 422#undef RATE 423#undef MCS 424#undef DOT11RATE 425} 426 427/* 428 * Pick a HT rate to begin using. 429 * 430 * Don't use any non-HT rates; only consider HT rates. 431 */ 432static int 433ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, 434 int frameLen) 435{ 436#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) 437#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) 438#define RATE(ix) (DOT11RATE(ix) / 2) 439 int rix = -1, ht_rix = -1; 440 const HAL_RATE_TABLE *rt = sc->sc_currates; 441 struct sample_node *sn = ATH_NODE_SAMPLE(an); 442 const int size_bin = size_to_bin(frameLen); 443 444 /* no packet has been sent successfully yet */ 445 for (rix = rt->rateCount-1; rix > 0; rix--) { 446 /* Skip rates we can't use */ 447 if ((sn->ratemask & (1<<rix)) == 0) 448 continue; 449 450 /* Keep a copy of the last seen HT rate index */ 451 if (rt->info[rix].phy == IEEE80211_T_HT) 452 ht_rix = rix; 453 454 /* Skip non-HT rates */ 455 if (rt->info[rix].phy != IEEE80211_T_HT) 456 continue; 457 458 /* 459 * Pick a medium-speed rate regardless of stream count 460 * which has not seen any failures. Higher rates may fail; 461 * we'll try them later. 462 */ 463 if (((MCS(rix) & 0x7) <= 4) && 464 sn->stats[size_bin][rix].successive_failures == 0) { 465 break; 466 } 467 } 468 469 /* 470 * If all the MCS rates have successive failures, rix should be 471 * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.) 472 */ 473 return MAX(rix, ht_rix); 474#undef RATE 475#undef MCS 476#undef DOT11RATE 477} 478 479 480void 481ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, 482 int shortPreamble, size_t frameLen, 483 u_int8_t *rix0, int *try0, u_int8_t *txrate) 484{ 485#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) 486#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) 487#define RATE(ix) (DOT11RATE(ix) / 2) 488 struct sample_node *sn = ATH_NODE_SAMPLE(an); 489 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 490 struct ifnet *ifp = sc->sc_ifp; 491 struct ieee80211com *ic = ifp->if_l2com; 492 const HAL_RATE_TABLE *rt = sc->sc_currates; 493 const int size_bin = size_to_bin(frameLen); 494 int rix, mrr, best_rix, change_rates; 495 unsigned average_tx_time; 496 497 ath_rate_update_static_rix(sc, &an->an_node); 498 499 if (sn->currates != sc->sc_currates) { 500 device_printf(sc->sc_dev, "%s: currates != sc_currates!\n", 501 __func__); 502 rix = 0; 503 *try0 = ATH_TXMAXTRY; 504 goto done; 505 } 506 507 if (sn->static_rix != -1) { 508 rix = sn->static_rix; 509 *try0 = ATH_TXMAXTRY; 510 goto done; 511 } 512 513 /* XXX TODO: this doesn't know about 11gn vs 11g protection; teach it */ 514 mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); 515 516 best_rix = pick_best_rate(an, rt, size_bin, !mrr); 517 if (best_rix >= 0) { 518 average_tx_time = sn->stats[size_bin][best_rix].average_tx_time; 519 } else { 520 average_tx_time = 0; 521 } 522 /* 523 * Limit the time measuring the performance of other tx 524 * rates to sample_rate% of the total transmission time. 525 */ 526 if (sn->sample_tt[size_bin] < average_tx_time * (sn->packets_since_sample[size_bin]*ssc->sample_rate/100)) { 527 rix = pick_sample_rate(ssc, an, rt, size_bin); 528 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, 529 &an->an_node, "att %d sample_tt %d size %u sample rate %d %s current rate %d %s", 530 average_tx_time, 531 sn->sample_tt[size_bin], 532 bin_to_size(size_bin), 533 dot11rate(rt, rix), 534 dot11rate_label(rt, rix), 535 dot11rate(rt, sn->current_rix[size_bin]), 536 dot11rate_label(rt, sn->current_rix[size_bin])); 537 if (rix != sn->current_rix[size_bin]) { 538 sn->current_sample_rix[size_bin] = rix; 539 } else { 540 sn->current_sample_rix[size_bin] = -1; 541 } 542 sn->packets_since_sample[size_bin] = 0; 543 } else { 544 change_rates = 0; 545 if (!sn->packets_sent[size_bin] || best_rix == -1) { 546 /* no packet has been sent successfully yet */ 547 change_rates = 1; 548 if (an->an_node.ni_flags & IEEE80211_NODE_HT) 549 best_rix = 550 ath_rate_pick_seed_rate_ht(sc, an, frameLen); 551 else 552 best_rix = 553 ath_rate_pick_seed_rate_legacy(sc, an, frameLen); 554 } else if (sn->packets_sent[size_bin] < 20) { 555 /* let the bit-rate switch quickly during the first few packets */ 556 IEEE80211_NOTE(an->an_node.ni_vap, 557 IEEE80211_MSG_RATECTL, &an->an_node, 558 "%s: switching quickly..", __func__); 559 change_rates = 1; 560 } else if (ticks - ssc->min_switch > sn->ticks_since_switch[size_bin]) { 561 /* min_switch seconds have gone by */ 562 IEEE80211_NOTE(an->an_node.ni_vap, 563 IEEE80211_MSG_RATECTL, &an->an_node, 564 "%s: min_switch %d > ticks_since_switch %d..", 565 __func__, ticks - ssc->min_switch, sn->ticks_since_switch[size_bin]); 566 change_rates = 1; 567 } else if ((! (an->an_node.ni_flags & IEEE80211_NODE_HT)) && 568 (2*average_tx_time < sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time)) { 569 /* the current bit-rate is twice as slow as the best one */ 570 IEEE80211_NOTE(an->an_node.ni_vap, 571 IEEE80211_MSG_RATECTL, &an->an_node, 572 "%s: 2x att (= %d) < cur_rix att %d", 573 __func__, 574 2 * average_tx_time, sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time); 575 change_rates = 1; 576 } else if ((an->an_node.ni_flags & IEEE80211_NODE_HT)) { 577 int cur_rix = sn->current_rix[size_bin]; 578 int cur_att = sn->stats[size_bin][cur_rix].average_tx_time; 579 /* 580 * If the node is HT, upgrade it if the MCS rate is 581 * higher and the average tx time is within 20% of 582 * the current rate. It can fail a little. 583 * 584 * This is likely not optimal! 585 */ 586#if 0 587 printf("cur rix/att %x/%d, best rix/att %x/%d\n", 588 MCS(cur_rix), cur_att, MCS(best_rix), average_tx_time); 589#endif 590 if ((MCS(best_rix) > MCS(cur_rix)) && 591 (average_tx_time * 8) <= (cur_att * 10)) { 592 IEEE80211_NOTE(an->an_node.ni_vap, 593 IEEE80211_MSG_RATECTL, &an->an_node, 594 "%s: HT: best_rix 0x%d > cur_rix 0x%x, average_tx_time %d, cur_att %d", 595 __func__, 596 MCS(best_rix), MCS(cur_rix), average_tx_time, cur_att); 597 change_rates = 1; 598 } 599 } 600 601 sn->packets_since_sample[size_bin]++; 602 603 if (change_rates) { 604 if (best_rix != sn->current_rix[size_bin]) { 605 IEEE80211_NOTE(an->an_node.ni_vap, 606 IEEE80211_MSG_RATECTL, 607 &an->an_node, 608"%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d", 609 __func__, 610 bin_to_size(size_bin), 611 RATE(sn->current_rix[size_bin]), 612 sn->stats[size_bin][sn->current_rix[size_bin]].average_tx_time, 613 sn->stats[size_bin][sn->current_rix[size_bin]].perfect_tx_time, 614 RATE(best_rix), 615 sn->stats[size_bin][best_rix].average_tx_time, 616 sn->stats[size_bin][best_rix].perfect_tx_time, 617 sn->packets_since_switch[size_bin], 618 mrr); 619 } 620 sn->packets_since_switch[size_bin] = 0; 621 sn->current_rix[size_bin] = best_rix; 622 sn->ticks_since_switch[size_bin] = ticks; 623 /* 624 * Set the visible txrate for this node. 625 */ 626 an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ? MCS(best_rix) : DOT11RATE(best_rix); 627 } 628 rix = sn->current_rix[size_bin]; 629 sn->packets_since_switch[size_bin]++; 630 } 631 *try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY; 632done: 633 634 /* 635 * This bug totally sucks and should be fixed. 636 * 637 * For now though, let's not panic, so we can start to figure 638 * out how to better reproduce it. 639 */ 640 if (rix < 0 || rix >= rt->rateCount) { 641 printf("%s: ERROR: rix %d out of bounds (rateCount=%d)\n", 642 __func__, 643 rix, 644 rt->rateCount); 645 rix = 0; /* XXX just default for now */ 646 } 647 KASSERT(rix >= 0 && rix < rt->rateCount, ("rix is %d", rix)); 648 649 *rix0 = rix; 650 *txrate = rt->info[rix].rateCode 651 | (shortPreamble ? rt->info[rix].shortPreamble : 0); 652 sn->packets_sent[size_bin]++; 653#undef DOT11RATE 654#undef MCS 655#undef RATE 656} 657 658/* 659 * Get the TX rates. Don't fiddle with short preamble flags for them; 660 * the caller can do that. 661 */ 662void 663ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, 664 uint8_t rix0, struct ath_rc_series *rc) 665{ 666 struct sample_node *sn = ATH_NODE_SAMPLE(an); 667 const struct txschedule *sched = &sn->sched[rix0]; 668 669 KASSERT(rix0 == sched->r0, ("rix0 (%x) != sched->r0 (%x)!\n", rix0, sched->r0)); 670 671 rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0; 672 673 rc[0].rix = sched->r0; 674 rc[1].rix = sched->r1; 675 rc[2].rix = sched->r2; 676 rc[3].rix = sched->r3; 677 678 rc[0].tries = sched->t0; 679 rc[1].tries = sched->t1; 680 rc[2].tries = sched->t2; 681 rc[3].tries = sched->t3; 682} 683 684void 685ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 686 struct ath_desc *ds, int shortPreamble, u_int8_t rix) 687{ 688 struct sample_node *sn = ATH_NODE_SAMPLE(an); 689 const struct txschedule *sched = &sn->sched[rix]; 690 const HAL_RATE_TABLE *rt = sc->sc_currates; 691 uint8_t rix1, s1code, rix2, s2code, rix3, s3code; 692 693 /* XXX precalculate short preamble tables */ 694 rix1 = sched->r1; 695 s1code = rt->info[rix1].rateCode 696 | (shortPreamble ? rt->info[rix1].shortPreamble : 0); 697 rix2 = sched->r2; 698 s2code = rt->info[rix2].rateCode 699 | (shortPreamble ? rt->info[rix2].shortPreamble : 0); 700 rix3 = sched->r3; 701 s3code = rt->info[rix3].rateCode 702 | (shortPreamble ? rt->info[rix3].shortPreamble : 0); 703 ath_hal_setupxtxdesc(sc->sc_ah, ds, 704 s1code, sched->t1, /* series 1 */ 705 s2code, sched->t2, /* series 2 */ 706 s3code, sched->t3); /* series 3 */ 707} 708 709/* 710 * Update the EWMA percentage. 711 * 712 * This is a simple hack to track an EWMA based on the current 713 * rate scenario. For the rate codes which failed, this will 714 * record a 0% against it. For the rate code which succeeded, 715 * EWMA will record the nbad*100/nframes percentage against it. 716 */ 717static void 718update_ewma_stats(struct ath_softc *sc, struct ath_node *an, 719 int frame_size, 720 int rix0, int tries0, 721 int rix1, int tries1, 722 int rix2, int tries2, 723 int rix3, int tries3, 724 int short_tries, int tries, int status, 725 int nframes, int nbad) 726{ 727 struct sample_node *sn = ATH_NODE_SAMPLE(an); 728 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 729 const int size_bin = size_to_bin(frame_size); 730 int tries_so_far; 731 int pct; 732 int rix = rix0; 733 734 /* Calculate percentage based on current rate */ 735 if (nframes == 0) 736 nframes = nbad = 1; 737 pct = ((nframes - nbad) * 1000) / nframes; 738 739 /* Figure out which rate index succeeded */ 740 tries_so_far = tries0; 741 742 if (tries1 && tries_so_far < tries) { 743 tries_so_far += tries1; 744 rix = rix1; 745 /* XXX bump ewma pct */ 746 } 747 748 if (tries2 && tries_so_far < tries) { 749 tries_so_far += tries2; 750 rix = rix2; 751 /* XXX bump ewma pct */ 752 } 753 754 if (tries3 && tries_so_far < tries) { 755 rix = rix3; 756 /* XXX bump ewma pct */ 757 } 758 759 /* rix is the successful rate, update EWMA for final rix */ 760 if (sn->stats[size_bin][rix].total_packets < 761 ssc->smoothing_minpackets) { 762 /* just average the first few packets */ 763 int a_pct = (sn->stats[size_bin][rix].packets_acked * 1000) / 764 (sn->stats[size_bin][rix].total_packets); 765 sn->stats[size_bin][rix].ewma_pct = a_pct; 766 } else { 767 /* use a ewma */ 768 sn->stats[size_bin][rix].ewma_pct = 769 ((sn->stats[size_bin][rix].ewma_pct * ssc->smoothing_rate) + 770 (pct * (100 - ssc->smoothing_rate))) / 100; 771 } 772} 773 774static void 775update_stats(struct ath_softc *sc, struct ath_node *an, 776 int frame_size, 777 int rix0, int tries0, 778 int rix1, int tries1, 779 int rix2, int tries2, 780 int rix3, int tries3, 781 int short_tries, int tries, int status, 782 int nframes, int nbad) 783{ 784 struct sample_node *sn = ATH_NODE_SAMPLE(an); 785 struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc); 786#ifdef IEEE80211_DEBUG 787 const HAL_RATE_TABLE *rt = sc->sc_currates; 788#endif 789 const int size_bin = size_to_bin(frame_size); 790 const int size = bin_to_size(size_bin); 791 int tt, tries_so_far; 792 int is_ht40 = (an->an_node.ni_chw == 40); 793 794 if (!IS_RATE_DEFINED(sn, rix0)) 795 return; 796 tt = calc_usecs_unicast_packet(sc, size, rix0, short_tries, 797 MIN(tries0, tries) - 1, is_ht40); 798 tries_so_far = tries0; 799 800 if (tries1 && tries_so_far < tries) { 801 if (!IS_RATE_DEFINED(sn, rix1)) 802 return; 803 tt += calc_usecs_unicast_packet(sc, size, rix1, short_tries, 804 MIN(tries1 + tries_so_far, tries) - tries_so_far - 1, is_ht40); 805 tries_so_far += tries1; 806 } 807 808 if (tries2 && tries_so_far < tries) { 809 if (!IS_RATE_DEFINED(sn, rix2)) 810 return; 811 tt += calc_usecs_unicast_packet(sc, size, rix2, short_tries, 812 MIN(tries2 + tries_so_far, tries) - tries_so_far - 1, is_ht40); 813 tries_so_far += tries2; 814 } 815 816 if (tries3 && tries_so_far < tries) { 817 if (!IS_RATE_DEFINED(sn, rix3)) 818 return; 819 tt += calc_usecs_unicast_packet(sc, size, rix3, short_tries, 820 MIN(tries3 + tries_so_far, tries) - tries_so_far - 1, is_ht40); 821 } 822 823 if (sn->stats[size_bin][rix0].total_packets < ssc->smoothing_minpackets) { 824 /* just average the first few packets */ 825 int avg_tx = sn->stats[size_bin][rix0].average_tx_time; 826 int packets = sn->stats[size_bin][rix0].total_packets; 827 sn->stats[size_bin][rix0].average_tx_time = (tt+(avg_tx*packets))/(packets+nframes); 828 } else { 829 /* use a ewma */ 830 sn->stats[size_bin][rix0].average_tx_time = 831 ((sn->stats[size_bin][rix0].average_tx_time * ssc->smoothing_rate) + 832 (tt * (100 - ssc->smoothing_rate))) / 100; 833 } 834 835 /* 836 * XXX Don't mark the higher bit rates as also having failed; as this 837 * unfortunately stops those rates from being tasted when trying to 838 * TX. This happens with 11n aggregation. 839 */ 840 if (nframes == nbad) { 841#if 0 842 int y; 843#endif 844 sn->stats[size_bin][rix0].successive_failures += nbad; 845#if 0 846 for (y = size_bin+1; y < NUM_PACKET_SIZE_BINS; y++) { 847 /* 848 * Also say larger packets failed since we 849 * assume if a small packet fails at a 850 * bit-rate then a larger one will also. 851 */ 852 sn->stats[y][rix0].successive_failures += nbad; 853 sn->stats[y][rix0].last_tx = ticks; 854 sn->stats[y][rix0].tries += tries; 855 sn->stats[y][rix0].total_packets += nframes; 856 } 857#endif 858 } else { 859 sn->stats[size_bin][rix0].packets_acked += (nframes - nbad); 860 sn->stats[size_bin][rix0].successive_failures = 0; 861 } 862 sn->stats[size_bin][rix0].tries += tries; 863 sn->stats[size_bin][rix0].last_tx = ticks; 864 sn->stats[size_bin][rix0].total_packets += nframes; 865 866 if (rix0 == sn->current_sample_rix[size_bin]) { 867 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, 868 &an->an_node, 869"%s: size %d %s sample rate %d %s tries (%d/%d) tt %d avg_tt (%d/%d) nfrm %d nbad %d", 870 __func__, 871 size, 872 status ? "FAIL" : "OK", 873 dot11rate(rt, rix0), 874 dot11rate_label(rt, rix0), 875 short_tries, tries, tt, 876 sn->stats[size_bin][rix0].average_tx_time, 877 sn->stats[size_bin][rix0].perfect_tx_time, 878 nframes, nbad); 879 sn->sample_tt[size_bin] = tt; 880 sn->current_sample_rix[size_bin] = -1; 881 } 882} 883 884static void 885badrate(struct ifnet *ifp, int series, int hwrate, int tries, int status) 886{ 887 if_printf(ifp, "bad series%d hwrate 0x%x, tries %u ts_status 0x%x\n", 888 series, hwrate, tries, status); 889} 890 891void 892ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, 893 const struct ath_rc_series *rc, const struct ath_tx_status *ts, 894 int frame_size, int nframes, int nbad) 895{ 896 struct ifnet *ifp = sc->sc_ifp; 897 struct ieee80211com *ic = ifp->if_l2com; 898 struct sample_node *sn = ATH_NODE_SAMPLE(an); 899 int final_rix, short_tries, long_tries; 900 const HAL_RATE_TABLE *rt = sc->sc_currates; 901 int status = ts->ts_status; 902 int mrr; 903 904 final_rix = rt->rateCodeToIndex[ts->ts_rate]; 905 short_tries = ts->ts_shortretry; 906 long_tries = ts->ts_longretry + 1; 907 908 if (frame_size == 0) /* NB: should not happen */ 909 frame_size = 1500; 910 911 if (sn->ratemask == 0) { 912 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, 913 &an->an_node, 914 "%s: size %d %s rate/try %d/%d no rates yet", 915 __func__, 916 bin_to_size(size_to_bin(frame_size)), 917 status ? "FAIL" : "OK", 918 short_tries, long_tries); 919 return; 920 } 921 mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT); 922 if (!mrr || ts->ts_finaltsi == 0) { 923 if (!IS_RATE_DEFINED(sn, final_rix)) { 924 badrate(ifp, 0, ts->ts_rate, long_tries, status); 925 return; 926 } 927 /* 928 * Only one rate was used; optimize work. 929 */ 930 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, 931 &an->an_node, "%s: size %d (%d bytes) %s rate/try %d %s/%d/%d nframes/nbad [%d/%d]", 932 __func__, 933 bin_to_size(size_to_bin(frame_size)), 934 frame_size, 935 status ? "FAIL" : "OK", 936 dot11rate(rt, final_rix), dot11rate_label(rt, final_rix), 937 short_tries, long_tries, nframes, nbad); 938 update_stats(sc, an, frame_size, 939 final_rix, long_tries, 940 0, 0, 941 0, 0, 942 0, 0, 943 short_tries, long_tries, status, 944 nframes, nbad); 945 update_ewma_stats(sc, an, frame_size, 946 final_rix, long_tries, 947 0, 0, 948 0, 0, 949 0, 0, 950 short_tries, long_tries, status, 951 nframes, nbad); 952 953 } else { 954 int finalTSIdx = ts->ts_finaltsi; 955 int i; 956 957 /* 958 * Process intermediate rates that failed. 959 */ 960 961 IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL, 962 &an->an_node, 963"%s: size %d (%d bytes) finaltsidx %d tries %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d] nframes/nbad [%d/%d]", 964 __func__, 965 bin_to_size(size_to_bin(frame_size)), 966 frame_size, 967 finalTSIdx, 968 long_tries, 969 status ? "FAIL" : "OK", 970 dot11rate(rt, rc[0].rix), 971 dot11rate_label(rt, rc[0].rix), rc[0].tries, 972 dot11rate(rt, rc[1].rix), 973 dot11rate_label(rt, rc[1].rix), rc[1].tries, 974 dot11rate(rt, rc[2].rix), 975 dot11rate_label(rt, rc[2].rix), rc[2].tries, 976 dot11rate(rt, rc[3].rix), 977 dot11rate_label(rt, rc[3].rix), rc[3].tries, 978 nframes, nbad); 979 980 for (i = 0; i < 4; i++) { 981 if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix)) 982 badrate(ifp, 0, rc[i].ratecode, rc[i].tries, 983 status); 984 } 985 986 /* 987 * NB: series > 0 are not penalized for failure 988 * based on the try counts under the assumption 989 * that losses are often bursty and since we 990 * sample higher rates 1 try at a time doing so 991 * may unfairly penalize them. 992 */ 993 if (rc[0].tries) { 994 update_stats(sc, an, frame_size, 995 rc[0].rix, rc[0].tries, 996 rc[1].rix, rc[1].tries, 997 rc[2].rix, rc[2].tries, 998 rc[3].rix, rc[3].tries, 999 short_tries, long_tries, 1000 long_tries > rc[0].tries, 1001 nframes, nbad); 1002 long_tries -= rc[0].tries; 1003 } 1004 1005 if (rc[1].tries && finalTSIdx > 0) { 1006 update_stats(sc, an, frame_size, 1007 rc[1].rix, rc[1].tries, 1008 rc[2].rix, rc[2].tries, 1009 rc[3].rix, rc[3].tries, 1010 0, 0, 1011 short_tries, long_tries, 1012 status, 1013 nframes, nbad); 1014 long_tries -= rc[1].tries; 1015 } 1016 1017 if (rc[2].tries && finalTSIdx > 1) { 1018 update_stats(sc, an, frame_size, 1019 rc[2].rix, rc[2].tries, 1020 rc[3].rix, rc[3].tries, 1021 0, 0, 1022 0, 0, 1023 short_tries, long_tries, 1024 status, 1025 nframes, nbad); 1026 long_tries -= rc[2].tries; 1027 } 1028 1029 if (rc[3].tries && finalTSIdx > 2) { 1030 update_stats(sc, an, frame_size, 1031 rc[3].rix, rc[3].tries, 1032 0, 0, 1033 0, 0, 1034 0, 0, 1035 short_tries, long_tries, 1036 status, 1037 nframes, nbad); 1038 } 1039 1040 update_ewma_stats(sc, an, frame_size, 1041 rc[0].rix, rc[0].tries, 1042 rc[1].rix, rc[1].tries, 1043 rc[2].rix, rc[2].tries, 1044 rc[3].rix, rc[3].tries, 1045 short_tries, long_tries, 1046 long_tries > rc[0].tries, 1047 nframes, nbad); 1048 1049 } 1050} 1051 1052void 1053ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 1054{ 1055 if (isnew) 1056 ath_rate_ctl_reset(sc, &an->an_node); 1057} 1058 1059static const struct txschedule *mrr_schedules[IEEE80211_MODE_MAX+2] = { 1060 NULL, /* IEEE80211_MODE_AUTO */ 1061 series_11a, /* IEEE80211_MODE_11A */ 1062 series_11g, /* IEEE80211_MODE_11B */ 1063 series_11g, /* IEEE80211_MODE_11G */ 1064 NULL, /* IEEE80211_MODE_FH */ 1065 series_11a, /* IEEE80211_MODE_TURBO_A */ 1066 series_11g, /* IEEE80211_MODE_TURBO_G */ 1067 series_11a, /* IEEE80211_MODE_STURBO_A */ 1068 series_11na, /* IEEE80211_MODE_11NA */ 1069 series_11ng, /* IEEE80211_MODE_11NG */ 1070 series_half, /* IEEE80211_MODE_HALF */ 1071 series_quarter, /* IEEE80211_MODE_QUARTER */ 1072}; 1073 1074/* 1075 * Initialize the tables for a node. 1076 */ 1077static void 1078ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) 1079{ 1080#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 1081#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) 1082#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) 1083 struct ath_node *an = ATH_NODE(ni); 1084 struct sample_node *sn = ATH_NODE_SAMPLE(an); 1085 const HAL_RATE_TABLE *rt = sc->sc_currates; 1086 int x, y, rix; 1087 1088 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 1089 1090 KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2, 1091 ("curmode %u", sc->sc_curmode)); 1092 sn->sched = mrr_schedules[sc->sc_curmode]; 1093 KASSERT(sn->sched != NULL, 1094 ("no mrr schedule for mode %u", sc->sc_curmode)); 1095 1096 sn->static_rix = -1; 1097 ath_rate_update_static_rix(sc, ni); 1098 1099 sn->currates = sc->sc_currates; 1100 1101 /* 1102 * Construct a bitmask of usable rates. This has all 1103 * negotiated rates minus those marked by the hal as 1104 * to be ignored for doing rate control. 1105 */ 1106 sn->ratemask = 0; 1107 /* MCS rates */ 1108 if (ni->ni_flags & IEEE80211_NODE_HT) { 1109 for (x = 0; x < ni->ni_htrates.rs_nrates; x++) { 1110 rix = sc->sc_rixmap[MCS(x)]; 1111 if (rix == 0xff) 1112 continue; 1113 /* skip rates marked broken by hal */ 1114 if (!rt->info[rix].valid) 1115 continue; 1116 KASSERT(rix < SAMPLE_MAXRATES, 1117 ("mcs %u has rix %d", MCS(x), rix)); 1118 sn->ratemask |= 1<<rix; 1119 } 1120 } 1121 1122 /* Legacy rates */ 1123 for (x = 0; x < ni->ni_rates.rs_nrates; x++) { 1124 rix = sc->sc_rixmap[RATE(x)]; 1125 if (rix == 0xff) 1126 continue; 1127 /* skip rates marked broken by hal */ 1128 if (!rt->info[rix].valid) 1129 continue; 1130 KASSERT(rix < SAMPLE_MAXRATES, 1131 ("rate %u has rix %d", RATE(x), rix)); 1132 sn->ratemask |= 1<<rix; 1133 } 1134#ifdef IEEE80211_DEBUG 1135 if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) { 1136 uint32_t mask; 1137 1138 ieee80211_note(ni->ni_vap, "[%6D] %s: size 1600 rate/tt", 1139 ni->ni_macaddr, ":", __func__); 1140 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { 1141 if ((mask & 1) == 0) 1142 continue; 1143 printf(" %d %s/%d", dot11rate(rt, rix), dot11rate_label(rt, rix), 1144 calc_usecs_unicast_packet(sc, 1600, rix, 0,0, 1145 (ni->ni_chw == 40))); 1146 } 1147 printf("\n"); 1148 } 1149#endif 1150 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { 1151 int size = bin_to_size(y); 1152 uint32_t mask; 1153 1154 sn->packets_sent[y] = 0; 1155 sn->current_sample_rix[y] = -1; 1156 sn->last_sample_rix[y] = 0; 1157 /* XXX start with first valid rate */ 1158 sn->current_rix[y] = ffs(sn->ratemask)-1; 1159 1160 /* 1161 * Initialize the statistics buckets; these are 1162 * indexed by the rate code index. 1163 */ 1164 for (rix = 0, mask = sn->ratemask; mask != 0; rix++, mask >>= 1) { 1165 if ((mask & 1) == 0) /* not a valid rate */ 1166 continue; 1167 sn->stats[y][rix].successive_failures = 0; 1168 sn->stats[y][rix].tries = 0; 1169 sn->stats[y][rix].total_packets = 0; 1170 sn->stats[y][rix].packets_acked = 0; 1171 sn->stats[y][rix].last_tx = 0; 1172 sn->stats[y][rix].ewma_pct = 0; 1173 1174 sn->stats[y][rix].perfect_tx_time = 1175 calc_usecs_unicast_packet(sc, size, rix, 0, 0, 1176 (ni->ni_chw == 40)); 1177 sn->stats[y][rix].average_tx_time = 1178 sn->stats[y][rix].perfect_tx_time; 1179 } 1180 } 1181#if 0 1182 /* XXX 0, num_rates-1 are wrong */ 1183 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, 1184 "%s: %d rates %d%sMbps (%dus)- %d%sMbps (%dus)", __func__, 1185 sn->num_rates, 1186 DOT11RATE(0)/2, DOT11RATE(0) % 1 ? ".5" : "", 1187 sn->stats[1][0].perfect_tx_time, 1188 DOT11RATE(sn->num_rates-1)/2, DOT11RATE(sn->num_rates-1) % 1 ? ".5" : "", 1189 sn->stats[1][sn->num_rates-1].perfect_tx_time 1190 ); 1191#endif 1192 /* set the visible bit-rate */ 1193 if (sn->static_rix != -1) 1194 ni->ni_txrate = DOT11RATE(sn->static_rix); 1195 else 1196 ni->ni_txrate = RATE(0); 1197#undef RATE 1198#undef DOT11RATE 1199} 1200 1201static void 1202sample_stats(void *arg, struct ieee80211_node *ni) 1203{ 1204 struct ath_softc *sc = arg; 1205 const HAL_RATE_TABLE *rt = sc->sc_currates; 1206 struct sample_node *sn = ATH_NODE_SAMPLE(ATH_NODE(ni)); 1207 uint32_t mask; 1208 int rix, y; 1209 1210 printf("\n[%s] refcnt %d static_rix (%d %s) ratemask 0x%x\n", 1211 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni), 1212 dot11rate(rt, sn->static_rix), 1213 dot11rate_label(rt, sn->static_rix), 1214 sn->ratemask); 1215 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { 1216 printf("[%4u] cur rix %d (%d %s) since switch: packets %d ticks %u\n", 1217 bin_to_size(y), sn->current_rix[y], 1218 dot11rate(rt, sn->current_rix[y]), 1219 dot11rate_label(rt, sn->current_rix[y]), 1220 sn->packets_since_switch[y], sn->ticks_since_switch[y]); 1221 printf("[%4u] last sample (%d %s) cur sample (%d %s) packets sent %d\n", 1222 bin_to_size(y), 1223 dot11rate(rt, sn->last_sample_rix[y]), 1224 dot11rate_label(rt, sn->last_sample_rix[y]), 1225 dot11rate(rt, sn->current_sample_rix[y]), 1226 dot11rate_label(rt, sn->current_sample_rix[y]), 1227 sn->packets_sent[y]); 1228 printf("[%4u] packets since sample %d sample tt %u\n", 1229 bin_to_size(y), sn->packets_since_sample[y], 1230 sn->sample_tt[y]); 1231 } 1232 for (mask = sn->ratemask, rix = 0; mask != 0; mask >>= 1, rix++) { 1233 if ((mask & 1) == 0) 1234 continue; 1235 for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) { 1236 if (sn->stats[y][rix].total_packets == 0) 1237 continue; 1238 printf("[%2u %s:%4u] %8ju:%-8ju (%3d%%) (EWMA %3d.%1d%%) T %8ju F %4d avg %5u last %u\n", 1239 dot11rate(rt, rix), dot11rate_label(rt, rix), 1240 bin_to_size(y), 1241 (uintmax_t) sn->stats[y][rix].total_packets, 1242 (uintmax_t) sn->stats[y][rix].packets_acked, 1243 (int) ((sn->stats[y][rix].packets_acked * 100ULL) / 1244 sn->stats[y][rix].total_packets), 1245 sn->stats[y][rix].ewma_pct / 10, 1246 sn->stats[y][rix].ewma_pct % 10, 1247 (uintmax_t) sn->stats[y][rix].tries, 1248 sn->stats[y][rix].successive_failures, 1249 sn->stats[y][rix].average_tx_time, 1250 ticks - sn->stats[y][rix].last_tx); 1251 } 1252 } 1253} 1254 1255static int 1256ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS) 1257{ 1258 struct ath_softc *sc = arg1; 1259 struct ifnet *ifp = sc->sc_ifp; 1260 struct ieee80211com *ic = ifp->if_l2com; 1261 int error, v; 1262 1263 v = 0; 1264 error = sysctl_handle_int(oidp, &v, 0, req); 1265 if (error || !req->newptr) 1266 return error; 1267 ieee80211_iterate_nodes(&ic->ic_sta, sample_stats, sc); 1268 return 0; 1269} 1270 1271static int 1272ath_rate_sysctl_smoothing_rate(SYSCTL_HANDLER_ARGS) 1273{ 1274 struct sample_softc *ssc = arg1; 1275 int rate, error; 1276 1277 rate = ssc->smoothing_rate; 1278 error = sysctl_handle_int(oidp, &rate, 0, req); 1279 if (error || !req->newptr) 1280 return error; 1281 if (!(0 <= rate && rate < 100)) 1282 return EINVAL; 1283 ssc->smoothing_rate = rate; 1284 ssc->smoothing_minpackets = 100 / (100 - rate); 1285 return 0; 1286} 1287 1288static int 1289ath_rate_sysctl_sample_rate(SYSCTL_HANDLER_ARGS) 1290{ 1291 struct sample_softc *ssc = arg1; 1292 int rate, error; 1293 1294 rate = ssc->sample_rate; 1295 error = sysctl_handle_int(oidp, &rate, 0, req); 1296 if (error || !req->newptr) 1297 return error; 1298 if (!(2 <= rate && rate <= 100)) 1299 return EINVAL; 1300 ssc->sample_rate = rate; 1301 return 0; 1302} 1303 1304static void 1305ath_rate_sysctlattach(struct ath_softc *sc, struct sample_softc *ssc) 1306{ 1307 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 1308 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 1309 1310 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1311 "smoothing_rate", CTLTYPE_INT | CTLFLAG_RW, ssc, 0, 1312 ath_rate_sysctl_smoothing_rate, "I", 1313 "sample: smoothing rate for avg tx time (%%)"); 1314 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1315 "sample_rate", CTLTYPE_INT | CTLFLAG_RW, ssc, 0, 1316 ath_rate_sysctl_sample_rate, "I", 1317 "sample: percent air time devoted to sampling new rates (%%)"); 1318 /* XXX max_successive_failures, stale_failure_timeout, min_switch */ 1319 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1320 "sample_stats", CTLTYPE_INT | CTLFLAG_RW, sc, 0, 1321 ath_rate_sysctl_stats, "I", "sample: print statistics"); 1322} 1323 1324struct ath_ratectrl * 1325ath_rate_attach(struct ath_softc *sc) 1326{ 1327 struct sample_softc *ssc; 1328 1329 ssc = malloc(sizeof(struct sample_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 1330 if (ssc == NULL) 1331 return NULL; 1332 ssc->arc.arc_space = sizeof(struct sample_node); 1333 ssc->smoothing_rate = 95; /* ewma percentage ([0..99]) */ 1334 ssc->smoothing_minpackets = 100 / (100 - ssc->smoothing_rate); 1335 ssc->sample_rate = 10; /* %time to try diff tx rates */ 1336 ssc->max_successive_failures = 3; /* threshold for rate sampling*/ 1337 ssc->stale_failure_timeout = 10 * hz; /* 10 seconds */ 1338 ssc->min_switch = hz; /* 1 second */ 1339 ath_rate_sysctlattach(sc, ssc); 1340 return &ssc->arc; 1341} 1342 1343void 1344ath_rate_detach(struct ath_ratectrl *arc) 1345{ 1346 struct sample_softc *ssc = (struct sample_softc *) arc; 1347 1348 free(ssc, M_DEVBUF); 1349} 1350