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>
