/* * Reset the rate control state for each 802.11 state transition. */ static void ath_rate_newstate(struct ieee80211vap *vap, enum ieee80211_state state) { struct ieee80211com *ic = vap->iv_ic; struct ath_softc *sc = ic->ic_dev->priv; struct ieee80211_node *ni; if (state == IEEE80211_S_INIT) return; if (vap->iv_opmode == IEEE80211_M_STA) { /* * Reset local xmit state; this is really only * meaningful when operating in station mode. */ ni = vap->iv_bss; if (state == IEEE80211_S_RUN) { ath_rate_ctl_start(sc, ni); } else { ath_rate_update(sc, ni, 0); } } else { /* * When operating as a station the node table holds * the AP's that were discovered during scanning. * For any other operating mode we want to reset the * tx rate state of each node. */ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, NULL); ath_rate_update(sc, vap->iv_bss, 0); } }
static void ath_rate_cb(void *arg, struct ieee80211_node *ni) { struct ath_softc *sc = arg; ath_rate_update(sc, ni, 0); }
/* * Reset the rate control state for each 802.11 state transition. */ void ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state) { struct onoe_softc *osc = (struct onoe_softc *) sc->sc_rc; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; if (state == IEEE80211_S_INIT) { callout_stop(&osc->timer); return; } if (ic->ic_opmode == IEEE80211_M_STA) { /* * Reset local xmit state; this is really only * meaningful when operating in station mode. */ ni = ic->ic_bss; if (state == IEEE80211_S_RUN) { ath_rate_ctl_start(sc, ni); } else { ath_rate_update(sc, ni, 0); } } else { /* * When operating as a station the node table holds * the AP's that were discovered during scanning. * For any other operating mode we want to reset the * tx rate state of each node. */ ieee80211_iterate_nodes(&ic->ic_sta, ath_rate_cb, sc); ath_rate_update(sc, ic->ic_bss, 0); } if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE && state == IEEE80211_S_RUN) { int interval; /* * Start the background rate control thread if we * are not configured to use a fixed xmit rate. */ interval = ath_rateinterval; if (ic->ic_opmode == IEEE80211_M_STA) interval /= 2; callout_reset(&osc->timer, (interval * hz) / 1000, ath_ratectl, &sc->sc_if); } }
/* * Reset the rate control state for each 802.11 state transition. */ void ath_rate_newstate(struct ath_softc *sc, enum ieee80211_state state) { struct amrr_softc *asc = (struct amrr_softc *) sc->sc_rc; struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_node *ni; if (state == IEEE80211_S_INIT) { del_timer(&asc->timer); return; } if (ic->ic_opmode == IEEE80211_M_STA) { /* * Reset local xmit state; this is really only * meaningful when operating in station mode. */ ni = ic->ic_bss; if (state == IEEE80211_S_RUN) { ath_rate_ctl_start(sc, ni); } else { ath_rate_update(sc, ni, 0); } } else { /* * When operating as a station the node table holds * the AP's that were discovered during scanning. * For any other operating mode we want to reset the * tx rate state of each node. */ TAILQ_FOREACH(ni, &ic->ic_node, ni_list) ath_rate_update(sc, ni, 0); /* use lowest rate */ ath_rate_update(sc, ic->ic_bss, 0); } if (ic->ic_fixed_rate == -1 && state == IEEE80211_S_RUN) { int interval; /* * Start the background rate control thread if we * are not configured to use a fixed xmit rate. */ interval = ath_rateinterval; if (ic->ic_opmode == IEEE80211_M_STA) interval /= 2; mod_timer(&asc->timer, jiffies + ((HZ * interval) / 1000)); } }
/* * Set the starting transmit rate for a node. */ static void ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) { #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) const struct ieee80211_txparam *tp = ni->ni_txparms; int srate; KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); if (tp == NULL || tp->ucastrate == IEEE80211_FIXED_RATE_NONE) { /* * No fixed rate is requested. For 11b start with * the highest negotiated rate; otherwise, for 11g * and 11a, we start "in the middle" at 24Mb or 36Mb. */ srate = ni->ni_rates.rs_nrates - 1; if (sc->sc_curmode != IEEE80211_MODE_11B) { /* * Scan the negotiated rate set to find the * closest rate. */ /* NB: the rate set is assumed sorted */ for (; srate >= 0 && RATE(srate) > 72; srate--) ; } } else { /* * A fixed rate is to be used; ic_fixed_rate is the * IEEE code for this rate (sans basic bit). Convert this * to the index into the negotiated rate set for * the node. We know the rate is there because the * rate set is checked when the station associates. */ /* NB: the rate set is assumed sorted */ srate = ni->ni_rates.rs_nrates - 1; for (; srate >= 0 && RATE(srate) != tp->ucastrate; srate--) ; } /* * The selected rate may not be available due to races * and mode settings. Also orphaned nodes created in * adhoc mode may not have any rate set so this lookup * can fail. This is not fatal. */ ath_rate_update(sc, ni, srate < 0 ? 0 : srate); #undef RATE }
/* * Set the starting transmit rate for a node. */ static void ath_rate_ctl_start(struct ath_softc *sc, struct ieee80211_node *ni) { #define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) struct ieee80211com *ic = &sc->sc_ic; int srate; KASSERT(ni->ni_rates.rs_nrates > 0, ("no rates")); if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) { /* * No fixed rate is requested. For 11b start with * the highest negotiated rate; otherwise, for 11g * and 11a, we start "in the middle" at 24Mb or 36Mb. */ srate = ni->ni_rates.rs_nrates - 1; if (sc->sc_curmode != IEEE80211_MODE_11B) { /* * Scan the negotiated rate set to find the * closest rate. */ /* NB: the rate set is assumed sorted */ for (; srate >= 0 && RATE(srate) > 72; srate--) ; KASSERT(srate >= 0, ("bogus rate set")); } } else { /* * A fixed rate is to be used; ic_fixed_rate is an * index into the supported rate set. Convert this * to the index into the negotiated rate set for * the node. We know the rate is there because the * rate set is checked when the station associates. */ const struct ieee80211_rateset *rs = &ic->ic_sup_rates[ic->ic_curmode]; int r = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL; /* NB: the rate set is assumed sorted */ srate = ni->ni_rates.rs_nrates - 1; for (; srate >= 0 && RATE(srate) != r; srate--) ; KASSERT(srate >= 0, ("fixed rate %d not in rate set", ic->ic_fixed_rate)); } ath_rate_update(sc, ni, srate); #undef RATE }
/* * Examine and potentially adjust the transmit rate. */ static void ath_rate_ctl(void *arg, struct ieee80211_node *ni) { struct ath_softc *sc = arg; struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni)); int rix; #define is_success(amn) \ (amn->amn_tx_try1_cnt < (amn->amn_tx_try0_cnt/10)) #define is_enough(amn) \ (amn->amn_tx_try0_cnt > 10) #define is_failure(amn) \ (amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3)) rix = amn->amn_rix; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d", amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt, amn->amn_tx_try3_cnt, amn->amn_success_threshold); if (is_success (amn) && is_enough (amn)) { amn->amn_success++; if (amn->amn_success == amn->amn_success_threshold && rix + 1 < ni->ni_rates.rs_nrates) { amn->amn_recovery = 1; amn->amn_success = 0; rix++; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, "increase rate to %d", rix); } else { amn->amn_recovery = 0; } } else if (is_failure (amn)) { amn->amn_success = 0; if (rix > 0) { if (amn->amn_recovery) { /* recovery failure. */ amn->amn_success_threshold *= 2; amn->amn_success_threshold = min (amn->amn_success_threshold, (u_int)ath_rate_max_success_threshold); IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, "decrease rate recovery thr: %d", amn->amn_success_threshold); } else { /* simple failure. */ amn->amn_success_threshold = ath_rate_min_success_threshold; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, "decrease rate normal thr: %d", amn->amn_success_threshold); } amn->amn_recovery = 0; rix--; } else { amn->amn_recovery = 0; } } if (is_enough (amn) || rix != amn->amn_rix) { /* reset counters. */ amn->amn_tx_try0_cnt = 0; amn->amn_tx_try1_cnt = 0; amn->amn_tx_try2_cnt = 0; amn->amn_tx_try3_cnt = 0; amn->amn_tx_failure_cnt = 0; } if (rix != amn->amn_rix) { ath_rate_update(sc, ni, rix); } }
/* * Examine and potentially adjust the transmit rate. */ static void ath_rate_ctl(void *arg, struct ieee80211_node *ni) { struct ath_softc *sc = arg; struct onoe_node *on = ATH_NODE_ONOE(ATH_NODE(ni)); struct ieee80211_rateset *rs = &ni->ni_rates; int dir = 0, nrate, enough; /* * Rate control * XXX: very primitive version. */ enough = (on->on_tx_ok + on->on_tx_err >= 10); /* no packet reached -> down */ if (on->on_tx_err > 0 && on->on_tx_ok == 0) dir = -1; /* all packets needs retry in average -> down */ if (enough && on->on_tx_ok < on->on_tx_retr) dir = -1; /* no error and less than rate_raise% of packets need retry -> up */ if (enough && on->on_tx_err == 0 && on->on_tx_retr < (on->on_tx_ok * ath_rate_raise) / 100) dir = 1; DPRINTF(sc, "%s: ok %d err %d retr %d upper %d dir %d\n", ether_sprintf(ni->ni_macaddr), on->on_tx_ok, on->on_tx_err, on->on_tx_retr, on->on_tx_upper, dir); nrate = ni->ni_txrate; switch (dir) { case 0: if (enough && on->on_tx_upper > 0) on->on_tx_upper--; break; case -1: if (nrate > 0) { nrate--; sc->sc_stats.ast_rate_drop++; } on->on_tx_upper = 0; break; case 1: /* raise rate if we hit rate_raise_threshold */ if (++on->on_tx_upper < ath_rate_raise_threshold) break; on->on_tx_upper = 0; if (nrate + 1 < rs->rs_nrates) { nrate++; sc->sc_stats.ast_rate_raise++; } break; } if (nrate != ni->ni_txrate) { DPRINTF(sc, "%s: %dM -> %dM (%d ok, %d err, %d retr)\n", __func__, (rs->rs_rates[ni->ni_txrate] & IEEE80211_RATE_VAL) / 2, (rs->rs_rates[nrate] & IEEE80211_RATE_VAL) / 2, on->on_tx_ok, on->on_tx_err, on->on_tx_retr); ath_rate_update(sc, ni, nrate); } else if (enough) on->on_tx_ok = on->on_tx_err = on->on_tx_retr = 0; }
void ath_rate_node_init(struct ath_softc *sc, struct ath_node *an) { /* NB: assumed to be zero'd by caller */ ath_rate_update(sc, &an->an_node, 0); }
static void ath_rate_cb(void *arg, struct ieee80211_node *ni) { ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg); }
/* * Examine and potentially adjust the transmit rate. */ static void ath_rate_ctl(void *arg, struct ieee80211_node *ni) { struct ath_softc *sc = arg; struct amrr_node *amn = ATH_NODE_AMRR(ATH_NODE (ni)); int old_rate; #define is_success(amn) \ (amn->amn_tx_try1_cnt < (amn->amn_tx_try0_cnt/10)) #define is_enough(amn) \ (amn->amn_tx_try0_cnt > 10) #define is_failure(amn) \ (amn->amn_tx_try1_cnt > (amn->amn_tx_try0_cnt/3)) #define is_max_rate(ni) \ ((ni->ni_txrate + 1) >= ni->ni_rates.rs_nrates) #define is_min_rate(ni) \ (ni->ni_txrate == 0) old_rate = ni->ni_txrate; DPRINTF (sc, "cnt0: %d cnt1: %d cnt2: %d cnt3: %d -- threshold: %d\n", amn->amn_tx_try0_cnt, amn->amn_tx_try1_cnt, amn->amn_tx_try2_cnt, amn->amn_tx_try3_cnt, amn->amn_success_threshold); if (is_success (amn) && is_enough (amn)) { amn->amn_success++; if (amn->amn_success == amn->amn_success_threshold && !is_max_rate (ni)) { amn->amn_recovery = 1; amn->amn_success = 0; ni->ni_txrate++; DPRINTF (sc, "increase rate to %d\n", ni->ni_txrate); } else { amn->amn_recovery = 0; } } else if (is_failure (amn)) { amn->amn_success = 0; if (!is_min_rate (ni)) { if (amn->amn_recovery) { /* recovery failure. */ amn->amn_success_threshold *= 2; amn->amn_success_threshold = min (amn->amn_success_threshold, (u_int)ath_rate_max_success_threshold); DPRINTF (sc, "decrease rate recovery thr: %d\n", amn->amn_success_threshold); } else { /* simple failure. */ amn->amn_success_threshold = ath_rate_min_success_threshold; DPRINTF (sc, "decrease rate normal thr: %d\n", amn->amn_success_threshold); } amn->amn_recovery = 0; ni->ni_txrate--; } else { amn->amn_recovery = 0; } } if (is_enough (amn) || old_rate != ni->ni_txrate) { /* reset counters. */ amn->amn_tx_try0_cnt = 0; amn->amn_tx_try1_cnt = 0; amn->amn_tx_try2_cnt = 0; amn->amn_tx_try3_cnt = 0; amn->amn_tx_failure_cnt = 0; } if (old_rate != ni->ni_txrate) { ath_rate_update(sc, ni, ni->ni_txrate); } }