Add a per-node rate control routine for each rate control module.

For now, the only module implement is 'sample', and that's only partially
implemented.  The main issue here with reusing this structure in userland
is that it uses 'rix' everywhere, which requires the userland code to
have access to the current HAL rate table.

For now, this is a very large work in progress.

Specific details:

* The rate control information is per-node at the moment and wrapped
  in a TLV, to ease parsing and backwards compatibility.
* .. but so I can be slack for now, the userland statistics are just
  a copy of the kernel-land sample node state.
* However, for now use a temporary copy and change the rix entries
  to dot11rate entries to make it slightly easier to eyeball.

Problems:

* The actual rate information table is unfortunately indexed by rix
  and it doesn't contain a rate code.  So the userland side of this
  currently has no way to extract out a mapping.

TODO:

* Add a TLV payload to dump out the rate control table mapping so
  'rix' can be turned into a dot11 / MCS rate.
* .. then remove the temporary copy.
This commit is contained in:
Adrian Chadd 2012-07-20 01:36:02 +00:00
parent 9e38f70840
commit 2d20d6559d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=238633
4 changed files with 97 additions and 8 deletions

View File

@ -421,6 +421,14 @@ ath_rate_ctl(void *arg, struct ieee80211_node *ni)
}
}
static int
ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an,
struct ath_rateioctl *re)
{
return (EINVAL);
}
static void
ath_rate_sysctlattach(struct ath_softc *sc)
{

View File

@ -407,6 +407,14 @@ ath_rate_sysctlattach(struct ath_softc *sc)
"rate control: # good periods before raising rate");
}
static int
ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an,
struct ath_rateioctl *re)
{
return (EINVAL);
}
struct ath_ratectrl *
ath_rate_attach(struct ath_softc *sc)
{

View File

@ -105,8 +105,6 @@ __FBSDID("$FreeBSD$");
static void ath_rate_ctl_reset(struct ath_softc *, struct ieee80211_node *);
static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600 };
static __inline int
size_to_bin(int size)
{
@ -128,12 +126,6 @@ size_to_bin(int size)
return NUM_PACKET_SIZE_BINS-1;
}
static __inline int
bin_to_size(int index)
{
return packet_size_bins[index];
}
void
ath_rate_node_init(struct ath_softc *sc, struct ath_node *an)
{
@ -1198,6 +1190,79 @@ ath_rate_ctl_reset(struct ath_softc *sc, struct ieee80211_node *ni)
#undef DOT11RATE
}
/*
* Fetch the statistics for the given node.
*
* The ieee80211 node must be referenced and unlocked, however the ath_node
* must be locked.
*
* The main difference here is that we convert the rate indexes
* to 802.11 rates, or the userland output won't make much sense
* as it has no access to the rix table.
*/
int
ath_rate_fetch_node_stats(struct ath_softc *sc, struct ath_node *an,
struct ath_rateioctl *rs)
{
struct sample_node *sn = ATH_NODE_SAMPLE(an);
const HAL_RATE_TABLE *rt = sc->sc_currates;
struct ath_rateioctl_tlv av;
struct sample_node *ts;
int y;
ATH_NODE_LOCK_ASSERT(an);
/*
* Ensure there's enough space for the statistics.
*/
if (rs->len <
sizeof(struct ath_rateioctl_tlv) +
sizeof(struct sample_node))
return (EINVAL);
/*
* Take a temporary copy of the sample node state so we can
* modify it before we copy it.
*/
ts = malloc(sizeof(struct sample_node), M_TEMP, M_WAITOK | M_ZERO);
if (ts == NULL)
return (ENOMEM);
memcpy(ts, sn, sizeof(struct sample_node));
/* Convert rix -> 802.11 rate codes */
ts->static_rix = dot11rate(rt, sn->static_rix);
for (y = 0; y < NUM_PACKET_SIZE_BINS; y++) {
/*
* For non-11n rates, clear the high bit - that
* means "basic rate" and will confuse things.
*
* For 11n rates, set the high bit.
*/
ts->current_rix[y] = dot11rate(rt, sn->current_rix[y]);
ts->current_sample_rix[y] =
dot11rate(rt, sn->current_sample_rix[y]);
ts->last_sample_rix[y] =
dot11rate(rt, sn->last_sample_rix[y]);
}
/*
* Assemble the TLV.
*/
av.tlv_id = ATH_RATE_TLV_SAMPLENODE;
av.tlv_len = sizeof(struct sample_node);
copyout(&av, rs->buf, sizeof(struct ath_rateioctl_tlv));
/*
* Copy the statistics over to the provided buffer.
*/
copyout(ts, rs->buf + sizeof(struct ath_rateioctl_tlv),
sizeof(struct sample_node));
free(ts, M_TEMP);
return (0);
}
static void
sample_stats(void *arg, struct ieee80211_node *ni)
{

View File

@ -79,6 +79,14 @@ struct txschedule {
*/
#define NUM_PACKET_SIZE_BINS 2
static const int packet_size_bins[NUM_PACKET_SIZE_BINS] = { 250, 1600 };
static inline int
bin_to_size(int index)
{
return packet_size_bins[index];
}
/* per-node state */
struct sample_node {
int static_rix; /* rate index of fixed tx rate */