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 static void 200 node_reset(struct amrr_node *amn) 201 { 202 amn->amn_tx_try0_cnt = 0; 203 amn->amn_tx_try1_cnt = 0; 204 amn->amn_tx_try2_cnt = 0; 205 amn->amn_tx_try3_cnt = 0; 206 amn->amn_tx_failure_cnt = 0; 207 amn->amn_success = 0; 208 amn->amn_recovery = 0; 209 amn->amn_success_threshold = ath_rate_min_success_threshold; 210 } 211 212 213 /** 214 * The code below assumes that we are dealing with hardware multi rate retry 215 * I have no idea what will happen if you try to use this module with another 216 * type of hardware. Your machine might catch fire or it might work with 217 * horrible performance... 218 */ 219 static void 220 ath_rate_update(struct ath_softc *sc, struct ieee80211_node *ni, int rate) 221 { 222 struct ath_node *an = ATH_NODE(ni); 223 struct amrr_node *amn = ATH_NODE_AMRR(an); 224 struct ieee80211vap *vap = ni->ni_vap; 225 const HAL_RATE_TABLE *rt = sc->sc_currates; 226 u_int8_t rix; 227 228 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); 229 230 IEEE80211_NOTE(vap, IEEE80211_MSG_RATECTL, ni, 231 "%s: set xmit rate to %dM", __func__, 232 ni->ni_rates.rs_nrates > 0 ? 233 (ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL) / 2 : 0); 234 235 amn->amn_rix = rate; 236 /* 237 * Before associating a node has no rate set setup 238 * so we can't calculate any transmit codes to use. 239 * This is ok since we should never be sending anything 240 * but management frames and those always go at the 241 * lowest hardware rate. 242 */ 243 if (ni->ni_rates.rs_nrates > 0) { 244 ni->ni_txrate = ni->ni_rates.rs_rates[rate] & IEEE80211_RATE_VAL; 245 amn->amn_tx_rix0 = sc->sc_rixmap[ni->ni_txrate]; 246 amn->amn_tx_rate0 = rt->info[amn->amn_tx_rix0].rateCode; 247 amn->amn_tx_rate0sp = amn->amn_tx_rate0 | 248 rt->info[amn->amn_tx_rix0].shortPreamble; 249 if (sc->sc_mrretry) { 250 amn->amn_tx_try0 = 1; 251 amn->amn_tx_try1 = 1; 252 amn->amn_tx_try2 = 1; 253 amn->amn_tx_try3 = 1; 254 if (--rate >= 0) { 255 rix = sc->sc_rixmap[ 256 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 257 amn->amn_tx_rate1 = rt->info[rix].rateCode; 258 amn->amn_tx_rate1sp = amn->amn_tx_rate1 | 259 rt->info[rix].shortPreamble; 260 } else { 261 amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0; 262 } 263 if (--rate >= 0) { 264 rix = sc->sc_rixmap[ 265 ni->ni_rates.rs_rates[rate]&IEEE80211_RATE_VAL]; 266 amn->amn_tx_rate2 = rt->info[rix].rateCode; 267 amn->amn_tx_rate2sp = amn->amn_tx_rate2 | 268 rt->info[rix].shortPreamble; 269 } else { 270 amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0; 271 } 272 if (rate > 0) { 273 /* NB: only do this if we didn't already do it above */ 274 amn->amn_tx_rate3 = rt->info[0].rateCode; 275 amn->amn_tx_rate3sp = 276 amn->amn_tx_rate3 | rt->info[0].shortPreamble; 277 } else { 278 amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0; 279 } 280 } else { 281 amn->amn_tx_try0 = ATH_TXMAXTRY; 282 /* theorically, these statements are useless because 283 * the code which uses them tests for an_tx_try0 == ATH_TXMAXTRY 284 */ 285 amn->amn_tx_try1 = 0; 286 amn->amn_tx_try2 = 0; 287 amn->amn_tx_try3 = 0; 288 amn->amn_tx_rate1 = amn->amn_tx_rate1sp = 0; 289 amn->amn_tx_rate2 = amn->amn_tx_rate2sp = 0; 290 amn->amn_tx_rate3 = amn->amn_tx_rate3sp = 0; 291 } 292 } 293 node_reset(amn); 294 295 amn->amn_interval = ath_rateinterval; 296 if (vap->iv_opmode == IEEE80211_M_STA) 297 amn->amn_interval /= 2; 298 amn->amn_interval = (amn->amn_interval * hz) / 1000; 299 } 300 301 /* 302 * Set the starting transmit rate for a node. 303 */ 304 static void 305 ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) 306 { 307 #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) 308 const struct ieee80211_txparam *tp = ni->ni_txparms; 309 int srate; 310 311 KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); 312 if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { 313 /* 314 * No fixed rate is requested. For 11b start with 315 * the highest negotiated rate; otherwise, for 11g 316 * and 11a, we start "in the middle" at 24Mb or 36Mb. 317 */ 318 srate = ni->ni_rates.rs_nrates - 1; 319 if (sc->sc_curmode != IEEE80211_MODE_11B) { 320 /* 321 * Scan the negotiated rate set to find the 322 * closest rate. 323 */ 324 /* NB: the rate set is assumed sorted */ 325 for (; srate >= 0 && RATE(srate) > 72; srate--) 326 ; 327 } 328 } else { 329 /* 330 * A fixed rate is to be used; ic_fixed_rate is the 331 * IEEE code for this rate (sans basic bit). Convert this 332 * to the index into the negotiated rate set for 333 * the node. We know the rate is there because the 334 * rate set is checked when the station associates. 335 */ 336 /* NB: the rate set is assumed sorted */ 337 srate = ni->ni_rates.rs_nrates - 1; 338 for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--) 339 ; 340 } 341 /* 342 * The selected rate may not be available due to races 343 * and mode settings. Also orphaned nodes created in 344 * adhoc mode may not have any rate set so this lookup 345 * can fail. This is not fatal. 346 */ 347 ath_rate_update(sc, ni, srate < 0 ? 0 : srate); 348 #undef RATE 349 } 350 351 /* 352 * Examine and potentially adjust the transmit rate. 353 */ 354 static void 355 ath_rate_ctl(void *arg, struct ieee80211_node *ni) 356 { 357 struct ath_softc *sc = arg; 358 struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni)); 359 int rix; 360 361 #define is_success(amn) \ 362 (amn->amn_tx_try1_cnt < (amn->amn_tx_try0_cnt/10)) 363 #define is_enough(amn) \ 364 (amn->amn_tx_try0_cnt > 10) 365 #define is_failure(amn) \ 366 (amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3)) 367 368 rix = amn->amn_rix; 369 370 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, 371 "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d", 372 amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt, 373 amn->amn_tx_try3_cnt, amn->amn_success_threshold); 374 if (is_success (amn) && is_enough (amn)) { 375 amn->amn_success++; 376 if (amn->amn_success == amn->amn_success_threshold && 377 rix + 1 < ni->ni_rates.rs_nrates) { 378 amn->amn_recovery = 1; 379 amn->amn_success = 0; 380 rix++; 381 IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, 382 "increase rate to %d", rix); 383 } else { 384 amn->amn_recovery = 0; 385 } 386 } else if (is_failure (amn)) { 387 amn->amn_success = 0; 388 if (rix > 0) { 389 if (amn->amn_recovery) { 390 /* recovery failure. */ 391 amn->amn_success_threshold *= 2; 392 amn->amn_success_threshold = min (amn->amn_success_threshold, 393 (u_int)ath_rate_max_success_threshold); 394 IEEE80211_NOTE(ni->ni_vap, 395 IEEE80211_MSG_RATECTL, ni, 396 "decrease rate recovery thr: %d", 397 amn->amn_success_threshold); 398 } else { 399 /* simple failure. */ 400 amn->amn_success_threshold = ath_rate_min_success_threshold; 401 IEEE80211_NOTE(ni->ni_vap, 402 IEEE80211_MSG_RATECTL, ni, 403 "decrease rate normal thr: %d", 404 amn->amn_success_threshold); 405 } 406 amn->amn_recovery = 0; 407 rix--; 408 } else { 409 amn->amn_recovery = 0; 410 } 411 412 } 413 if (is_enough (amn) || rix != amn->amn_rix) { 414 /* reset counters. */ 415 amn->amn_tx_try0_cnt = 0; 416 amn->amn_tx_try1_cnt = 0; 417 amn->amn_tx_try2_cnt = 0; 418 amn->amn_tx_try3_cnt = 0; 419 amn->amn_tx_failure_cnt = 0; 420 } 421 if (rix != amn->amn_rix) { 422 ath_rate_update(sc, ni, rix); 423 } 424 } 425 426 static int 427 ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an, 428 struct ath_rateioctl *re) 429 { 430 431 return (EINVAL); 432 } 433 434 static void 435 ath_rate_sysctlattach(struct ath_softc *sc) 436 { 437 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); 438 struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); 439 440 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 441 "rate_interval", CTLFLAG_RW, &ath_rateinterval, 0, 442 "rate control: operation interval (ms)"); 443 /* XXX bounds check values */ 444 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 445 "max_sucess_threshold", CTLFLAG_RW, 446 &ath_rate_max_success_threshold, 0, ""); 447 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 448 "min_sucess_threshold", CTLFLAG_RW, 449 &ath_rate_min_success_threshold, 0, ""); 450 } 451 452 struct ath_ratectrl * 453 ath_rate_attach(struct ath_softc *sc) 454 { 455 struct amrr_softc *asc; 456 457 asc = malloc(sizeof(struct amrr_softc), M_DEVBUF, M_NOWAIT|M_ZERO); 458 if (asc == NULL) 459 return NULL; 460 asc->arc.arc_space = sizeof(struct amrr_node); 461 ath_rate_sysctlattach(sc); 462 463 return &asc->arc; 464 } 465 466 void 467 ath_rate_detach(struct ath_ratectrl *arc) 468 { 469 struct amrr_softc *asc = (struct amrr_softc *) arc; 470 471 free(asc, M_DEVBUF); 472 } 473