示例#1
0
/*
 * 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);
	}
}
示例#2
0
static void
ath_rate_cb(void *arg, struct ieee80211_node *ni)
{
	struct ath_softc *sc = arg;

	ath_rate_update(sc, ni, 0);
}
示例#3
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);
	}
}
示例#4
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 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));
	}
}
示例#5
0
/*
 * 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
}
示例#6
0
/*
 * 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
}
示例#7
0
/*
 * 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);
    }
}
示例#8
0
/* 
 * 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;
}
示例#9
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);
}
示例#10
0
static void
ath_rate_cb(void *arg, struct ieee80211_node *ni)
{
	ath_rate_update(ni->ni_ic->ic_dev->priv, ni, (long) arg);
}
示例#11
0
/* 
 * 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);
	}
}