1 /* $NetBSD: athrate-onoe.c,v 1.14 2009/03/27 16:10:50 dyoung Exp $ */ 2 3 /*- 4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer, 12 * without modification. 13 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 14 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 15 * redistribution must be conditioned upon including a substantially 16 * similar Disclaimer requirement for further binary redistribution. 17 * 3. Neither the names of the above-listed copyright holders nor the names 18 * of any contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * Alternatively, this software may be distributed under the terms of the 22 * GNU General Public License ("GPL") version 2 as published by the Free 23 * Software Foundation. 24 * 25 * NO WARRANTY 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 30 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 31 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 34 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 36 * THE POSSIBILITY OF SUCH DAMAGES. 37 */ 38 39 #include <sys/cdefs.h> 40 #ifdef __FreeBSD__ 41 __FBSDID("$FreeBSD: src/sys/dev/ath/ath_rate/onoe/onoe.c,v 1.10 2005/08/09 10:19:43 rwatson Exp $"); 42 #endif 43 #ifdef __NetBSD__ 44 __KERNEL_RCSID(0, "$NetBSD: athrate-onoe.c,v 1.14 2009/03/27 16:10:50 dyoung Exp $"); 45 #endif 46 47 /* 48 * Atsushi Onoe's rate control algorithm. 49 */ 50 #include "opt_inet.h" 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/sysctl.h> 55 #include <sys/kernel.h> 56 #include <sys/errno.h> 57 #include <sys/device.h> 58 #include <sys/bus.h> 59 #include <sys/socket.h> 60 61 #include <net/if.h> 62 #include <net/if_media.h> 63 #include <net/if_arp.h> 64 #include <net/if_ether.h> /* XXX for ether_sprintf */ 65 66 #include <net80211/ieee80211_var.h> 67 68 #include <net/bpf.h> 69 70 #ifdef INET 71 #include <netinet/in.h> 72 #endif 73 74 #include "ah_desc.h" 75 #include <dev/ic/ath_netbsd.h> 76 #include <dev/ic/athvar.h> 77 #include <dev/ic/athrate-onoe.h> 78 79 #include <external/isc/atheros_hal/dist/ah.h> 80 81 #ifndef ONOE_DEBUG 82 #define ONOE_DEBUG 83 #endif 84 85 #ifdef ONOE_DEBUG 86 enum { 87 ATH_DEBUG_RATE = 0x00000010, /* rate control */ 88 }; 89 #define DPRINTF(sc, _fmt, ...) do { \ 90 if (sc->sc_debug & ATH_DEBUG_RATE) \ 91 printf(_fmt, __VA_ARGS__); \ 92 } while (0) 93 #else 94 #define DPRINTF(sc, _fmt, ...) 95 #endif 96 97 /* 98 * Default parameters for the rate control algorithm. These are 99 * all tunable with sysctls. The rate controller runs periodically 100 * (each ath_rateinterval ms) analyzing transmit statistics for each 101 * neighbor/station (when operating in station mode this is only the AP). 102 * If transmits look to be working well over a sampling period then 103 * it gives a "raise rate credit". If transmits look to not be working 104 * well than it deducts a credit. If the credits cross a threshold then 105 * the transmit rate is raised. Various error conditions force the 106 * the transmit rate to be dropped. 107 * 108 * The decision to issue/deduct a credit is based on the errors and 109 * retries accumulated over the sampling period. ath_rate_raise defines 110 * the percent of retransmits for which a credit is issued/deducted. 111 * ath_rate_raise_threshold defines the threshold on credits at which 112 * the transmit rate is increased. 113 * 114 * XXX this algorithm is flawed. 115 */ 116 static int ath_rateinterval = 1000; /* rate ctl interval (ms) */ 117 static int ath_rate_raise = 10; /* add credit threshold */ 118 static int ath_rate_raise_threshold = 10; /* rate ctl raise threshold */ 119 120 static void ath_ratectl(void *); 121 static void ath_rate_update(struct ath_softc *, struct ieee80211_node *, 122 int rate); 123 static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *); 124 static void ath_rate_ctl(void *, struct ieee80211_node *); 125 126 void 127 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) 128 { 129 /* NB: assumed to be zero'd by caller */ 130 ath_rate_update(sc, &an->an_node, 0); 131 } 132 133 void 134 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 135 { 136 } 137 138 void 139 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, 140 int shortPreamble, size_t frameLen, 141 u_int8_t *rix, int *try0, u_int8_t *txrate) 142 { 143 struct onoe_node *on = ATH_NODE_ONOE(an); 144 145 *rix = on->on_tx_rix0; 146 *try0 = on->on_tx_try0; 147 if (shortPreamble) 148 *txrate = on->on_tx_rate0sp; 149 else 150 *txrate = on->on_tx_rate0; 151 } 152 153 void 154 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 155 struct ath_desc *ds, int shortPreamble, u_int8_t rix) 156 { 157 struct onoe_node *on = ATH_NODE_ONOE(an); 158 159 ath_hal_setupxtxdesc(sc->sc_ah, ds 160 , on->on_tx_rate1sp, 2 /* series 1 */ 161 , on->on_tx_rate2sp, 2 /* series 2 */ 162 , on->on_tx_rate3sp, 2 /* series 3 */ 163 ); 164 } 165 166 void 167 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, 168 const struct ath_desc *ds, const struct ath_desc *ds0) 169 { 170 struct onoe_node *on = ATH_NODE_ONOE(an); 171 172 if (ds->ds_txstat.ts_status == 0) 173 on->on_tx_ok++; 174 else 175 on->on_tx_err++; 176 on->on_tx_retr += ds->ds_txstat.ts_shortretry 177 + ds->ds_txstat.ts_longretry; 178 } 179 180 void 181 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 182 { 183 if (isnew) 184 ath_rate_ctl_start(sc, &an->an_node); 185 } 186 187 static void 188 ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate) 189 { 190 struct ath_node *an = ATH_NODE(ni); 191 struct onoe_node *on = ATH_NODE_ONOE(an); 192 const HAL_RATE_TABLE *rt = sc->sc_currates; 193 u_int8_t rix; 194 195 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 196 197 DPRINTF(sc, "%s: set xmit rate for %s to %dM\n", 198 __func__, ether_sprintf(ni->ni_macaddr), 199 ni->ni_rates.rs_nrates > 0 ? 200 (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0); 201 202 ni->ni_txrate = rate; 203 /* 204 * Before associating a node has no rate set setup 205 * so we can't calculate any transmit codes to use. 206 * This is ok since we should never be sending anything 207 * but management frames and those always go at the 208 * lowest hardware rate. 209 */ 210 if (ni->ni_rates.rs_nrates == 0) 211 goto done; 212 on->on_tx_rix0 = sc->sc_rixmap[ 213 ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL]; 214 on->on_tx_rate0 = rt->info[on->on_tx_rix0].rateCode; 215 216 on->on_tx_rate0sp = on->on_tx_rate0 | 217 rt->info[on->on_tx_rix0].shortPreamble; 218 if (sc->sc_mrretry) { 219 /* 220 * Hardware supports multi-rate retry; setup two 221 * step-down retry rates and make the lowest rate 222 * be the ``last chance''. We use 4, 2, 2, 2 tries 223 * respectively (4 is set here, the rest are fixed 224 * in the xmit routine). 225 */ 226 on->on_tx_try0 = 1 + 3; /* 4 tries at rate 0 */ 227 if (--rate >= 0) { 228 rix = sc->sc_rixmap[ 229 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 230 on->on_tx_rate1 = rt->info[rix].rateCode; 231 on->on_tx_rate1sp = on->on_tx_rate1 | 232 rt->info[rix].shortPreamble; 233 } else { 234 on->on_tx_rate1 = on->on_tx_rate1sp = 0; 235 } 236 if (--rate >= 0) { 237 rix = sc->sc_rixmap[ 238 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 239 on->on_tx_rate2 = rt->info[rix].rateCode; 240 on->on_tx_rate2sp = on->on_tx_rate2 | 241 rt->info[rix].shortPreamble; 242 } else { 243 on->on_tx_rate2 = on->on_tx_rate2sp = 0; 244 } 245 if (rate > 0) { 246 /* NB: only do this if we didn't already do it above */ 247 on->on_tx_rate3 = rt->info[0].rateCode; 248 on->on_tx_rate3sp = 249 on->on_tx_rate3 | rt->info[0].shortPreamble; 250 } else { 251 on->on_tx_rate3 = on->on_tx_rate3sp = 0; 252 } 253 } else { 254 on->on_tx_try0 = ATH_TXMAXTRY; /* max tries at rate 0 */ 255 on->on_tx_rate1 = on->on_tx_rate1sp = 0; 256 on->on_tx_rate2 = on->on_tx_rate2sp = 0; 257 on->on_tx_rate3 = on->on_tx_rate3sp = 0; 258 } 259 done: 260 on->on_tx_ok = on->on_tx_err = on->on_tx_retr = on->on_tx_upper = 0; 261 } 262 263 /* 264 * Set the starting transmit rate for a node. 265 */ 266 static void 267 ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) 268 { 269 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 270 struct ieee80211com *ic = &sc->sc_ic; 271 int srate; 272 273 KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); 274 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { 275 /* 276 * No fixed rate is requested. For 11b start with 277 * the highest negotiated rate; otherwise, for 11g 278 * and 11a, we start "in the middle" at 24Mb or 36Mb. 279 */ 280 srate = ni->ni_rates.rs_nrates - 1; 281 if (sc->sc_curmode != IEEE80211_MODE_11B) { 282 /* 283 * Scan the negotiated rate set to find the 284 * closest rate. 285 */ 286 /* NB: the rate set is assumed sorted */ 287 for (; srate >= 0 && RATE(srate) > 72; srate--) 288 ; 289 KASSERT(srate >= 0, ("bogus rate set")); 290 } 291 } else { 292 /* 293 * A fixed rate is to be used; ic_fixed_rate is an 294 * index into the supported rate set. Convert this 295 * to the index into the negotiated rate set for 296 * the node. We know the rate is there because the 297 * rate set is checked when the station associates. 298 */ 299 const struct ieee80211_rateset *rs = 300 &ic->ic_sup_rates[ic->ic_curmode]; 301 int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; 302 /* NB: the rate set is assumed sorted */ 303 srate = ni->ni_rates.rs_nrates - 1; 304 for (; srate >= 0 && RATE(srate) != r; srate--) 305 ; 306 KASSERT(srate >= 0, 307 ("fixed rate %d not in rate set", ic->ic_fixed_rate)); 308 } 309 ath_rate_update(sc, ni, srate); 310 #undef RATE 311 } 312 313 static void 314 ath_rate_cb(void *arg, struct ieee80211_node *ni) 315 { 316 struct ath_softc *sc = arg; 317 318 ath_rate_update(sc, ni, 0); 319 } 320 321 /* 322 * Reset the rate control state for each 802.11 state transition. 323 */ 324 void 325 ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state) 326 { 327 struct onoe_softc *osc = (struct onoe_softc *) sc->sc_rc; 328 struct ieee80211com *ic = &sc->sc_ic; 329 struct ieee80211_node *ni; 330 331 if (state == IEEE80211_S_INIT) { 332 callout_stop(&osc->timer); 333 return; 334 } 335 if (ic->ic_opmode == IEEE80211_M_STA) { 336 /* 337 * Reset local xmit state; this is really only 338 * meaningful when operating in station mode. 339 */ 340 ni = ic->ic_bss; 341 if (state == IEEE80211_S_RUN) { 342 ath_rate_ctl_start(sc, ni); 343 } else { 344 ath_rate_update(sc, ni, 0); 345 } 346 } else { 347 /* 348 * When operating as a station the node table holds 349 * the AP's that were discovered during scanning. 350 * For any other operating mode we want to reset the 351 * tx rate state of each node. 352 */ 353 ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, sc); 354 ath_rate_update(sc, ic->ic_bss, 0); 355 } 356 if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE && 357 state == IEEE80211_S_RUN) { 358 int interval; 359 /* 360 * Start the background rate control thread if we 361 * are not configured to use a fixed xmit rate. 362 */ 363 interval = ath_rateinterval; 364 if (ic->ic_opmode == IEEE80211_M_STA) 365 interval /= 2; 366 callout_reset(&osc->timer, (interval * hz) / 1000, 367 ath_ratectl, &sc->sc_if); 368 } 369 } 370 371 /* 372 * Examine and potentially adjust the transmit rate. 373 */ 374 static void 375 ath_rate_ctl(void *arg, struct ieee80211_node *ni) 376 { 377 struct ath_softc *sc = arg; 378 struct onoe_node *on = ATH_NODE_ONOE(ATH_NODE(ni)); 379 struct ieee80211_rateset *rs = &ni->ni_rates; 380 int dir = 0, nrate, enough; 381 382 /* 383 * Rate control 384 * XXX: very primitive version. 385 */ 386 enough = (on->on_tx_ok + on->on_tx_err >= 10); 387 388 /* no packet reached -> down */ 389 if (on->on_tx_err > 0 && on->on_tx_ok == 0) 390 dir = -1; 391 392 /* all packets needs retry in average -> down */ 393 if (enough && on->on_tx_ok < on->on_tx_retr) 394 dir = -1; 395 396 /* no error and less than rate_raise% of packets need retry -> up */ 397 if (enough && on->on_tx_err == 0 && 398 on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100) 399 dir = 1; 400 401 DPRINTF(sc, "%s: ok %d err %d retr %d upper %d dir %d\n", 402 ether_sprintf(ni->ni_macaddr), 403 on->on_tx_ok, on->on_tx_err, on->on_tx_retr, 404 on->on_tx_upper, dir); 405 406 nrate = ni->ni_txrate; 407 switch (dir) { 408 case 0: 409 if (enough && on->on_tx_upper > 0) 410 on->on_tx_upper--; 411 break; 412 case -1: 413 if (nrate > 0) { 414 nrate--; 415 sc->sc_stats.ast_rate_drop++; 416 } 417 on->on_tx_upper = 0; 418 break; 419 case 1: 420 /* raise rate if we hit rate_raise_threshold */ 421 if (++on->on_tx_upper < ath_rate_raise_threshold) 422 break; 423 on->on_tx_upper = 0; 424 if (nrate + 1 < rs->rs_nrates) { 425 nrate++; 426 sc->sc_stats.ast_rate_raise++; 427 } 428 break; 429 } 430 431 if (nrate != ni->ni_txrate) { 432 DPRINTF(sc, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n", 433 __func__, 434 (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2, 435 (rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2, 436 on->on_tx_ok, on->on_tx_err, on->on_tx_retr); 437 ath_rate_update(sc, ni, nrate); 438 } else if (enough) 439 on->on_tx_ok = on->on_tx_err = on->on_tx_retr = 0; 440 } 441 442 static void 443 ath_ratectl(void *arg) 444 { 445 struct ifnet *ifp = arg; 446 struct ath_softc *sc = ifp->if_softc; 447 struct onoe_softc *osc = (struct onoe_softc *) sc->sc_rc; 448 struct ieee80211com *ic = &sc->sc_ic; 449 int interval; 450 451 if (ifp->if_flags & IFF_RUNNING) { 452 sc->sc_stats.ast_rate_calls++; 453 454 if (ic->ic_opmode == IEEE80211_M_STA) 455 ath_rate_ctl(sc, ic->ic_bss); /* NB: no reference */ 456 else 457 ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_ctl, sc); 458 } 459 interval = ath_rateinterval; 460 if (ic->ic_opmode == IEEE80211_M_STA) 461 interval /= 2; 462 callout_reset(&osc->timer, (interval * hz) / 1000, 463 ath_ratectl, &sc->sc_if); 464 } 465 466 static void 467 ath_rate_sysctlattach(struct ath_softc *sc) 468 { 469 struct sysctllog **clog = &sc->sc_sysctllog; 470 const struct sysctlnode *cnode, *rnode; 471 472 if ((rnode = ath_sysctl_treetop(NULL)) == NULL) 473 return; 474 475 SYSCTL_GLOBAL_INT(CTLFLAG_READWRITE, "rate_interval", 476 "rate control: operation interval (ms)", rateinterval); 477 /* XXX bounds check values */ 478 SYSCTL_GLOBAL_INT(CTLFLAG_READWRITE, "rate_raise", 479 "rate control: retry threshold to credit rate raise (%%)", 480 rate_raise); 481 SYSCTL_GLOBAL_INT(CTLFLAG_READWRITE, "rate_raise_threshold", 482 "rate control: # good periods before raising rate", 483 rate_raise_threshold); 484 } 485 486 struct ath_ratectrl * 487 ath_rate_attach(struct ath_softc *sc) 488 { 489 struct onoe_softc *osc; 490 491 osc = malloc(sizeof(struct onoe_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 492 if (osc == NULL) 493 return NULL; 494 osc->arc.arc_space = sizeof(struct onoe_node); 495 callout_init(&osc->timer, 0); 496 ath_rate_sysctlattach(sc); 497 498 return &osc->arc; 499 } 500 501 void 502 ath_rate_detach(struct ath_ratectrl *arc) 503 { 504 struct onoe_softc *osc = (struct onoe_softc *) arc; 505 506 callout_stop(&osc->timer); 507 free(osc, M_DEVBUF); 508 } 509