Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Jul 2013 11:28:31 +0800
From:      Chenchong Qin <qinchenchong@gmail.com>
To:        freebsd-wireless@freebsd.org
Subject:   Chenchong's work on net80211_ratectl
Message-ID:  <CAFnsE3dYdPf5yGTFH683Q1Zh0mc-g%2B_YtCTraNNt28z2vBoSKw@mail.gmail.com>

index | next in thread | raw e-mail

[-- Attachment #1 --]
Hi, there!

Attachment is the diff that contains my work on net80211_ratectl done these
days.

I've done the fllowing things:

1) Add some rc options.
Chip can tell some options (i.e. whether mrr and mrrprot is support,
whether have more than 1 txchain, etc.) to rc code when rc is initializing.
Then rc algo can calc rates with these options in mind and do the right
things.

2) Support multi-rate attempt.
Instead of returning just one rate, let rc return up to 4 rates. I add
ieee80211_rc_series. Basically, it's just a copy of ath_rc_series but drop
max4msframelen filed (it seems that max4msframelen is not used to setup the
rc stuffs). And at each rate lookup, rc can get shortPreamble and frameLen
info from the caller.

3) Support some 11n features.
Add some 11n features (i.e. cw40, short-gi, stbc) to net80211 rc stuffs. To
be frankly, I just let the rc algo decide whether to use the 11n features.
But I do provide rc algo with some abilities to know whether particular
feature can be used. Then, rc algo can do rate decisions based on these cap
info.

Besides, I use iv_htcaps other than ic_htcaps to decide the 11n features
capabilities. I think iv_htcaps is more relevant to per vap rc operations
and I found iv_htcaps is just a copy of ic_htcaps at first (but some caps
may to be disabled by some vaps). But I'm not sure whether this can operate
properly by now.

Once the rc algo decides to use one 11n feature for some rate attemps, it
must set corresponding rate flags. This is not the same as before. For now,
the rc algo get more power and then it comes more responsibility.

4) Complete the rc flags
After the rate lookup, we have an opportunity to make sure that rc code
doesn't mess it up. I blank tries 1, 2, 3 if rts/cts is enabled and it's a
pre-802.11n scenario.

It's also the chance to fill some rate options/flags that the rc algo may
not be interested by now.

Looking forward to your feedbacks!

Thanks!

Chenchong

[-- Attachment #2 --]
Index: net80211/ieee80211_ratectl.c
===================================================================
--- net80211/ieee80211_ratectl.c	(revision 254826)
+++ net80211/ieee80211_ratectl.c	(working copy)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
+ * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -66,10 +67,11 @@
 }
 
 void
-ieee80211_ratectl_init(struct ieee80211vap *vap)
+ieee80211_ratectl_init(struct ieee80211vap *vap, uint32_t options)
 {
 	if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
 		ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
+	vap->iv_rate.options = options;
 	vap->iv_rate->ir_init(vap);
 }
 
Index: net80211/ieee80211_ratectl.h
===================================================================
--- net80211/ieee80211_ratectl.h	(revision 254826)
+++ net80211/ieee80211_ratectl.h	(working copy)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
+ * Copyright (c) 2013 Chenchong Qin <ccqin@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,8 +38,41 @@
 #define	IEEE80211_RATECTL_TX_SUCCESS	1
 #define	IEEE80211_RATECTL_TX_FAILURE	0
 
+#define	IEEE80211_RATECTL_TRUE		1
+#define	IEEE80211_RATECTL_FALSE		0
+
+#define	IEEE80211_RATECTL_NUM		4
+
+#define	IEEE80211_RATECTL_DS_FLAG		0x01	/* dual-stream rate */
+#define	IEEE80211_RATECTL_CW40_FLAG		0x02	/* use HT40 */
+#define	IEEE80211_RATECTL_SGI_FLAG		0x04	/* use short-GI */
+#define	IEEE80211_RATECTL_HT_FLAG		0x08	/* use HT */
+#define	IEEE80211_RATECTL_RTSCTS_FLAG	0x10	/* enable RTS/CTS protection */
+#define	IEEE80211_RATECTL_STBC_FLAG		0x20	/* enable STBC */
+#define	IEEE80211_RATECTL_TS_FLAG		0x40	/* triple-stream rate */
+
+/* Hardware options chip offered to rate control code */
+#define	IEEE80211_RATECTL_OPT_MRR			0x01	/* support MRR */
+#define	IEEE80211_RATECTL_OPT_MRRPROT		0x02	/* support MRR + protect */
+#define	IEEE80211_RATECTL_OPT_MULTXCHAIN	0x04	/* has more than 1 txchain */
+
+#define IS_VAP_HT(vap)	((vap)->iv_htcaps & IEEE80211_HTC_HT)
+
+#define IS_HT_RATE(_rate)   ((_rate) & 0x80)
+#define HT_RC_2_MCS(_rc)    ((_rc) & 0x7f)
+#define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
+
+struct ieee80211_rc_series {
+	uint8_t rix;		/* ratetable index, not rate code */
+	uint8_t ratecode;	/* hardware rate code */
+	uint8_t tries;
+	uint8_t tx_power_cap;
+	uint16_t flags;
+};
+
 struct ieee80211_ratectl {
 	const char *ir_name;
+	uint32_t options;		/* IEEE80211_RATECTL_OPTs */
 	int	(*ir_attach)(const struct ieee80211vap *);
 	void	(*ir_detach)(const struct ieee80211vap *);
 	void	(*ir_init)(struct ieee80211vap *);
@@ -46,6 +80,7 @@
 	void	(*ir_node_init)(struct ieee80211_node *);
 	void	(*ir_node_deinit)(struct ieee80211_node *);
 	int	(*ir_rate)(struct ieee80211_node *, void *, uint32_t);
+	void	(*ir_rates)(struct ieee80211_node *, struct ieee80211_rc_series *, int, size_t);
 	void	(*ir_tx_complete)(const struct ieee80211vap *,
 	    			  const struct ieee80211_node *, int,
 	    			  void *, void *);
@@ -57,7 +92,7 @@
 
 void	ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
 void	ieee80211_ratectl_unregister(int);
-void	ieee80211_ratectl_init(struct ieee80211vap *);
+void	ieee80211_ratectl_init(struct ieee80211vap *, uint32_t);
 void	ieee80211_ratectl_set(struct ieee80211vap *, int);
 
 MALLOC_DECLARE(M_80211_RATECTL);
@@ -69,11 +104,11 @@
 }
 
 static void __inline
-ieee80211_ratectl_node_init(struct ieee80211_node *ni)
+ieee80211_ratectl_node_init(struct ieee80211_node *ni, uint32_t options)
 {
 	const struct ieee80211vap *vap = ni->ni_vap;
 
-	vap->iv_rate->ir_node_init(ni);
+	vap->iv_rate->ir_node_init(ni, options);
 }
 
 static void __inline
@@ -93,6 +128,17 @@
 }
 
 static void __inline
+ieee80211_ratectl_rates(struct ieee80211_node *ni, struct ieee80211_rc_series *rc,
+		int shortPreamble, size_t frameLen)
+{
+	const struct ieee80211vap *vap = ni->ni_vap;
+
+	vap->iv_rate->ir_rates(ni, rc, shortPreamble, frameLen);
+	
+	ieee80211_ratectl_complete_rcflags(ni, rc, shortPreamble);
+}
+
+static void __inline
 ieee80211_ratectl_tx_complete(const struct ieee80211vap *vap,
     const struct ieee80211_node *ni, int status, void *arg1, void *arg2)
 {
@@ -115,3 +161,106 @@
 		return;
 	vap->iv_rate->ir_setinterval(vap, msecs);
 }
+
+static int __inline
+ieee80211_ratectl_hascap_cw40(const struct ieee80211vap *vap,
+		const struct ieee80211_node *ni)
+{
+	return IS_VAP_HT(vap) && (ni->ni_chw == 40);
+}
+
+static int __inline
+ieee80211_ratectl_hascap_shortgi(const struct ieee80211vap *vap,
+		const struct ieee80211_node *ni)
+{
+	if (! IS_VAP_HT(vap))
+		return IEEE80211_RATECTL_FALSE;
+
+	if (ni->ni_chw == 40 &&
+			vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
+			ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+		return IEEE80211_RATECTL_TRUE;
+
+	if (ni->ni_chw == 20 &&
+			vap->iv_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
+			ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
+		return IEEE80211_RATECTL_TRUE;
+}
+
+
+static int __inline
+ieee80211_ratectl_hascap_stbc(const struct ieee80211vap *vap,
+		const struct ieee80211_node *ni)
+{
+   return IS_VAP_HT(vap) && (vap->iv_htcaps & IEEE80211_HTCAP_TXSTBC) &&
+			    (ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM) &&
+			    (vap->iv_rate->options & IEEE80211_RATECTL_OPT_MULTXCHAIN);
+}
+
+static void
+ieee80211_ratectl_complete_rcflags(struct ieee80211_node *ni,
+		struct ieee80211_rc_series *rc, int shortPreamble)
+{
+	struct ieee80211com *ic = ni->ni_ic;
+	const struct ieee80211_rate_table * rt = ic->ic_rt;
+	uint8_t rate0, rate;
+	int i;
+
+	rate0 = rt->info[rc[0].rix].rateCode;
+	
+	/* Make sure that rate control code doesn't mess it up.
+	 * If enable rts/cts and is pre-802.11n, blank tries 1, 2, 3 
+	 */
+
+	if (! IS_HT_RATE(rate0))
+	{
+		if (rc[0].flags & IEEE80211_RATECTL_RTSCTS_FLAG)
+			rc[1].tries = rc[2].tries = rc[3].tries = 0;
+		rc[1].flags &= ~IEEE80211_RATECTL_RTSCTS_FLAG; 
+		rc[2].flags &= ~IEEE80211_RATECTL_RTSCTS_FLAG; 
+		rc[3].flags &= ~IEEE80211_RATECTL_RTSCTS_FLAG; 
+	}
+
+	for (i = 0; i < IEEE80211_RATECTL_NUM; i++) {
+		
+		if (rc[i].tries == 0)
+			continue;
+
+		rate = rt->info[rc[i].rix].rateCode;
+
+		/*
+		 * Only enable short preamble for legacy rates
+		 */
+		if ((! IS_HT_RATE(rate)) && shortPreamble)
+			rate |= rt->info[rc[i].rix].shortPreamble;
+
+		/*
+		 * Save this, used by the TX and completion code
+		 */
+		rc[i].ratecode = rate;
+
+		/* Only enable shortgi, 2040, dual-stream if HT is set */
+		if (IS_HT_RATE(rate)) {
+			rc[i].flags |= IEEE80211_RATECTL_HT_FLAG;
+
+			/*
+			 * XXX TODO: LDPC
+			 */
+
+			/*
+			 * Dual / Triple stream rate?
+			 */
+			if (HT_RC_2_STREAMS(rate) == 2)
+				rc[i].flags |= IEEE80211_RATECTL_DS_FLAG;
+			else if (HT_RC_2_STREAMS(rate) == 3)
+				rc[i].flags |= IEEE80211_RATECTL_TS_FLAG;
+		}
+
+		/*
+		 * Calculate the maximum TX power cap for the current
+		 * node. 
+		 * Rate control algo can't control TX power by now.
+		 */
+		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
+	}
+}
help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFnsE3dYdPf5yGTFH683Q1Zh0mc-g%2B_YtCTraNNt28z2vBoSKw>