Date: Mon, 5 Sep 2011 06:11:17 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r225383 - user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample Message-ID: <201109050611.p856BHGA023457@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Mon Sep 5 06:11:17 2011 New Revision: 225383 URL: http://svn.freebsd.org/changeset/base/225383 Log: Make the default rate choice semi 11n aware. There's a couple of bugs here which I'm trying to fix: * There's a bit of code which marks all larger size bins as having failures if a smaller bin has a failure. * If there's no large packet TX (say I'm doing an iperf TCP test in the opposite direction) then the 1600-byte bins all get marked with both TX failures and _successive_ TX failures. * Thus when it's time to TX a large packet, all the rates are marked as invalid. This commit fixes the first problem - that the default rate selection was simply choosing the highest MCS rate (and thus MCS15 was being used on a two stream NIC) and so things like DHCP may take a few retransmits. It also fixes the problem where all those MCS rates are slowly marked as invalid by failures in small packets; the only rate left over is the base rate (6mbit for 11a). This doesn't fix a related problem - where subsequent TXes doesn't ever probe the higher rates. Because the successive failures exist, those rates aren't ever selected. pick_sample_rate() should be trying those after a while - 10 seconds by default. Modified: user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c Modified: user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c Mon Sep 5 03:43:43 2011 (r225382) +++ user/adrian/if_ath_tx/sys/dev/ath/ath_rate/sample/sample.c Mon Sep 5 06:11:17 2011 (r225383) @@ -320,6 +320,96 @@ ath_rate_update_static_rix(struct ath_so } } +/* + * Pick a non-HT rate to begin using. + */ +static int +ath_rate_pick_seed_rate_legacy(struct ath_softc *sc, struct ath_node *an, + int frameLen) +{ +#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) +#define RATE(ix) (DOT11RATE(ix) / 2) + int rix = -1; + const HAL_RATE_TABLE *rt = sc->sc_currates; + struct sample_node *sn = ATH_NODE_SAMPLE(an); + const int size_bin = size_to_bin(frameLen); + + /* no packet has been sent successfully yet */ + for (rix = rt->rateCount-1; rix > 0; rix--) { + if ((sn->ratemask & (1<<rix)) == 0) + continue; + + /* Skip HT rates */ + if (rt->info[rix].phy == IEEE80211_T_HT) + continue; + + /* + * Pick the highest rate <= 36 Mbps + * that hasn't failed. + */ + if (DOT11RATE(rix) <= 72 && + sn->stats[size_bin][rix].successive_failures == 0) { + break; + } + } + return rix; +#undef RATE +#undef MCS +#undef DOT11RATE +} + +/* + * Pick a HT rate to begin using. + * + * Don't use any non-HT rates; only consider HT rates. + */ +static int +ath_rate_pick_seed_rate_ht(struct ath_softc *sc, struct ath_node *an, + int frameLen) +{ +#define DOT11RATE(ix) (rt->info[ix].dot11Rate & IEEE80211_RATE_VAL) +#define MCS(ix) (rt->info[ix].dot11Rate | IEEE80211_RATE_MCS) +#define RATE(ix) (DOT11RATE(ix) / 2) + int rix = -1, ht_rix = -1; + const HAL_RATE_TABLE *rt = sc->sc_currates; + struct sample_node *sn = ATH_NODE_SAMPLE(an); + const int size_bin = size_to_bin(frameLen); + + /* no packet has been sent successfully yet */ + for (rix = rt->rateCount-1; rix > 0; rix--) { + /* Skip rates we can't use */ + if ((sn->ratemask & (1<<rix)) == 0) + continue; + + /* Keep a copy of the last seen HT rate index */ + if (rt->info[rix].phy == IEEE80211_T_HT) + ht_rix = rix; + + /* Skip non-HT rates */ + if (rt->info[rix].phy != IEEE80211_T_HT) + continue; + + /* + * Pick a medium-speed rate regardless of stream count + * which has not seen any failures. Higher rates may fail; + * we'll try them later. + */ + if (((MCS(rix) & 0x7) <= 4) && + sn->stats[size_bin][rix].successive_failures == 0) { + break; + } + } + + /* + * If all the MCS rates have successive failures, rix should be + * > 0; otherwise use the lowest MCS rix (hopefully MCS 0.) + */ + return MAX(rix, ht_rix); +#undef RATE +#undef MCS +#undef DOT11RATE +} void @@ -379,20 +469,13 @@ ath_rate_findrate(struct ath_softc *sc, change_rates = 0; if (!sn->packets_sent[size_bin] || best_rix == -1) { /* no packet has been sent successfully yet */ - for (rix = rt->rateCount-1; rix > 0; rix--) { - if ((sn->ratemask & (1<<rix)) == 0) - continue; - /* - * Pick the highest rate <= 36 Mbps - * that hasn't failed. - */ - if (DOT11RATE(rix) <= 72 && - sn->stats[size_bin][rix].successive_failures == 0) { - break; - } - } change_rates = 1; - best_rix = rix; + if (an->an_node.ni_flags & IEEE80211_NODE_HT) + best_rix = + ath_rate_pick_seed_rate_ht(sc, an, frameLen); + else + best_rix = + ath_rate_pick_seed_rate_legacy(sc, an, frameLen); } else if (sn->packets_sent[size_bin] < 20) { /* let the bit-rate switch quickly during the first few packets */ change_rates = 1;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201109050611.p856BHGA023457>