[ath] [ath_rate] Add some extra data into the rate control lookup.
Right now (well, since I did this in 2011/2012) the rate control code makes some super bad choices for 11n aggregates/rates, and it tracks statistics even more questionably. It's been long enough and I'm now trying to use it again daily, so let's start by: * telling the rate control code if it's an aggregate or not; * being clearer about the TID - yes it can be extracted from the ath_buf but this way it can be overridden by the caller without changing the TID itself. (This is for doing experiments with voice/video QoS at some point..) * Return an optional field to limit how long the aggregate is in microseconds. Right now the rate control code supplies a rate table and the ath aggr form code will look at the rate table and limit the aggregate size to 4ms at the slowest rate. Yeah, this is pretty terrible. * Add some more TODO comments around handling txpower, rate and handling filtered frames status so if I continue to have spoons for this I can go poke at it.
This commit is contained in:
parent
83b4342743
commit
84f950a54d
@ -104,8 +104,8 @@ ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
|
||||
void
|
||||
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
int shortPreamble, size_t frameLen,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate)
|
||||
int shortPreamble, size_t frameLen, int tid, bool is_aggr,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur)
|
||||
{
|
||||
struct amrr_node *amn = ATH_NODE_AMRR(an);
|
||||
|
||||
@ -115,6 +115,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
*txrate = amn->amn_tx_rate0sp;
|
||||
else
|
||||
*txrate = amn->amn_tx_rate0;
|
||||
maxdur = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -112,8 +112,8 @@ ath_rate_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
|
||||
void
|
||||
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
int shortPreamble, size_t frameLen,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate)
|
||||
int shortPreamble, size_t frameLen, int tid, bool is_aggr,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur)
|
||||
{
|
||||
struct onoe_node *on = ATH_NODE_ONOE(an);
|
||||
|
||||
@ -123,6 +123,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
*txrate = on->on_tx_rate0sp;
|
||||
else
|
||||
*txrate = on->on_tx_rate0;
|
||||
*maxdur = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -482,8 +482,9 @@ ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
void
|
||||
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
int shortPreamble, size_t frameLen,
|
||||
u_int8_t *rix0, int *try0, u_int8_t *txrate)
|
||||
int shortPreamble, size_t frameLen, int tid,
|
||||
bool is_aggr, u_int8_t *rix0, int *try0,
|
||||
u_int8_t *txrate, int *maxdur)
|
||||
{
|
||||
#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL)
|
||||
#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS)
|
||||
@ -498,6 +499,10 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
|
||||
|
||||
ath_rate_update_static_rix(sc, &an->an_node);
|
||||
|
||||
/* For now don't take TID, is_aggr into account */
|
||||
/* Also for now don't calculate a max duration; that'll come later */
|
||||
*maxdur = -1;
|
||||
|
||||
if (sn->currates != sc->sc_currates) {
|
||||
device_printf(sc->sc_dev, "%s: currates != sc_currates!\n",
|
||||
__func__);
|
||||
|
@ -4312,6 +4312,11 @@ ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni,
|
||||
an = ATH_NODE(ni);
|
||||
ATH_NODE_UNLOCK_ASSERT(an);
|
||||
|
||||
/*
|
||||
* XXX TODO: teach the rate control about TXERR_FILT and
|
||||
* see about handling it (eg see how many attempts were
|
||||
* made before it got filtered and account for that.)
|
||||
*/
|
||||
if ((ts->ts_status & HAL_TXERR_FILT) == 0) {
|
||||
ATH_NODE_LOCK(an);
|
||||
ath_rate_tx_complete(sc, an, rc, ts, frmlen, nframes, nbad);
|
||||
@ -4355,6 +4360,9 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq,
|
||||
/*
|
||||
* XXX assume this isn't an aggregate
|
||||
* frame.
|
||||
*
|
||||
* XXX TODO: also do this for filtered frames?
|
||||
* Once rate control knows about them?
|
||||
*/
|
||||
ath_tx_update_ratectrl(sc, ni,
|
||||
bf->bf_state.bfs_rc, ts,
|
||||
|
@ -1376,10 +1376,12 @@ ath_tx_setds(struct ath_softc *sc, struct ath_buf *bf)
|
||||
* as they may depend upon the rate chosen.
|
||||
*/
|
||||
static void
|
||||
ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf)
|
||||
ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf, int tid,
|
||||
bool is_aggr)
|
||||
{
|
||||
uint8_t rate, rix;
|
||||
int try0;
|
||||
int maxdur; // Note: Unused for now
|
||||
|
||||
if (! bf->bf_state.bfs_doratelookup)
|
||||
return;
|
||||
@ -1389,7 +1391,7 @@ ath_tx_do_ratelookup(struct ath_softc *sc, struct ath_buf *bf)
|
||||
|
||||
ATH_NODE_LOCK(ATH_NODE(bf->bf_node));
|
||||
ath_rate_findrate(sc, ATH_NODE(bf->bf_node), bf->bf_state.bfs_shpream,
|
||||
bf->bf_state.bfs_pktlen, &rix, &try0, &rate);
|
||||
bf->bf_state.bfs_pktlen, tid, is_aggr, &rix, &try0, &rate, &maxdur);
|
||||
|
||||
/* In case MRR is disabled, make sure rc[0] is setup correctly */
|
||||
bf->bf_state.bfs_rc[0].rix = rix;
|
||||
@ -1519,7 +1521,7 @@ ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq,
|
||||
bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK;
|
||||
|
||||
/* Setup the descriptor before handoff */
|
||||
ath_tx_do_ratelookup(sc, bf);
|
||||
ath_tx_do_ratelookup(sc, bf, tid->tid, false);
|
||||
ath_tx_calc_duration(sc, bf);
|
||||
ath_tx_calc_protection(sc, bf);
|
||||
ath_tx_set_rtscts(sc, bf);
|
||||
@ -3094,7 +3096,7 @@ ath_tx_xmit_aggr(struct ath_softc *sc, struct ath_node *an,
|
||||
ath_tx_update_clrdmask(sc, tid, bf);
|
||||
|
||||
/* Direct dispatch to hardware */
|
||||
ath_tx_do_ratelookup(sc, bf);
|
||||
ath_tx_do_ratelookup(sc, bf, tid->tid, false);
|
||||
ath_tx_calc_duration(sc, bf);
|
||||
ath_tx_calc_protection(sc, bf);
|
||||
ath_tx_set_rtscts(sc, bf);
|
||||
@ -4689,6 +4691,8 @@ ath_tx_comp_aggr_error(struct ath_softc *sc, struct ath_buf *bf_first,
|
||||
*
|
||||
* XXX use the length in the first frame in the series;
|
||||
* XXX just so things are consistent for now.
|
||||
*
|
||||
* XXX TODO: need to signal this is a large frame no matter what...
|
||||
*/
|
||||
ath_tx_update_ratectrl(sc, ni, bf_first->bf_state.bfs_rc,
|
||||
&bf_first->bf_status.ds_txstat,
|
||||
@ -5088,9 +5092,11 @@ ath_tx_aggr_comp_aggr(struct ath_softc *sc, struct ath_buf *bf_first,
|
||||
* Now we know how many frames were bad, call the rate
|
||||
* control code.
|
||||
*/
|
||||
if (fail == 0)
|
||||
if (fail == 0) {
|
||||
/* XXX TODO: what's pktlen here? */
|
||||
ath_tx_update_ratectrl(sc, ni, rc, &ts, pktlen, nframes,
|
||||
nbad);
|
||||
}
|
||||
|
||||
/*
|
||||
* send bar if we dropped any frames
|
||||
@ -5429,7 +5435,7 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an,
|
||||
/* Update CLRDMASK just before this frame is queued */
|
||||
ath_tx_update_clrdmask(sc, tid, bf);
|
||||
|
||||
ath_tx_do_ratelookup(sc, bf);
|
||||
ath_tx_do_ratelookup(sc, bf, tid->tid, false);
|
||||
ath_tx_calc_duration(sc, bf);
|
||||
ath_tx_calc_protection(sc, bf);
|
||||
ath_tx_set_rtscts(sc, bf);
|
||||
@ -5453,7 +5459,7 @@ ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an,
|
||||
* really "do" aggregate lookups, so it only considers
|
||||
* the size of the first frame.
|
||||
*/
|
||||
ath_tx_do_ratelookup(sc, bf);
|
||||
ath_tx_do_ratelookup(sc, bf, tid->tid, true);
|
||||
bf->bf_state.bfs_rc[3].rix = 0;
|
||||
bf->bf_state.bfs_rc[3].tries = 0;
|
||||
|
||||
@ -5644,7 +5650,7 @@ ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an,
|
||||
ath_tx_update_clrdmask(sc, tid, bf);
|
||||
|
||||
/* Program descriptors + rate control */
|
||||
ath_tx_do_ratelookup(sc, bf);
|
||||
ath_tx_do_ratelookup(sc, bf, tid->tid, false);
|
||||
ath_tx_calc_duration(sc, bf);
|
||||
ath_tx_calc_protection(sc, bf);
|
||||
ath_tx_set_rtscts(sc, bf);
|
||||
|
@ -132,10 +132,15 @@ void ath_rate_getxtxrates(struct ath_softc *sc, struct ath_node *an,
|
||||
* is to be setup then try0 should contain a value other than ATH_TXMATRY
|
||||
* and ath_rate_setupxtxdesc will be called after deciding if the frame
|
||||
* can be transmitted with multi-rate retry.
|
||||
*
|
||||
* maxdur is an optional return value (or -1 if not set) that defines
|
||||
* the maximum frame duration in microseconds. This allows the rate
|
||||
* control selection to override the maximum duration (normally 4ms)
|
||||
* that the packet aggregation logic makes.
|
||||
*/
|
||||
void ath_rate_findrate(struct ath_softc *, struct ath_node *,
|
||||
int shortPreamble, size_t frameLen,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate);
|
||||
int shortPreamble, size_t frameLen, int tid, bool is_aggr,
|
||||
u_int8_t *rix, int *try0, u_int8_t *txrate, int *maxdur);
|
||||
/*
|
||||
* Setup any extended (multi-rate) descriptor state for a data packet.
|
||||
* The rate index returned by ath_rate_findrate is passed back in.
|
||||
|
Loading…
Reference in New Issue
Block a user