This seems to be a more accurate interpretation of the MiRA paper (a link to paper can be found at the top of the ieee80211_mira.h header file). I see a slight stabilization of Tx throughput with the change.
MiRA's rate probe interval is computed based on the number of frames sent, and perhaps lost, during a probe attempt to another Tx rate. If we saw no loss during our probe attempt the new interval will be small so the rate may be probed again soon. If we saw high packet loss the new interval will be larger (up to about 20 seconds) in order to reduce packet loss caused by probing. The paper says the probe interval for a rate needs to be updated if the rate's goodput is worse than that of the "current transmission rate" (see the "Adaptive probing interval" section). Our implementation interpreted "current transmission rate" as "rate being probed right now" and adjusted the interval of the previously probed rate. However, the context of this section of the paper suggests that "current transmissions rate" intends to refer to the currently selected best rate for our non-probing transmissions. At least that's what I believe after having re-read the section a few times... With this diff we update the probing interval of any rate which has been probed and has lost against the best rate. As before, the interval of a rate is reset to the minimum if it gets chosen as the best rate. Note that there are two ways probing can be triggered, and the probe interval is just one of those two. The other trigger is a significant change in measured throughput (which happens when e.g. a laptop moves further from the AP, and we start probing down). This other probing trigger is unaffected. diff 25e76d314b84a6d0b1c697db14f987e4ad0a9520 14a1ca7807811e518898c39a278a89782a0362d8 blob - 15b2250fc3701a48824bc0c5772586c30e19e85a blob + fbfd7148bd3e7d82eca9c0221203b64318d57d2f --- sys/net80211/ieee80211_mira.c +++ sys/net80211/ieee80211_mira.c @@ -73,7 +73,7 @@ int ieee80211_mira_inter_mode_ra_finished( struct ieee80211_mira_node *, struct ieee80211_node *); int ieee80211_mira_best_rate(struct ieee80211_mira_node *, struct ieee80211_node *); -void ieee80211_mira_update_probe_interval(struct ieee80211_mira_node *, +void ieee80211_mira_update_probe_interval( struct ieee80211_mira_goodput_stats *); void ieee80211_mira_schedule_probe_timers(struct ieee80211_mira_node *, struct ieee80211_node *); @@ -735,6 +735,19 @@ ieee80211_mira_probe_valid(struct ieee80211_mira_node void ieee80211_mira_probe_done(struct ieee80211_mira_node *mn) { + int mcs; + + /* Reset probe interval of the best rate. */ + mn->g[mn->best_mcs].probe_interval = IEEE80211_MIRA_PROBE_TIMEOUT_MIN; + mn->g[mn->best_mcs].nprobes = 0; + mn->g[mn->best_mcs].nprobe_bytes = 0; + + /* Update probing interval of other probed rates. */ + for (mcs = 0; mcs < IEEE80211_HT_RATESET_NUM_MCS; mcs++) { + if (mcs != mn->best_mcs && (mn->probed_rates & (1 << mcs))) + ieee80211_mira_update_probe_interval(&mn->g[mcs]); + } + ieee80211_mira_cancel_timeouts(mn); ieee80211_mira_reset_driver_stats(mn); ieee80211_mira_reset_collision_stats(mn); @@ -871,8 +884,7 @@ ieee80211_mira_best_rate(struct ieee80211_mira_node *m /* See section 5.1.1 (at "Adaptive probing interval") in MiRA paper. */ void -ieee80211_mira_update_probe_interval(struct ieee80211_mira_node *mn, - struct ieee80211_mira_goodput_stats *g) +ieee80211_mira_update_probe_interval(struct ieee80211_mira_goodput_stats *g) { uint64_t lt; int intval; @@ -971,17 +983,6 @@ void ieee80211_mira_probe_next_rate(struct ieee80211_mira_node *mn, struct ieee80211_node *ni) { - struct ieee80211_mira_goodput_stats *gprev, *g; - int prev_mcs; - - prev_mcs = ieee80211_mira_prev_mcs(mn, ni); - gprev = &mn->g[prev_mcs]; - g = &mn->g[ni->ni_txmcs]; - /* If the previous rate was worse, increase its probing interval. */ - if (prev_mcs != ni->ni_txmcs && - gprev->measured + IEEE80211_MIRA_RATE_THRESHOLD < g->measured) - ieee80211_mira_update_probe_interval(mn, gprev); - /* Select the next rate to probe. */ mn->probed_rates |= (1 << ni->ni_txmcs); ni->ni_txmcs = ieee80211_mira_next_mcs(mn, ni); @@ -1165,16 +1166,9 @@ ieee80211_mira_choose(struct ieee80211_mira_node *mn, DPRINTFN(4, ("probing MCS %d\n", ni->ni_txmcs)); } else if (ieee80211_mira_inter_mode_ra_finished(mn, ni)) { int best = ieee80211_mira_best_rate(mn, ni); - if (mn->best_mcs != best) { + if (mn->best_mcs != best) mn->best_mcs = best; - ni->ni_txmcs = best; - /* Reset probe interval for new best rate. */ - mn->g[best].probe_interval = - IEEE80211_MIRA_PROBE_TIMEOUT_MIN; - mn->g[best].nprobes = 0; - mn->g[best].nprobe_bytes = 0; - } else - ni->ni_txmcs = mn->best_mcs; + ni->ni_txmcs = mn->best_mcs; ieee80211_mira_probe_done(mn); }