Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Jul 2013 21:38:43 +0800
From:      Chenchong Qin <qinchenchong@gmail.com>
To:        Adrian Chadd <adrian@freebsd.org>
Cc:        freebsd-wireless@freebsd.org
Subject:   Re: Chenchong's work on net80211_ratectl
Message-ID:  <CAFnsE3eaOyRcO3LXSi3L=jbzpyMv5Nt_jRGKt_mmA0WV-EV5vA@mail.gmail.com>
In-Reply-To: <CAJ-Vmo=k8NddAYyAJCkx4eOaA_8XsSxg6uKrdddx%2BgmeT%2BX9KA@mail.gmail.com>
References:  <CAFnsE3dYdPf5yGTFH683Q1Zh0mc-g%2B_YtCTraNNt28z2vBoSKw@mail.gmail.com> <CAJ-Vmom4sY7jcNwWmJkrDwfWjsok2fk8UEwTi5A=egj1JyerLw@mail.gmail.com> <CAFnsE3cyg=msBfQqqKUMmLABSL=j24VoMBwbBjxQ6b7Dyy7Mqg@mail.gmail.com> <CAJ-Vmo=k8NddAYyAJCkx4eOaA_8XsSxg6uKrdddx%2BgmeT%2BX9KA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
My pleasure!

It's also against HEAD.

Thanks!


On Wed, Jul 24, 2013 at 9:15 PM, Adrian Chadd <adrian@freebsd.org> wrote:

> cool!
>
> Would you mind posting an updated diff?
>
>
>
> -adrian
>
> On 24 July 2013 01:39, Chenchong Qin <qinchenchong@gmail.com> wrote:
> >
> > Hi!
> >
> > Thanks for your constructive feedback!
> >
> > First, I've done some renaming things. IEEE80211_RATECTL_OPT_* became
> > IEEE80211_RATECTL_CAP_* and options in ieee80211_ratectl became
> > ir_capabilities.
> >
> > As for max4msframelen , I re-added this field and also ported
> > ath_max_4ms_framelen[4][32] to ieee80211_ratectl.
> >
> > An error is also corrected (about initialization of ir_capabilities).
> >
> >
> > On Tue, Jul 23, 2013 at 10:30 PM, Adrian Chadd <adrian@freebsd.org>
> wrote:
> >>
> >>
> >> * Why do you have IEEE80211_RATECTL_OPT_MULTXCHAIN ?
> >
> >
> > IEEE80211_RATECTL_OPT_MULTXCHAIN is used in
> ieee80211_ratectl_hascap_stbc()
> > to assist the determination of whether we can enable STBC.
> >
> >> * The reason why I check both the vap/ic and the node bits for HT
> >> capabilities is that they're negotiated. The node bits are what the
> >> remote peer supports. The vap/ic bits are what the local device/vap
> >> supports. So, if the remote node supports STBC and the local node
> >> doesn't, we shouldn't try transmitting short-GI.
> >
> >
> > uh... I also do the "double check" stuff. Do the
> ieee80211_ratectl_hascap_*
> > functions do
> > wrong things? And, I'm not very clear about the relation between STBC and
> > short-GI now.
> > It seems that I need some further reading. :)
> >
> >>
> >> * In ieee80211_ratectl_complete_rcflags(), enabling RTS/CTS but not
> >> transmitting an 11n rate isn't "right." The 11n hardware supports
> >> per-rate RTS/CTS for non-HT rates. You have to ensure that works.
> >> You've added a capability bit for this (IEEE80211_RATECTL_OPT_MRRPROT)
> >> so you should use it.
> >
> >
> > Yeah... here my logic messed up. It's corrected.
> >
> >>
> >> * the new rate field "options" should be "ir_options", like how the
> >> rest of the fields are prefixed with ir_
> >> * .. and, nitpicking, it should be "ir_capabilities".
> >>
> >
> > It's already done.
> >
> >
> > 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
@@ -49,6 +50,33 @@
 
 MALLOC_DEFINE(M_80211_RATECTL, "80211ratectl", "802.11 rate control");
 
+int max_4ms_framelen[4][32] = {
+	[MCS_HT20] = {
+		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
+		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
+		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
+		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
+	},
+	[MCS_HT20_SGI] = {
+		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
+		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
+		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
+		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
+	},
+	[MCS_HT40] = {
+		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
+		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
+		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
+		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
+	},
+	[MCS_HT40_SGI] = {
+		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
+		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
+		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
+		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
+	}
+};
+
 void
 ieee80211_ratectl_register(int type, const struct ieee80211_ratectl *ratectl)
 {
@@ -66,10 +94,11 @@
 }
 
 void
-ieee80211_ratectl_init(struct ieee80211vap *vap)
+ieee80211_ratectl_init(struct ieee80211vap *vap, uint32_t capabilities)
 {
 	if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
 		ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
+	vap->iv_rate.ir_capabilities = capabilities;
 	vap->iv_rate->ir_init(vap);
 }
 
@@ -90,3 +119,95 @@
 	}
 	vap->iv_rate = ratectls[type];
 }
+
+void
+ieee80211_ratectl_complete_rcflags(const struct ieee80211_node *ni,
+		struct ieee80211_rc_series *rc, int shortPreamble)
+{
+	const struct ieee80211com *ic = ni->ni_ic;
+	const struct ieee80211vap *vap = ni->ni_vap;
+	const struct ieee80211_rate_table * rt = ic->ic_rt;
+	uint8_t rate;
+	int i;
+
+	/* 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 (! (vap->iv_rate->ir_capabilities & IEEE80211_RATECTL_CAP_MRRPROT))
+	{
+		for (i = 1; i < IEEE80211_RATECTL_NUM; i++)
+		{
+			if (rc[0].flags & IEEE80211_RATECTL_RTSCTS_FLAG)
+				rc[i].tries = 0;
+			rc[i].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);
+		
+		/*
+		 * Calculate the maximum 4ms frame length based
+		 * on the MCS rate, SGI and channel width flags.
+		 */
+		if ((rc[i].flags & IEEE80211_RATECTL_HT_FLAG) &&
+		    (HT_RC_2_MCS(rate) < 32)) {
+			int j;
+			if (rc[i].flags & IEEE80211_RATECTL_CW40_FLAG) {
+				if (rc[i].flags & IEEE80211_RATECTL_SGI_FLAG)
+					j = MCS_HT40_SGI;
+				else
+					j = MCS_HT40;
+			} else {
+				if (rc[i].flags & IEEE80211_RATECTL_SGI_FLAG)
+					j = MCS_HT20_SGI;
+				else
+					j = MCS_HT20;
+			}
+			rc[i].max4msframelen =
+			    max_4ms_framelen[j][HT_RC_2_MCS(rate)];
+		} else
+			rc[i].max4msframelen = 0;
+	}
+}
+
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
@@ -24,6 +25,8 @@
  *
  * $FreeBSD$
  */
+#ifndef _NET80211_IEEE80211_RATECTL_H_
+#define _NET80211_IEEE80211_RATECTL_H_
 
 enum ieee80211_ratealgs {
 	IEEE80211_RATECTL_AMRR		= 0,
@@ -34,11 +37,56 @@
 	IEEE80211_RATECTL_MAX
 };
 
+enum {
+	MCS_HT20,
+	MCS_HT20_SGI,
+	MCS_HT40,
+	MCS_HT40_SGI,
+};
+
 #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 CAPs chip offered to rate control code */
+#define	IEEE80211_RATECTL_CAP_MRR			0x01	/* support MRR */
+#define	IEEE80211_RATECTL_CAP_MRRPROT		0x02	/* support MRR + protect */
+#define	IEEE80211_RATECTL_CAP_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)
+
+
+extern int max_4ms_framelen[4][32];
+
+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;
+	uint16_t max4msframelen;
+};
+
 struct ieee80211_ratectl {
 	const char *ir_name;
+	uint32_t ir_capabilities;		/* hardware capabilities offered to rc */
+
 	int	(*ir_attach)(const struct ieee80211vap *);
 	void	(*ir_detach)(const struct ieee80211vap *);
 	void	(*ir_init)(struct ieee80211vap *);
@@ -46,6 +94,8 @@
 	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,8 +107,10 @@
 
 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);
+void	ieee80211_ratectl_complete_rcflags(const struct ieee80211_node *, 
+		struct ieee80211_rc_series *, int)
 
 MALLOC_DECLARE(M_80211_RATECTL);
 
@@ -93,6 +145,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 +178,40 @@
 		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->ir_capabilities & IEEE80211_RATECTL_CAP_MULTXCHAIN);
+}
+
+#endif

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAFnsE3eaOyRcO3LXSi3L=jbzpyMv5Nt_jRGKt_mmA0WV-EV5vA>