Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ath/ath_rate/sample/sample.c
Show First 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | |||||
static const char * | static const char * | ||||
dot11rate_label(const HAL_RATE_TABLE *rt, int rix) | dot11rate_label(const HAL_RATE_TABLE *rt, int rix) | ||||
{ | { | ||||
if (rix < 0) | if (rix < 0) | ||||
return ""; | return ""; | ||||
return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb "; | return rt->info[rix].phy == IEEE80211_T_HT ? "MCS" : "Mb "; | ||||
} | } | ||||
static uint16_t | |||||
get11rate_idx(const HAL_RATE_TABLE *rt, int rix) | |||||
{ | |||||
uint16_t rate_idx; | |||||
uint8_t rate; | |||||
KASSERT(rix >= 0, ("rix < 0!")); | |||||
if (rt->info[rix].phy == IEEE80211_T_HT) | |||||
rate = rt->info[rix].dot11Rate; | |||||
else | |||||
rate = IEEE80211_RV(rt->info[rix].dot11Rate); | |||||
rate_idx = ieee80211_lookup_rate_index(rt->info[rix].phy, rate); | |||||
KASSERT(rate_idx != IEEE80211_RATE_NONEXISTENT, | |||||
("rate index not found for phy %u / rate %u", | |||||
rt->info[rix].phy, rate)); | |||||
return rate_idx; | |||||
} | |||||
/* | /* | ||||
* Return the rix with the lowest average_tx_time, | * Return the rix with the lowest average_tx_time, | ||||
* or -1 if all the average_tx_times are 0. | * or -1 if all the average_tx_times are 0. | ||||
*/ | */ | ||||
static __inline int | static __inline int | ||||
pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, | pick_best_rate(struct ath_node *an, const HAL_RATE_TABLE *rt, | ||||
int size_bin, int require_acked_before) | int size_bin, int require_acked_before) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | #endif | ||||
return current_rix; | return current_rix; | ||||
#undef DOT11RATE | #undef DOT11RATE | ||||
#undef MCS | #undef MCS | ||||
} | } | ||||
static int | static int | ||||
ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni) | ath_rate_get_static_rix(struct ath_softc *sc, const struct ieee80211_node *ni) | ||||
{ | { | ||||
#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) | const struct ieee80211_rate_t *rate; | ||||
#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) | uint8_t value; | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | |||||
int srate; | |||||
/* Check MCS rates */ | /* NB: already checked against IEEE80211_RATE_NONEXISTENT */ | ||||
for (srate = ni->ni_htrates.rs_nrates - 1; srate >= 0; srate--) { | rate = ieee80211_get_rate(tp->ucastrate); | ||||
if (MCS(srate) == tp->ucastrate) | value = rate->value; | ||||
return sc->sc_rixmap[tp->ucastrate]; | |||||
} | |||||
if (rate->type == IEEE80211_T_HT) { | |||||
/* Check MCS rates */ | |||||
if (isset(ni->ni_htrates.rs_bitmap, value)) | |||||
return sc->sc_rixmap[value | IEEE80211_RATE_MCS]; | |||||
} else { | |||||
/* Check legacy rates */ | /* Check legacy rates */ | ||||
for (srate = ni->ni_rates.rs_nrates - 1; srate >= 0; srate--) { | if (isset(ni->ni_rates.rs_bitmap, value)) | ||||
if (RATE(srate) == tp->ucastrate) | return sc->sc_rixmap[value]; | ||||
return sc->sc_rixmap[tp->ucastrate]; | |||||
} | } | ||||
return -1; | return -1; | ||||
#undef RATE | |||||
#undef DOT11RATE | |||||
#undef MCS | |||||
} | } | ||||
static void | static void | ||||
ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni) | ath_rate_update_static_rix(struct ath_softc *sc, struct ieee80211_node *ni) | ||||
{ | { | ||||
struct ath_node *an = ATH_NODE(ni); | struct ath_node *an = ATH_NODE(ni); | ||||
const struct ieee80211_txparam *tp = ni->ni_txparms; | const struct ieee80211_txparam_vht *tp = ni->ni_txparms; | ||||
struct sample_node *sn = ATH_NODE_SAMPLE(an); | struct sample_node *sn = ATH_NODE_SAMPLE(an); | ||||
if (tp != NULL && tp->ucastrate != IEEE80211_FIXED_RATE_NONE) { | if (tp != NULL && tp->ucastrate != IEEE80211_RATE_NONEXISTENT) { | ||||
/* | /* | ||||
* A fixed rate is to be used; ucastrate is the IEEE code | * A fixed rate is to be used; ucastrate is the IEEE code | ||||
* for this rate (sans basic bit). Check this against the | * for this rate (sans basic bit). Check this against the | ||||
* negotiated rate set for the node. Note the fixed rate | * negotiated rate set for the node. Note the fixed rate | ||||
* may not be available for various reasons so we only | * may not be available for various reasons so we only | ||||
* setup the static rate index if the lookup is successful. | * setup the static rate index if the lookup is successful. | ||||
*/ | */ | ||||
sn->static_rix = ath_rate_get_static_rix(sc, ni); | sn->static_rix = ath_rate_get_static_rix(sc, ni); | ||||
▲ Show 20 Lines • Show All 236 Lines • ▼ Show 20 Lines | "%s: size %d switch rate %d (%d/%d) -> %d (%d/%d) after %d packets mrr %d", | ||||
mrr); | mrr); | ||||
} | } | ||||
sn->packets_since_switch[size_bin] = 0; | sn->packets_since_switch[size_bin] = 0; | ||||
sn->current_rix[size_bin] = best_rix; | sn->current_rix[size_bin] = best_rix; | ||||
sn->ticks_since_switch[size_bin] = ticks; | sn->ticks_since_switch[size_bin] = ticks; | ||||
/* | /* | ||||
* Set the visible txrate for this node. | * Set the visible txrate for this node. | ||||
*/ | */ | ||||
an->an_node.ni_txrate = (rt->info[best_rix].phy == IEEE80211_T_HT) ? MCS(best_rix) : DOT11RATE(best_rix); | an->an_node.ni_txrate = get11rate_idx(rt, best_rix); | ||||
} | } | ||||
rix = sn->current_rix[size_bin]; | rix = sn->current_rix[size_bin]; | ||||
sn->packets_since_switch[size_bin]++; | sn->packets_since_switch[size_bin]++; | ||||
} | } | ||||
*try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY; | *try0 = mrr ? sn->sched[rix].t0 : ATH_TXMAXTRY; | ||||
done: | done: | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 396 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
/* | /* | ||||
* Initialize the tables for a node. | * Initialize the tables for a node. | ||||
*/ | */ | ||||
static void | static void | ||||
ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) | ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni) | ||||
{ | { | ||||
#define RATE(_ix) (ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL) | #define RATE_IDX(_ix) (ni->ni_rates.rates[(_ix)].rs_index) | ||||
#define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) | #define DOT11RATE(_ix) (rt->info[(_ix)].dot11Rate & IEEE80211_RATE_VAL) | ||||
#define MCS(_ix) (ni->ni_htrates.rs_rates[_ix] | IEEE80211_RATE_MCS) | #define HTRATE_IDX(_ix) (ni->ni_htrates.rates[(_ix)].rs_index) | ||||
#define MCS(_ix) ((_ix) | IEEE80211_RATE_MCS) | |||||
struct ath_node *an = ATH_NODE(ni); | struct ath_node *an = ATH_NODE(ni); | ||||
struct sample_node *sn = ATH_NODE_SAMPLE(an); | struct sample_node *sn = ATH_NODE_SAMPLE(an); | ||||
const HAL_RATE_TABLE *rt = sc->sc_currates; | const HAL_RATE_TABLE *rt = sc->sc_currates; | ||||
const struct ieee80211_rate_t *rate; | |||||
int x, y, rix; | int x, y, rix; | ||||
KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); | KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode)); | ||||
KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2, | KASSERT(sc->sc_curmode < IEEE80211_MODE_MAX+2, | ||||
("curmode %u", sc->sc_curmode)); | ("curmode %u", sc->sc_curmode)); | ||||
sn->sched = mrr_schedules[sc->sc_curmode]; | sn->sched = mrr_schedules[sc->sc_curmode]; | ||||
Show All 9 Lines | #define MCS(_ix) ((_ix) | IEEE80211_RATE_MCS) | ||||
* Construct a bitmask of usable rates. This has all | * Construct a bitmask of usable rates. This has all | ||||
* negotiated rates minus those marked by the hal as | * negotiated rates minus those marked by the hal as | ||||
* to be ignored for doing rate control. | * to be ignored for doing rate control. | ||||
*/ | */ | ||||
sn->ratemask = 0; | sn->ratemask = 0; | ||||
/* MCS rates */ | /* MCS rates */ | ||||
if (ni->ni_flags & IEEE80211_NODE_HT) { | if (ni->ni_flags & IEEE80211_NODE_HT) { | ||||
for (x = 0; x < ni->ni_htrates.rs_nrates; x++) { | for (x = 0; x < ni->ni_htrates.rs_nrates; x++) { | ||||
rix = sc->sc_rixmap[MCS(x)]; | rate = ieee80211_get_rate(HTRATE_IDX(x)); | ||||
rix = sc->sc_rixmap[MCS(rate->value)]; | |||||
if (rix == 0xff) | if (rix == 0xff) | ||||
continue; | continue; | ||||
/* skip rates marked broken by hal */ | /* skip rates marked broken by hal */ | ||||
if (!rt->info[rix].valid) | if (!rt->info[rix].valid) | ||||
continue; | continue; | ||||
KASSERT(rix < SAMPLE_MAXRATES, | KASSERT(rix < SAMPLE_MAXRATES, | ||||
("mcs %u has rix %d", MCS(x), rix)); | ("mcs %u has rix %d", MCS(x), rix)); | ||||
sn->ratemask |= (uint64_t) 1<<rix; | sn->ratemask |= (uint64_t) 1<<rix; | ||||
} | } | ||||
} | } | ||||
/* Legacy rates */ | /* Legacy rates */ | ||||
for (x = 0; x < ni->ni_rates.rs_nrates; x++) { | for (x = 0; x < ni->ni_rates.rs_nrates; x++) { | ||||
rix = sc->sc_rixmap[RATE(x)]; | rate = ieee80211_get_rate(RATE_IDX(x)); | ||||
rix = sc->sc_rixmap[rate->value]; | |||||
if (rix == 0xff) | if (rix == 0xff) | ||||
continue; | continue; | ||||
/* skip rates marked broken by hal */ | /* skip rates marked broken by hal */ | ||||
if (!rt->info[rix].valid) | if (!rt->info[rix].valid) | ||||
continue; | continue; | ||||
KASSERT(rix < SAMPLE_MAXRATES, | KASSERT(rix < SAMPLE_MAXRATES, | ||||
("rate %u has rix %d", RATE(x), rix)); | ("rate %u has rix %d", RATE_IDX(x), rix)); | ||||
sn->ratemask |= (uint64_t) 1<<rix; | sn->ratemask |= (uint64_t) 1<<rix; | ||||
} | } | ||||
#ifdef IEEE80211_DEBUG | #ifdef IEEE80211_DEBUG | ||||
if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) { | if (ieee80211_msg(ni->ni_vap, IEEE80211_MSG_RATECTL)) { | ||||
uint64_t mask; | uint64_t mask; | ||||
ieee80211_note(ni->ni_vap, "[%6D] %s: size 1600 rate/tt", | ieee80211_note(ni->ni_vap, "[%6D] %s: size 1600 rate/tt", | ||||
ni->ni_macaddr, ":", __func__); | ni->ni_macaddr, ":", __func__); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_RATECTL, ni, | ||||
DOT11RATE(0)/2, DOT11RATE(0) % 1 ? ".5" : "", | DOT11RATE(0)/2, DOT11RATE(0) % 1 ? ".5" : "", | ||||
sn->stats[1][0].perfect_tx_time, | sn->stats[1][0].perfect_tx_time, | ||||
DOT11RATE(sn->num_rates-1)/2, DOT11RATE(sn->num_rates-1) % 1 ? ".5" : "", | DOT11RATE(sn->num_rates-1)/2, DOT11RATE(sn->num_rates-1) % 1 ? ".5" : "", | ||||
sn->stats[1][sn->num_rates-1].perfect_tx_time | sn->stats[1][sn->num_rates-1].perfect_tx_time | ||||
); | ); | ||||
#endif | #endif | ||||
/* set the visible bit-rate */ | /* set the visible bit-rate */ | ||||
if (sn->static_rix != -1) | if (sn->static_rix != -1) | ||||
ni->ni_txrate = DOT11RATE(sn->static_rix); | ni->ni_txrate = get11rate_idx(rt, sn->static_rix); | ||||
else | else | ||||
ni->ni_txrate = RATE(0); | ni->ni_txrate = RATE_IDX(0); | ||||
#undef RATE | #undef MCS | ||||
#undef HTRATE_IDX | |||||
#undef DOT11RATE | #undef DOT11RATE | ||||
#undef RATE_IDX | |||||
} | } | ||||
/* | /* | ||||
* Fetch the statistics for the given node. | * Fetch the statistics for the given node. | ||||
* | * | ||||
* The ieee80211 node must be referenced and unlocked, however the ath_node | * The ieee80211 node must be referenced and unlocked, however the ath_node | ||||
* must be locked. | * must be locked. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 229 Lines • Show Last 20 Lines |