Skip to content

Commit

Permalink
mac80211/minstrel_ht: improve accuracy of throughput metric at high d…
Browse files Browse the repository at this point in the history
…ata rates

At high data rates the average frame transmission durations are small
enough for rounding errors to matter, sometimes causing minstrel to use
slightly lower transmit rates than necessary.
To fix this, change the unit of the duration value to nanoseconds
instead of microseconds, and reorder the multiplications/divisions when
calculating the throughput metric so that they don't overflow or
truncate prematurely.
At 2-stream HT40 this makes TCP throughput a bit more stable.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Felix Fietkau authored and Johannes Berg committed Mar 6, 2013
1 parent 355199e commit ed97a13
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions net/mac80211/rc80211_minstrel_ht.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
/* Number of symbols for a packet with (bps) bits per symbol */
#define MCS_NSYMS(bps) ((MCS_NBITS + (bps) - 1) / (bps))

/* Transmission time for a packet containing (syms) symbols */
/* Transmission time (nanoseconds) for a packet containing (syms) symbols */
#define MCS_SYMBOL_TIME(sgi, syms) \
(sgi ? \
((syms) * 18 + 4) / 5 : /* syms * 3.6 us */ \
(syms) << 2 /* syms * 4 us */ \
((syms) * 18000 + 4000) / 5 : /* syms * 3.6 us */ \
((syms) * 1000) << 2 /* syms * 4 us */ \
)

/* Transmit duration for the raw data part of an average sized packet */
Expand Down Expand Up @@ -64,9 +64,9 @@
}

#define CCK_DURATION(_bitrate, _short, _len) \
(10 /* SIFS */ + \
(1000 * (10 /* SIFS */ + \
(_short ? 72 + 24 : 144 + 48 ) + \
(8 * (_len + 4) * 10) / (_bitrate))
(8 * (_len + 4) * 10) / (_bitrate)))

#define CCK_ACK_DURATION(_bitrate, _short) \
(CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \
Expand Down Expand Up @@ -211,7 +211,8 @@ static void
minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
{
struct minstrel_rate_stats *mr;
unsigned int usecs = 0;
unsigned int nsecs = 0;
unsigned int tp;

mr = &mi->groups[group].rates[rate];

Expand All @@ -221,10 +222,12 @@ minstrel_ht_calc_tp(struct minstrel_ht_sta *mi, int group, int rate)
}

if (group != MINSTREL_CCK_GROUP)
usecs = mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);
nsecs = 1000 * mi->overhead / MINSTREL_TRUNC(mi->avg_ampdu_len);

usecs += minstrel_mcs_groups[group].duration[rate];
mr->cur_tp = MINSTREL_TRUNC((1000000 / usecs) * mr->probability);
nsecs += minstrel_mcs_groups[group].duration[rate];
tp = 1000000 * ((mr->probability * 1000) / nsecs);

mr->cur_tp = MINSTREL_TRUNC(tp);
}

/*
Expand Down Expand Up @@ -536,7 +539,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
mr->retry_updated = true;

group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len;
tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len / 1000;

/* Contention time for first 2 tries */
ctime = (t_slot * cw) >> 1;
Expand Down

0 comments on commit ed97a13

Please sign in to comment.