Skip site navigation (1)Skip section navigation (2)
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>