1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2004 INRIA 5 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer, 13 * without modification. 14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 15 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 16 * redistribution must be conditioned upon including a substantially 17 * similar Disclaimer requirement for further binary redistribution. 18 * 3. Neither the names of the above-listed copyright holders nor the names 19 * of any contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * Alternatively, this software may be distributed under the terms of the 23 * GNU General Public License ("GPL") version 2 as published by the Free 24 * Software Foundation. 25 * 26 * NO WARRANTY 27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 30 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 31 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 32 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 35 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 37 * THE POSSIBILITY OF SUCH DAMAGES. 38 * 39 */ 40 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 /* 45 * AMRR rate control. See: 46 * http://www-sop.inria.fr/rapports/sophia/RR-5208.html 47 * "IEEE 802.11 Rate Adaptation: A Practical Approach" by 48 * Mathieu Lacage, Hossein Manshaei, Thierry Turletti 49 */ 50 #include "opt_ath.h" 51 #include "opt_inet.h" 52 #include "opt_wlan.h" 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/sysctl.h> 57 #include <sys/kernel.h> 58 #include <sys/lock.h> 59 #include <sys/mutex.h> 60 #include <sys/errno.h> 61 62 #include <machine/bus.h> 63 #include <machine/resource.h> 64 #include <sys/bus.h> 65 66 #include <sys/socket.h> 67 68 #include <net/if.h> 69 #include <net/if_media.h> 70 #include <net/if_arp.h> 71 72 #include <net80211/ieee80211_var.h> 73 74 #include <net/bpf.h> 75 76 #ifdef INET 77 #include <netinet/in.h> 78 #include <netinet/if_ether.h> 79 #endif 80 81 #include <dev/ath/if_athvar.h> 82 #include <dev/ath/ath_rate/amrr/amrr.h> 83 #include <dev/ath/ath_hal/ah_desc.h> 84 85 static int ath_rateinterval = 1000; /* rate ctl interval (ms) */ 86 static int ath_rate_max_success_threshold = 10; 87 static int ath_rate_min_success_threshold = 1; 88 89 static void ath_rate_update(struct ath_softc *, struct ieee80211_node *, 90 int rate); 91 static void ath_rate_ctl_start(struct ath_softc *, struct ieee80211_node *); 92 static void ath_rate_ctl(void *, struct ieee80211_node *); 93 94 void 95 ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) 96 { 97 /* NB: assumed to be zero'd by caller */ 98 } 99 100 void 101 ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an) 102 { 103 } 104 105 void 106 ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, 107 int shortPreamble, size_t frameLen, 108 u_int8_t *rix, int *try0, u_int8_t *txrate) 109 { 110 struct amrr_node *amn = ATH_NODE_AMRR(an); 111 112 *rix = amn->amn_tx_rix0; 113 *try0 = amn->amn_tx_try0; 114 if (shortPreamble) 115 *txrate = amn->amn_tx_rate0sp; 116 else 117 *txrate = amn->amn_tx_rate0; 118 } 119 120 /* 121 * Get the TX rates. 122 * 123 * The short preamble bits aren't set here; the caller should augment 124 * the returned rate with the relevant preamble rate flag. 125 */ 126 void 127 ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an, 128 uint8_t rix0, struct ath_rc_series *rc) 129 { 130 struct amrr_node *amn = ATH_NODE_AMRR(an); 131 132 rc[0].flags = rc[1].flags = rc[2].flags = rc[3].flags = 0; 133 134 rc[0].rix = amn->amn_tx_rate0; 135 rc[1].rix = amn->amn_tx_rate1; 136 rc[2].rix = amn->amn_tx_rate2; 137 rc[3].rix = amn->amn_tx_rate3; 138 139 rc[0].tries = amn->amn_tx_try0; 140 rc[1].tries = amn->amn_tx_try1; 141 rc[2].tries = amn->amn_tx_try2; 142 rc[3].tries = amn->amn_tx_try3; 143 } 144 145 146 void 147 ath_rate_setupxtxdesc(struct ath_softc *sc, struct ath_node *an, 148 struct ath_desc *ds, int shortPreamble, u_int8_t rix) 149 { 150 struct amrr_node *amn = ATH_NODE_AMRR(an); 151 152 ath_hal_setupxtxdesc(sc->sc_ah, ds 153 , amn->amn_tx_rate1sp, amn->amn_tx_try1 /* series 1 */ 154 , amn->amn_tx_rate2sp, amn->amn_tx_try2 /* series 2 */ 155 , amn->amn_tx_rate3sp, amn->amn_tx_try3 /* series 3 */ 156 ); 157 } 158 159 void 160 ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an, 161 const struct ath_rc_series *rc, const struct ath_tx_status *ts, 162 int frame_size, int nframes, int nbad) 163 { 164 struct amrr_node *amn = ATH_NODE_AMRR(an); 165 int sr = ts->ts_shortretry; 166 int lr = ts->ts_longretry; 167 int retry_count = sr + lr; 168 169 amn->amn_tx_try0_cnt++; 170 if (retry_count == 1) { 171 amn->amn_tx_try1_cnt++; 172 } else if (retry_count == 2) { 173 amn->amn_tx_try1_cnt++; 174 amn->amn_tx_try2_cnt++; 175 } else if (retry_count == 3) { 176 amn->amn_tx_try1_cnt++; 177 amn->amn_tx_try2_cnt++; 178 amn->amn_tx_try3_cnt++; 179 } else if (retry_count > 3) { 180 amn->amn_tx_try1_cnt++; 181 amn->amn_tx_try2_cnt++; 182 amn->amn_tx_try3_cnt++; 183 amn->amn_tx_failure_cnt++; 184 } 185 if (amn->amn_interval != 0 && 186 ticks - amn->amn_ticks > amn->amn_interval) { 187 ath_rate_ctl(sc, &an->an_node); 188 amn->amn_ticks = ticks; 189 } 190 } 191 192 void 193 ath_rate_newassoc(struct ath_softc *sc, struct ath_node *an, int isnew) 194 { 195 if (isnew) 196 ath_rate_ctl_start(sc, &an->an_node); 197 } 198 199 void 200 ath_rate_update_rx_rssi(struct ath_softc *sc, struct ath_node *an, int rssi) 201 { 202 } 203 204 static void 205 node_reset(struct amrr_node *amn) 206 { 207 amn->amn_tx_try0_cnt = 0; 208 amn->amn_tx_try1_cnt = 0; 209 amn->amn_tx_try2_cnt = 0; 210 amn->amn_tx_try3_cnt = 0; 211 amn->amn_tx_failure_cnt = 0; 212 amn->amn_success = 0; 213 amn->amn_recovery = 0; 214 amn->amn_success_threshold = ath_rate_min_success_threshold; 215 } 216 217 218 /** 219 * The code below assumes that we are dealing with hardware multi rate retry 220 * I have no idea what will happen if you try to use this module with another 221 * type of hardware. Your machine might catch fire or it might work with 222 * horrible performance... 223 */ 224 static void 225 ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate) 226 { 227 struct ath_node *an = ATH_NODE(ni); 228 struct amrr_node *amn = ATH_NODE_AMRR(an); 229 struct ieee80211vap *vap = ni->ni_vap; 230 const HAL_RATE_TABLE *rt = sc->sc_currates; 231 u_int8_t rix; 232 233 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 234 235 IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni, 236 "%s: set xmit rate to %dM", __func__, 237 ni->ni_rates.rs_nrates > 0 ? 238 (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0); 239 240 amn->amn_rix = rate; 241 /* 242 * Before associating a node has no rate set setup 243 * so we can't calculate any transmit codes to use. 244 * This is ok since we should never be sending anything 245 * but management frames and those always go at the 246 * lowest hardware rate. 247 */ 248 if (ni->ni_rates.rs_nrates > 0) { 249 ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL; 250 amn->amn_tx_rix0 = sc->sc_rixmap[ni->ni_txrate]; 251 amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode; 252 amn->amn_tx_rate0sp = amn->amn_tx_rate0 | 253 rt->info[amn->amn_tx_rix0].shortPreamble; 254 if (sc->sc_mrretry) { 255 amn->amn_tx_try0 = 1; 256 amn->amn_tx_try1 = 1; 257 amn->amn_tx_try2 = 1; 258 amn->amn_tx_try3 = 1; 259 if (--rate >= 0) { 260 rix = sc->sc_rixmap[ 261 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 262 amn->amn_tx_rate1 = rt->info[rix].rateCode; 263 amn->amn_tx_rate1sp = amn->amn_tx_rate1 | 264 rt->info[rix].shortPreamble; 265 } else { 266 amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0; 267 } 268 if (--rate >= 0) { 269 rix = sc->sc_rixmap[ 270 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 271 amn->amn_tx_rate2 = rt->info[rix].rateCode; 272 amn->amn_tx_rate2sp = amn->amn_tx_rate2 | 273 rt->info[rix].shortPreamble; 274 } else { 275 amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0; 276 } 277 if (rate > 0) { 278 /* NB: only do this if we didn't already do it above */ 279 amn->amn_tx_rate3 = rt->info[0].rateCode; 280 amn->amn_tx_rate3sp = 281 amn->amn_tx_rate3 | rt->info[0].shortPreamble; 282 } else { 283 amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0; 284 } 285 } else { 286 amn->amn_tx_try0 = ATH_TXMAXTRY; 287 /* theorically, these statements are useless because 288 * the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY 289 */ 290 amn->amn_tx_try1 = 0; 291 amn->amn_tx_try2 = 0; 292 amn->amn_tx_try3 = 0; 293 amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0; 294 amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0; 295 amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0; 296 } 297 } 298 node_reset(amn); 299 300 amn->amn_interval = ath_rateinterval; 301 if (vap->iv_opmode == IEEE80211_M_STA) 302 amn->amn_interval /= 2; 303 amn->amn_interval = (amn->amn_interval * hz) / 1000; 304 } 305 306 /* 307 * Set the starting transmit rate for a node. 308 */ 309 static void 310 ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) 311 { 312 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 313 const struct ieee80211_txparam *tp = ni->ni_txparms; 314 int srate; 315 316 KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); 317 if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { 318 /* 319 * No fixed rate is requested. For 11b start with 320 * the highest negotiated rate; otherwise, for 11g 321 * and 11a, we start "in the middle" at 24Mb or 36Mb. 322 */ 323 srate = ni->ni_rates.rs_nrates - 1; 324 if (sc->sc_curmode != IEEE80211_MODE_11B) { 325 /* 326 * Scan the negotiated rate set to find the 327 * closest rate. 328 */ 329 /* NB: the rate set is assumed sorted */ 330 for (; srate >= 0 && RATE(srate) > 72; srate--) 331 ; 332 } 333 } else { 334 /* 335 * A fixed rate is to be used; ic_fixed_rate is the 336 * IEEE code for this rate (sans basic bit). Convert this 337 * to the index into the negotiated rate set for 338 * the node. We know the rate is there because the 339 * rate set is checked when the station associates. 340 */ 341 /* NB: the rate set is assumed sorted */ 342 srate = ni->ni_rates.rs_nrates - 1; 343 for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--) 344 ; 345 } 346 /* 347 * The selected rate may not be available due to races 348 * and mode settings. Also orphaned nodes created in 349 * adhoc mode may not have any rate set so this lookup 350 * can fail. This is not fatal. 351 */ 352 ath_rate_update(sc, ni, srate < 0 ? 0 : srate); 353 #undef RATE 354 } 355 356 /* 357 * Examine and potentially adjust the transmit rate. 358 */ 359 static void 360 ath_rate_ctl(void *arg, struct ieee80211_node *ni) 361 { 362 struct ath_softc *sc = arg; 363 struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni)); 364 int rix; 365 366 #define is_success(amn) \ 367 (amn->amn_tx_try1_cnt < (amn->amn_tx_try0_cnt/10)) 368 #define is_enough(amn) \ 369 (amn->amn_tx_try0_cnt > 10) 370 #define is_failure(amn) \ 371 (amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3)) 372 373 rix = amn->amn_rix; 374 375 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, 376 "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d", 377 amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt, 378 amn->amn_tx_try3_cnt, amn->amn_success_threshold); 379 if (is_success (amn) && is_enough (amn)) { 380 amn->amn_success++; 381 if (amn->amn_success == amn->amn_success_threshold && 382 rix + 1 < ni->ni_rates.rs_nrates) { 383 amn->amn_recovery = 1; 384 amn->amn_success = 0; 385 rix++; 386 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, 387 "increase rate to %d", rix); 388 } else { 389 amn->amn_recovery = 0; 390 } 391 } else if (is_failure (amn)) { 392 amn->amn_success = 0; 393 if (rix > 0) { 394 if (amn->amn_recovery) { 395 /* recovery failure. */ 396 amn->amn_success_threshold *= 2; 397 amn->amn_success_threshold = min (amn->amn_success_threshold, 398 (u_int)ath_rate_max_success_threshold); 399 IEEE80211_NOTE(ni->ni_vap, 400 IEEE80211_MSG_RATECTL, ni, 401 "decrease rate recovery thr: %d", 402 amn->amn_success_threshold); 403 } else { 404 /* simple failure. */ 405 amn->amn_success_threshold = ath_rate_min_success_threshold; 406 IEEE80211_NOTE(ni->ni_vap, 407 IEEE80211_MSG_RATECTL, ni, 408 "decrease rate normal thr: %d", 409 amn->amn_success_threshold); 410 } 411 amn->amn_recovery = 0; 412 rix--; 413 } else { 414 amn->amn_recovery = 0; 415 } 416 417 } 418 if (is_enough (amn) || rix != amn->amn_rix) { 419 /* reset counters. */ 420 amn->amn_tx_try0_cnt = 0; 421 amn->amn_tx_try1_cnt = 0; 422 amn->amn_tx_try2_cnt = 0; 423 amn->amn_tx_try3_cnt = 0; 424 amn->amn_tx_failure_cnt = 0; 425 } 426 if (rix != amn->amn_rix) { 427 ath_rate_update(sc, ni, rix); 428 } 429 } 430 431 static int 432 ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an, 433 struct ath_rateioctl *re) 434 { 435 436 return (EINVAL); 437 } 438 439 static void 440 ath_rate_sysctlattach(struct ath_softc *sc) 441 { 442 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 443 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 444 445 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 446 "rate_interval", CTLFLAG_RW, &ath_rateinterval, 0, 447 "rate control: operation interval (ms)"); 448 /* XXX bounds check values */ 449 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 450 "max_sucess_threshold", CTLFLAG_RW, 451 &ath_rate_max_success_threshold, 0, ""); 452 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 453 "min_sucess_threshold", CTLFLAG_RW, 454 &ath_rate_min_success_threshold, 0, ""); 455 } 456 457 struct ath_ratectrl * 458 ath_rate_attach(struct ath_softc *sc) 459 { 460 struct amrr_softc *asc; 461 462 asc = malloc(sizeof(struct amrr_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 463 if (asc == NULL) 464 return NULL; 465 asc->arc.arc_space = sizeof(struct amrr_node); 466 ath_rate_sysctlattach(sc); 467 468 return &asc->arc; 469 } 470 471 void 472 ath_rate_detach(struct ath_ratectrl *arc) 473 { 474 struct amrr_softc *asc = (struct amrr_softc *) arc; 475 476 free(asc, M_DEVBUF); 477 } 478