svn commit: r251201 - user/adrian/net80211_tx/sys/net80211

Adrian Chadd adrian at FreeBSD.org
Fri May 31 22:07:29 UTC 2013


Author: adrian
Date: Fri May 31 22:07:28 2013
New Revision: 251201
URL: http://svnweb.freebsd.org/changeset/base/251201

Log:
  Bring over the initial cut of the "teach the PHY code about 11n" work.
  
  This gets a bit odd because the 11n rate representation and the basic
  rate representation involves the same bit (0x80) being set.  In theory
  (hah!) the net80211 stack shouldn't ever have the MCS rates show up
  in code that's tinkering with legacy rates, but this won't hold true
  inside drivers.
  
  There's also the question of how one represents turbo mode rates
  (ie 108mbit) given it will exist with the basic rate bit set (as it
  will be represented as a value > 127.)
  
  So, the changes made:
  
  * Add in 11n aware rate tables, up to MCS23
  * Modify the rate table setup code to not store basic rate entries,
    because doing so means we have an overlap between the basic rate
    tagged legacy rates (which have the 0x80 bit set) and the 11n rates
    (which, sadly, also have the 0x80 bit set.)
  * Add a routine to look up the rate table index given a rate value.
    Since it's for a legacy rate, we strip the basic rate bit.
    (The caller should do this anyway, so I may end up adding an assertion
    at some point to ensure this doesn't happen.)
  
  A few drivers implement some direct prodding of the net80211 rate table;
  something that we really should discourage.  It also turns out that
  the rate table is global rather than per-VAP; again something that
  should be discouraged moving forward.
  
  A follow-up commit will fix the direct prodding of the net80211 rate
  table for rate code -> rate index lookups.

Modified:
  user/adrian/net80211_tx/sys/net80211/ieee80211_phy.c
  user/adrian/net80211_tx/sys/net80211/ieee80211_phy.h

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_phy.c
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_phy.c	Fri May 31 21:55:50 2013	(r251200)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_phy.c	Fri May 31 22:07:28 2013	(r251201)
@@ -60,8 +60,11 @@ struct ieee80211_ds_plcp_hdr {
 #define	TURBO	IEEE80211_T_TURBO
 #define	HALF	IEEE80211_T_OFDM_HALF
 #define	QUART	IEEE80211_T_OFDM_QUARTER
+#define	HT	IEEE80211_T_HT
+/* XXX the 11n and the basic rate flag are unfortunately overlapping. Grr. */
+#define	N(r)	(IEEE80211_RATE_MCS | r)
 #define	PBCC	(IEEE80211_T_OFDM_QUARTER+1)		/* XXX */
-#define	B(r)	(0x80 | r)
+#define	B(r)	(IEEE80211_RATE_BASIC | r)
 #define	Mb(x)	(x*1000)
 
 static struct ieee80211_rate_table ieee80211_11b_table = {
@@ -176,6 +179,98 @@ static struct ieee80211_rate_table ieee8
     },
 };
 
+static struct ieee80211_rate_table ieee80211_11ng_table = {
+    .rateCount = 36,
+    .info = {
+/*                                   short            ctrl  */
+/*                                Preamble  dot11Rate Rate */
+     [0] = { .phy = CCK,     1000,    0x00,      B(2),   0 },
+     [1] = { .phy = CCK,     2000,    0x04,      B(4),   1 },
+     [2] = { .phy = CCK,     5500,    0x04,     B(11),   2 },
+     [3] = { .phy = CCK,    11000,    0x04,     B(22),   3 },
+     [4] = { .phy = OFDM,    6000,    0x00,        12,   4 },
+     [5] = { .phy = OFDM,    9000,    0x00,        18,   4 },
+     [6] = { .phy = OFDM,   12000,    0x00,        24,   6 },
+     [7] = { .phy = OFDM,   18000,    0x00,        36,   6 },
+     [8] = { .phy = OFDM,   24000,    0x00,        48,   8 },
+     [9] = { .phy = OFDM,   36000,    0x00,        72,   8 },
+    [10] = { .phy = OFDM,   48000,    0x00,        96,   8 },
+    [11] = { .phy = OFDM,   54000,    0x00,       108,   8 },
+
+    [12] = { .phy = HT,      6500,    0x00,      N(0),   4 },
+    [13] = { .phy = HT,     13000,    0x00,      N(1),   6 },
+    [14] = { .phy = HT,     19500,    0x00,      N(2),   6 },
+    [15] = { .phy = HT,     26000,    0x00,      N(3),   8 },
+    [16] = { .phy = HT,     39000,    0x00,      N(4),   8 },
+    [17] = { .phy = HT,     52000,    0x00,      N(5),   8 },
+    [18] = { .phy = HT,     58500,    0x00,      N(6),   8 },
+    [19] = { .phy = HT,     65000,    0x00,      N(7),   8 },
+
+    [20] = { .phy = HT,     13000,    0x00,      N(8),   4 },
+    [21] = { .phy = HT,     26000,    0x00,      N(9),   6 },
+    [22] = { .phy = HT,     39000,    0x00,     N(10),   6 },
+    [23] = { .phy = HT,     52000,    0x00,     N(11),   8 },
+    [24] = { .phy = HT,     78000,    0x00,     N(12),   8 },
+    [25] = { .phy = HT,    104000,    0x00,     N(13),   8 },
+    [26] = { .phy = HT,    117000,    0x00,     N(14),   8 },
+    [27] = { .phy = HT,    130000,    0x00,     N(15),   8 },
+
+    [28] = { .phy = HT,     19500,    0x00,     N(16),   4 },
+    [29] = { .phy = HT,     39000,    0x00,     N(17),   6 },
+    [30] = { .phy = HT,     58500,    0x00,     N(18),   6 },
+    [31] = { .phy = HT,     78000,    0x00,     N(19),   8 },
+    [32] = { .phy = HT,    117000,    0x00,     N(20),   8 },
+    [33] = { .phy = HT,    156000,    0x00,     N(21),   8 },
+    [34] = { .phy = HT,    175500,    0x00,     N(22),   8 },
+    [35] = { .phy = HT,    195000,    0x00,     N(23),   8 },
+
+    },
+};
+
+static struct ieee80211_rate_table ieee80211_11na_table = {
+    .rateCount = 32,
+    .info = {
+/*                                   short            ctrl  */
+/*                                Preamble  dot11Rate Rate */
+     [0] = { .phy = OFDM,    6000,    0x00,     B(12),   0 },
+     [1] = { .phy = OFDM,    9000,    0x00,        18,   0 },
+     [2] = { .phy = OFDM,   12000,    0x00,     B(24),   2 },
+     [3] = { .phy = OFDM,   18000,    0x00,        36,   2 },
+     [4] = { .phy = OFDM,   24000,    0x00,     B(48),   4 },
+     [5] = { .phy = OFDM,   36000,    0x00,        72,   4 },
+     [6] = { .phy = OFDM,   48000,    0x00,        96,   4 },
+     [7] = { .phy = OFDM,   54000,    0x00,       108,   4 },
+
+     [8] = { .phy = HT,      6500,    0x00,      N(0),   0 },
+     [9] = { .phy = HT,     13000,    0x00,      N(1),   2 },
+    [10] = { .phy = HT,     19500,    0x00,      N(2),   2 },
+    [11] = { .phy = HT,     26000,    0x00,      N(3),   4 },
+    [12] = { .phy = HT,     39000,    0x00,      N(4),   4 },
+    [13] = { .phy = HT,     52000,    0x00,      N(5),   4 },
+    [14] = { .phy = HT,     58500,    0x00,      N(6),   4 },
+    [15] = { .phy = HT,     65000,    0x00,      N(7),   4 },
+
+    [16] = { .phy = HT,     13000,    0x00,      N(8),   0 },
+    [17] = { .phy = HT,     26000,    0x00,      N(9),   2 },
+    [18] = { .phy = HT,     39000,    0x00,     N(10),   2 },
+    [19] = { .phy = HT,     52000,    0x00,     N(11),   4 },
+    [20] = { .phy = HT,     78000,    0x00,     N(12),   4 },
+    [21] = { .phy = HT,    104000,    0x00,     N(13),   4 },
+    [22] = { .phy = HT,    117000,    0x00,     N(14),   4 },
+    [23] = { .phy = HT,    130000,    0x00,     N(15),   4 },
+
+    [24] = { .phy = HT,     19500,    0x00,     N(16),   0 },
+    [25] = { .phy = HT,     39000,    0x00,     N(17),   2 },
+    [26] = { .phy = HT,     58500,    0x00,     N(18),   2 },
+    [27] = { .phy = HT,     78000,    0x00,     N(19),   4 },
+    [28] = { .phy = HT,    117000,    0x00,     N(20),   4 },
+    [29] = { .phy = HT,    156000,    0x00,     N(21),   4 },
+    [30] = { .phy = HT,    175500,    0x00,     N(22),   4 },
+    [31] = { .phy = HT,    195000,    0x00,     N(23),   4 },
+
+    },
+};
+
 #undef	Mb
 #undef	B
 #undef	OFDM
@@ -184,6 +279,8 @@ static struct ieee80211_rate_table ieee8
 #undef	CCK
 #undef	TURBO
 #undef	XR
+#undef	HT
+#undef	N
 
 /*
  * Setup a rate table's reverse lookup table and fill in
@@ -210,15 +307,23 @@ ieee80211_setup_ratetable(struct ieee802
 		uint8_t cix = rt->info[i].ctlRateIndex;
 		uint8_t ctl_rate = rt->info[cix].dot11Rate;
 
-		rt->rateCodeToIndex[code] = i;
-		if (code & IEEE80211_RATE_BASIC) {
-			/*
-			 * Map w/o basic rate bit too.
-			 */
-			code &= IEEE80211_RATE_VAL;
-			rt->rateCodeToIndex[code] = i;
+		/*
+		 * Map without the basic rate bit.
+		 *
+		 * It's up to the caller to ensure that the basic
+		 * rate bit is stripped here.
+		 *
+		 * For HT, use the MCS rate bit.
+		 */
+		code &= IEEE80211_RATE_VAL;
+		if (rt->info[i].phy == IEEE80211_T_HT) {
+			code |= IEEE80211_RATE_MCS;
 		}
 
+		/* XXX assume the control rate is non-MCS? */
+		ctl_rate &= IEEE80211_RATE_VAL;
+		rt->rateCodeToIndex[code] = i;
+
 		/*
 		 * XXX for 11g the control rate to use for 5.5 and 11 Mb/s
 		 *     depends on whether they are marked as basic rates;
@@ -247,8 +352,8 @@ ieee80211_phy_init(void)
 	static struct ieee80211_rate_table * const ratetables[] = {
 		&ieee80211_half_table,
 		&ieee80211_quarter_table,
-		&ieee80211_11a_table,
-		&ieee80211_11g_table,
+		&ieee80211_11na_table,
+		&ieee80211_11ng_table,
 		&ieee80211_turbog_table,
 		&ieee80211_turboa_table,
 		&ieee80211_turboa_table,
@@ -276,9 +381,9 @@ ieee80211_get_ratetable(struct ieee80211
 	else if (IEEE80211_IS_CHAN_QUARTER(c))
 		rt = &ieee80211_quarter_table;
 	else if (IEEE80211_IS_CHAN_HTA(c))
-		rt = &ieee80211_11a_table;	/* XXX */
+		rt = &ieee80211_11na_table;
 	else if (IEEE80211_IS_CHAN_HTG(c))
-		rt = &ieee80211_11g_table;	/* XXX */
+		rt = &ieee80211_11ng_table;
 	else if (IEEE80211_IS_CHAN_108G(c))
 		rt = &ieee80211_turbog_table;
 	else if (IEEE80211_IS_CHAN_ST(c))
@@ -463,3 +568,66 @@ ieee80211_compute_duration(const struct 
 	}
 	return txTime;
 }
+
+static const uint16_t ht20_bps[32] = {
+	26, 52, 78, 104, 156, 208, 234, 260,
+	52, 104, 156, 208, 312, 416, 468, 520,
+	78, 156, 234, 312, 468, 624, 702, 780,
+	104, 208, 312, 416, 624, 832, 936, 1040
+};
+static const uint16_t ht40_bps[32] = {
+	54, 108, 162, 216, 324, 432, 486, 540,
+	108, 216, 324, 432, 648, 864, 972, 1080,
+	162, 324, 486, 648, 972, 1296, 1458, 1620,
+	216, 432, 648, 864, 1296, 1728, 1944, 2160
+};
+
+
+#define	OFDM_PLCP_BITS	22
+#define	HT_L_STF	8
+#define	HT_L_LTF	8
+#define	HT_L_SIG	4
+#define	HT_SIG		8
+#define	HT_STF		4
+#define	HT_LTF(n)	((n) * 4)
+
+#define	HT_RC_2_MCS(_rc)	((_rc) & 0xf)
+#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
+#define	IS_HT_RATE(_rc)		( (_rc) & IEEE80211_RATE_MCS)
+
+/*
+ * Calculate the transmit duration of an 11n frame.
+ */
+uint32_t
+ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate,
+    int streams, int isht40, int isShortGI)
+{
+	uint32_t bitsPerSymbol, numBits, numSymbols, txTime;
+
+	KASSERT(rate & IEEE80211_RATE_MCS, ("not mcs %d", rate));
+	KASSERT((rate &~ IEEE80211_RATE_MCS) < 31, ("bad mcs 0x%x", rate));
+
+	if (isht40)
+		bitsPerSymbol = ht40_bps[rate & 0x1f];
+	else
+		bitsPerSymbol = ht20_bps[rate & 0x1f];
+	numBits = OFDM_PLCP_BITS + (frameLen << 3);
+	numSymbols = howmany(numBits, bitsPerSymbol);
+	if (isShortGI)
+		txTime = ((numSymbols * 18) + 4) / 5;   /* 3.6us */
+	else
+		txTime = numSymbols * 4;                /* 4us */
+	return txTime + HT_L_STF + HT_L_LTF +
+	    HT_L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+}
+
+#undef	IS_HT_RATE
+#undef	HT_RC_2_STREAMS
+#undef	HT_RC_2_MCS
+#undef	HT_LTF
+#undef	HT_STF
+#undef	HT_SIG
+#undef	HT_L_SIG
+#undef	HT_L_LTF
+#undef	HT_L_STF
+#undef	OFDM_PLCP_BITS

Modified: user/adrian/net80211_tx/sys/net80211/ieee80211_phy.h
==============================================================================
--- user/adrian/net80211_tx/sys/net80211/ieee80211_phy.h	Fri May 31 21:55:50 2013	(r251200)
+++ user/adrian/net80211_tx/sys/net80211/ieee80211_phy.h	Fri May 31 22:07:28 2013	(r251201)
@@ -60,6 +60,8 @@
 
 struct ieee80211_channel;
 
+#define	IEEE80211_RATE_TABLE_SIZE	128
+
 struct ieee80211_rate_table {
 	int		rateCount;		/* NB: for proper padding */
 	uint8_t		rateCodeToIndex[256];	/* back mapping */
@@ -74,7 +76,7 @@ struct ieee80211_rate_table {
 						 * rate; used for dur. calcs */
 		uint16_t	lpAckDuration;	/* long preamble ACK dur. */
 		uint16_t	spAckDuration;	/* short preamble ACK dur. */
-	} info[32];
+	} info[IEEE80211_RATE_TABLE_SIZE];
 };
 
 const struct ieee80211_rate_table *ieee80211_get_ratetable(
@@ -134,6 +136,14 @@ ieee80211_ack_duration(const struct ieee
 	}
 }
 
+static __inline__ uint8_t
+ieee80211_legacy_rate_lookup(const struct ieee80211_rate_table *rt,
+    uint8_t rate)
+{
+
+	return (rt->rateCodeToIndex[rate & IEEE80211_RATE_VAL]);
+}
+
 /*
  * Compute the time to transmit a frame of length frameLen bytes
  * using the specified 802.11 rate code, phy, and short preamble
@@ -151,5 +161,10 @@ uint8_t		ieee80211_plcp2rate(uint8_t, en
  * Convert 802.11 rate code to PLCP signal.
  */
 uint8_t		ieee80211_rate2plcp(int, enum ieee80211_phytype);
+
+uint32_t	ieee80211_compute_duration_ht(uint32_t frameLen,
+			uint16_t rate, int streams, int isht40,
+			int isShortGI);
+
 #endif	/* _KERNEL */
 #endif	/* !_NET80211_IEEE80211_PHY_H_ */


More information about the svn-src-user mailing list