On Tue, Jan 22, 2019 at 04:28:03PM +0100, Stefan Sperling wrote:
> Move 11n rateset definitions out of MiRA and make them available to
> net80211 and drivers in general. At the same time, I'm adding support
> for 'short guard interval' (SGI) mode to MiRA. SGI is currently only
> used by iwm(4), and of course internally by bwfm(4) firmware.
>
> We will need additional definitions for 40 MHz channel mode, but
> those can be added later. See mcsindex.com for the full list of
> what we'll eventually need.
>
> OK?
The iwm part of the previous diff had a small bug. Fixed in this version.
Index: dev/pci/if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.233
diff -u -p -r1.233 if_iwm.c
--- dev/pci/if_iwm.c 22 Sep 2018 13:55:55 -0000 1.233
+++ dev/pci/if_iwm.c 22 Jan 2019 15:30:21 -0000
@@ -5948,7 +5948,7 @@ iwm_setrates(struct iwm_node *in)
struct iwm_softc *sc = IC2IFP(ic)->if_softc;
struct iwm_lq_cmd *lq = &in->in_lq;
struct ieee80211_rateset *rs = &ni->ni_rates;
- int i, ridx, ridx_min, ridx_max, j, sgi_ok, mimo, tab = 0;
+ int i, ridx, ridx_min, ridx_max, j, sgi_ok = 0, mimo, tab = 0;
struct iwm_host_cmd cmd = {
.id = IWM_LQ_CMD,
.len = { sizeof(in->in_lq), },
@@ -5960,8 +5960,11 @@ iwm_setrates(struct iwm_node *in)
if (ic->ic_flags & IEEE80211_F_USEPROT)
lq->flags |= IWM_LQ_FLAG_USE_RTS_MSK;
- sgi_ok = ((ni->ni_flags & IEEE80211_NODE_HT) &&
- (ni->ni_htcaps & IEEE80211_HTCAP_SGI20));
+ if ((ni->ni_flags & IEEE80211_NODE_HT) &&
+ ieee80211_node_supports_ht_sgi20(ni)) {
+ ni->ni_flags |= IEEE80211_NODE_HT_SGI20;
+ sgi_ok = 1;
+ }
/*
* Fill the LQ rate selection table with legacy and/or HT rates
Index: net80211/ieee80211.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211.c,v
retrieving revision 1.70
diff -u -p -r1.70 ieee80211.c
--- net80211/ieee80211.c 11 Sep 2018 18:16:26 -0000 1.70
+++ net80211/ieee80211.c 22 Jan 2019 14:02:00 -0000
@@ -703,6 +703,32 @@ const struct ieee80211_rateset ieee80211
const struct ieee80211_rateset ieee80211_std_rateset_11g =
{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
+const struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[] = {
+ /* MCS 0-7, 20MHz channel, no SGI */
+ { 8, { 13, 26, 39, 52, 78, 104, 117, 130 }, 0x000000ff, 0, 7, 0},
+
+ /* MCS 0-7, 20MHz channel, SGI */
+ { 8, { 14, 29, 43, 58, 87, 116, 130, 144 }, 0x000000ff, 0, 7, 1 },
+
+ /* MCS 8-15, 20MHz channel, no SGI */
+ { 8, { 26, 52, 78, 104, 156, 208, 234, 260 }, 0x0000ff00, 8, 15, 0 },
+
+ /* MCS 8-15, 20MHz channel, SGI */
+ { 8, { 29, 58, 87, 116, 173, 231, 261, 289 }, 0x0000ff00, 8, 15, 1 },
+
+ /* MCS 16-23, 20MHz channel, no SGI */
+ { 8, { 39, 78, 117, 156, 234, 312, 351, 390 }, 0x00ff0000, 16, 23, 0 },
+
+ /* MCS 16-23, 20MHz channel, SGI */
+ { 8, { 43, 87, 130, 173, 260, 347, 390, 433 }, 0x00ff0000, 16, 23, 1 },
+
+ /* MCS 24-31, 20MHz channel, no SGI */
+ { 8, { 52, 104, 156, 208, 312, 416, 468, 520 }, 0xff000000, 24, 31, 0 },
+
+ /* MCS 24-31, 20MHz channel, SGI */
+ { 8, { 58, 116, 173, 231, 347, 462, 520, 578 }, 0xff000000, 24, 31, 1 },
+};
+
/*
* Mark the basic rates for the 11g rate table based on the
* operating mode. For real 11g we mark all the 11b rates
Index: net80211/ieee80211_mira.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_mira.c,v
retrieving revision 1.12
diff -u -p -r1.12 ieee80211_mira.c
--- net80211/ieee80211_mira.c 11 Jul 2018 21:18:23 -0000 1.12
+++ net80211/ieee80211_mira.c 22 Jan 2019 14:43:07 -0000
@@ -34,12 +34,12 @@
/* Allow for aggressive down probing when channel quality changes. */
#define MIRA_AGGRESSIVE_DOWNWARDS_PROBING
-const struct ieee80211_mira_rateset * ieee80211_mira_get_rateset(int);
+const struct ieee80211_ht_rateset * ieee80211_mira_get_rateset(int, int);
void ieee80211_mira_probe_timeout_up(void *);
void ieee80211_mira_probe_timeout_down(void *);
-uint64_t ieee80211_mira_get_txrate(int);
+uint64_t ieee80211_mira_get_txrate(int, int);
uint16_t ieee80211_mira_legacy_txtime(uint32_t, int, struct ieee80211com *);
-uint32_t ieee80211_mira_ht_txtime(uint32_t, int, int);
+uint32_t ieee80211_mira_ht_txtime(uint32_t, int, int, int);
int ieee80211_mira_best_basic_rate(struct ieee80211_node *);
int ieee80211_mira_ack_rate(struct ieee80211_node *);
uint64_t ieee80211_mira_toverhead(struct ieee80211_mira_node *,
@@ -52,12 +52,12 @@ int ieee80211_mira_next_lower_intra_rate
struct ieee80211_node *);
int ieee80211_mira_next_intra_rate(struct ieee80211_mira_node *,
struct ieee80211_node *);
-const struct ieee80211_mira_rateset * ieee80211_mira_next_rateset(
- struct ieee80211_mira_node *, int);
+const struct ieee80211_ht_rateset * ieee80211_mira_next_rateset(
+ struct ieee80211_mira_node *, struct ieee80211_node *);
int ieee80211_mira_best_mcs_in_rateset(struct ieee80211_mira_node *,
- const struct ieee80211_mira_rateset *);
+ const struct ieee80211_ht_rateset *);
void ieee80211_mira_probe_next_rateset(struct ieee80211_mira_node *,
- struct ieee80211_node *, const struct ieee80211_mira_rateset *);
+ struct ieee80211_node *, const struct ieee80211_ht_rateset *);
int ieee80211_mira_next_mcs(struct ieee80211_mira_node *,
struct ieee80211_node *);
int ieee80211_mira_prev_mcs(struct ieee80211_mira_node *,
@@ -84,7 +84,7 @@ void ieee80211_mira_probe_next_rate(stru
int ieee80211_mira_valid_tx_mcs(struct ieee80211com *, int);
uint32_t ieee80211_mira_valid_rates(struct ieee80211com *,
struct ieee80211_node *);
-uint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int);
+uint32_t ieee80211_mira_mcs_below(struct ieee80211_mira_node *, int, int);
/* We use fixed point arithmetic with 64 bit integers. */
#define MIRA_FP_SHIFT 21
@@ -150,56 +150,16 @@ mira_print_driver_stats(struct ieee80211
}
#endif /* MIRA_DEBUG */
-/*
- * Rate tables.
- */
-
-/* Index into ieee80211_mira_ratesets[] array. */
-#define IEEE80211_MIRA_RATESET_SISO 0
-#define IEEE80211_MIRA_RATESET_MIMO2 1
-#define IEEE80211_MIRA_RATESET_MIMO3 2
-#define IEEE80211_MIRA_RATESET_MIMO4 3
-
-#define IEEE80211_MIRA_RATESET_MAX 8 /* Maximum number of rates in a rateset.
*/
-struct ieee80211_mira_rateset {
- uint32_t nrates;
- uint32_t rates[IEEE80211_MIRA_RATESET_MAX];
- uint32_t mcs_mask;
- int min_mcs;
- int max_mcs;
-} ieee80211_mira_ratesets[] = {
-/* XXX We only support MCS 0-31, for now. */
-#ifdef notyet
- /* Legacy rates on a 2GHz channel. */
- { 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }, 0x0, -1, -1 },
-
- /* Legacy rates on a 5GHz channel. */
- { 8, { 12, 18, 24, 36, 48, 72, 96, 108 }, 0x0, -1, -1 },
-#endif
- /* MCS 0-7, 20MHz channel, no SGI */
- { 8, { 13, 26, 39, 52, 78, 104, 117, 130 }, 0x000000ff, 0, 7 },
-
- /* MCS 8-15, 20MHz channel, no SGI */
- { 8, { 26, 52, 78, 104, 156, 208, 234, 260 }, 0x0000ff00, 8, 15 },
-
- /* MCS 16-23, 20MHz channel, no SGI */
- { 8, { 39, 78, 117, 156, 234, 312, 351, 390 }, 0x00ff0000, 16, 23 },
-
- /* MCS 24-31, 20MHz channel, no SGI */
- { 8, { 52, 104, 156, 208, 312, 416, 468, 520 }, 0xff000000, 24, 31 },
-};
-
-/* XXX We only support HT rates, for now. With legacy added, these differ. */
-#define IEEE80211_MIRA_NUM_MCS IEEE80211_MIRA_NUM_RATES
-
-const struct ieee80211_mira_rateset *
-ieee80211_mira_get_rateset(int mcs)
+const struct ieee80211_ht_rateset *
+ieee80211_mira_get_rateset(int mcs, int sgi)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
int i;
- for (i = 0; i < nitems(ieee80211_mira_ratesets); i++) {
- rs = &ieee80211_mira_ratesets[i];
+ for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {
+ rs = &ieee80211_std_ratesets_11n[i];
+ if (sgi != rs->sgi)
+ continue;
if (mcs >= rs->min_mcs && mcs <= rs->max_mcs)
return rs;
}
@@ -244,12 +204,12 @@ ieee80211_mira_probe_timeout_down(void *
*/
uint64_t
-ieee80211_mira_get_txrate(int mcs)
+ieee80211_mira_get_txrate(int mcs, int sgi)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
uint64_t txrate;
- rs = ieee80211_mira_get_rateset(mcs);
+ rs = ieee80211_mira_get_rateset(mcs, sgi);
txrate = rs->rates[mcs - rs->min_mcs];
txrate <<= MIRA_FP_SHIFT; /* convert to fixed-point */
txrate *= 500; /* convert to kbit/s */
@@ -281,9 +241,9 @@ ieee80211_mira_legacy_txtime(uint32_t le
}
uint32_t
-ieee80211_mira_ht_txtime(uint32_t len, int mcs, int is2ghz)
+ieee80211_mira_ht_txtime(uint32_t len, int mcs, int is2ghz, int sgi)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
/* XXX These constants should be macros in ieee80211.h instead. */
const uint32_t t_lstf = 8; /* usec legacy short training field */
const uint32_t t_lltf = 8; /* usec legacy long training field */
@@ -292,6 +252,7 @@ ieee80211_mira_ht_txtime(uint32_t len, i
const uint32_t t_ltstf = 4; /* usec HT long training field */
const uint32_t t_htsig = 8; /* usec HT signal field */
const uint32_t t_sym = 4; /* usec symbol interval */
+ const uint32_t t_syms = 3; /* usec symbol interval; XXX actually 3.6 */
uint32_t n_sym, n_dbps;
uint32_t t_plcp;
uint32_t t_data;
@@ -304,10 +265,13 @@ ieee80211_mira_ht_txtime(uint32_t len, i
* XXX Assumes a 20MHz channel, HT-mixed frame format, no STBC.
*/
t_plcp = t_lstf + t_lltf + t_lsig + t_htstf + 4 * t_ltstf + t_htsig;
- rs = ieee80211_mira_get_rateset(mcs);
+ rs = ieee80211_mira_get_rateset(mcs, sgi);
n_dbps = rs->rates[mcs - rs->min_mcs] * 2;
n_sym = ((8 * len + 16 + 6) / n_dbps); /* "Equation (20-32)" */
- t_data = t_sym * n_sym;
+ if (sgi)
+ t_data = (t_syms * n_sym) / t_sym;
+ else
+ t_data = t_sym * n_sym;
txtime = t_plcp + t_data;
if (is2ghz)
@@ -370,9 +334,10 @@ ieee80211_mira_toverhead(struct ieee8021
uint64_t toverhead;
int rate, rts;
enum ieee80211_htprot htprot;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
overhead = ieee80211_mira_ht_txtime(0, ni->ni_txmcs,
- IEEE80211_IS_CHAN_2GHZ(ni->ni_chan));
+ IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi);
htprot = (ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK);
if (htprot == IEEE80211_HTPROT_NONMEMBER ||
@@ -404,9 +369,9 @@ ieee80211_mira_toverhead(struct ieee8021
if (mira_debug > 3) {
uint32_t txtime;
txtime = ieee80211_mira_ht_txtime(mn->ampdu_size, ni->ni_txmcs,
- IEEE80211_IS_CHAN_2GHZ(ni->ni_chan));
+ IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi);
txtime += overhead - ieee80211_mira_ht_txtime(0, ni->ni_txmcs,
- IEEE80211_IS_CHAN_2GHZ(ni->ni_chan));
+ IEEE80211_IS_CHAN_2GHZ(ni->ni_chan), sgi);
DPRINTFN(4, ("txtime: %u usec\n", txtime));
DPRINTFN(4, ("overhead: %u usec\n", overhead));
DPRINTFN(4, ("toverhead: %s\n", mira_fp_sprintf(toverhead)));
@@ -425,7 +390,8 @@ ieee80211_mira_update_stats(struct ieee8
uint64_t sfer, delta, toverhead;
uint64_t agglen = mn->agglen;
uint64_t ampdu_size = mn->ampdu_size * 8; /* convert to bits */
- uint64_t rate = ieee80211_mira_get_txrate(ni->ni_txmcs);
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
+ uint64_t rate = ieee80211_mira_get_txrate(ni->ni_txmcs, sgi);
struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];
g->nprobes += mn->agglen;
@@ -544,10 +510,11 @@ int
ieee80211_mira_next_lower_intra_rate(struct ieee80211_mira_node *mn,
struct ieee80211_node *ni)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
int i, next;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_mira_get_rateset(ni->ni_txmcs);
+ rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi);
if (ni->ni_txmcs == rs->min_mcs)
return rs->min_mcs;
@@ -568,10 +535,11 @@ int
ieee80211_mira_next_intra_rate(struct ieee80211_mira_node *mn,
struct ieee80211_node *ni)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
int i, next;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_mira_get_rateset(ni->ni_txmcs);
+ rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi);
if (ni->ni_txmcs == rs->max_mcs)
return rs->max_mcs;
@@ -588,35 +556,44 @@ ieee80211_mira_next_intra_rate(struct ie
return next;
}
-const struct ieee80211_mira_rateset *
-ieee80211_mira_next_rateset(struct ieee80211_mira_node *mn, int mcs)
+const struct ieee80211_ht_rateset *
+ieee80211_mira_next_rateset(struct ieee80211_mira_node *mn,
+ struct ieee80211_node *ni)
{
- const struct ieee80211_mira_rateset *rs, *rsnext;
+ const struct ieee80211_ht_rateset *rs, *rsnext;
int next;
+ int mcs = ni->ni_txmcs;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_mira_get_rateset(mcs);
+ rs = ieee80211_mira_get_rateset(mcs, sgi);
if (mn->probing & IEEE80211_MIRA_PROBING_UP) {
if (rs->max_mcs == 7) /* MCS 0-7 */
- next = IEEE80211_MIRA_RATESET_MIMO2;
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
+ IEEE80211_HT_RATESET_MIMO2;
else if (rs->max_mcs == 15) /* MCS 8-15 */
- next = IEEE80211_MIRA_RATESET_MIMO3;
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
+ IEEE80211_HT_RATESET_MIMO3;
else if (rs->max_mcs == 23) /* MCS 16-23 */
- next = IEEE80211_MIRA_RATESET_MIMO4;
+ next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI :
+ IEEE80211_HT_RATESET_MIMO4;
else /* MCS 24-31 */
return NULL;
} else if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {
if (rs->min_mcs == 24) /* MCS 24-31 */
- next = IEEE80211_MIRA_RATESET_MIMO3;
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
+ IEEE80211_HT_RATESET_MIMO3;
else if (rs->min_mcs == 16) /* MCS 16-23 */
- next = IEEE80211_MIRA_RATESET_MIMO2;
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
+ IEEE80211_HT_RATESET_MIMO2;
else if (rs->min_mcs == 8) /* MCS 8-15 */
- next = IEEE80211_MIRA_RATESET_SISO;
+ next = sgi ? IEEE80211_HT_RATESET_SISO_SGI :
+ IEEE80211_HT_RATESET_SISO;
else /* MCS 0-7 */
return NULL;
} else
panic("%s: invalid probing mode %d", __func__, mn->probing);
- rsnext = &ieee80211_mira_ratesets[next];
+ rsnext = &ieee80211_std_ratesets_11n[next];
if ((rsnext->mcs_mask & mn->valid_rates) == 0)
return NULL;
@@ -625,7 +602,7 @@ ieee80211_mira_next_rateset(struct ieee8
int
ieee80211_mira_best_mcs_in_rateset(struct ieee80211_mira_node *mn,
- const struct ieee80211_mira_rateset *rs)
+ const struct ieee80211_ht_rateset *rs)
{
uint64_t gmax = 0;
int i, best_mcs = rs->min_mcs;
@@ -646,14 +623,15 @@ ieee80211_mira_best_mcs_in_rateset(struc
void
ieee80211_mira_probe_next_rateset(struct ieee80211_mira_node *mn,
- struct ieee80211_node *ni, const struct ieee80211_mira_rateset *rsnext)
+ struct ieee80211_node *ni, const struct ieee80211_ht_rateset *rsnext)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
struct ieee80211_mira_goodput_stats *g;
int best_mcs, i;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
/* Find most recently measured best MCS from the current rateset. */
- rs = ieee80211_mira_get_rateset(ni->ni_txmcs);
+ rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi);
best_mcs = ieee80211_mira_best_mcs_in_rateset(mn, rs);
/* Switch to the next rateset. */
@@ -689,7 +667,7 @@ ieee80211_mira_probe_next_rateset(struct
} else if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {
#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING
mn->candidate_rates |= ieee80211_mira_mcs_below(mn,
- ni->ni_txmcs);
+ ni->ni_txmcs, sgi);
#else
mn->candidate_rates |=
(1 << ieee80211_mira_next_lower_intra_rate(mn, ni));
@@ -754,10 +732,11 @@ int
ieee80211_mira_intra_mode_ra_finished(struct ieee80211_mira_node *mn,
struct ieee80211_node *ni)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];
int next_mcs, best_mcs, probed_rates;
uint64_t next_rate;
+ int sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
if (!ieee80211_mira_probe_valid(mn, ni))
return 0;
@@ -765,7 +744,7 @@ ieee80211_mira_intra_mode_ra_finished(st
probed_rates = (mn->probed_rates | (1 << ni->ni_txmcs));
/* Check if the min/max MCS in this rateset has been probed. */
- rs = ieee80211_mira_get_rateset(ni->ni_txmcs);
+ rs = ieee80211_mira_get_rateset(ni->ni_txmcs, sgi);
if (mn->probing & IEEE80211_MIRA_PROBING_DOWN) {
if (ni->ni_txmcs == rs->min_mcs ||
probed_rates & (1 << rs->min_mcs)) {
@@ -789,7 +768,7 @@ ieee80211_mira_intra_mode_ra_finished(st
ieee80211_mira_trigger_next_rateset(mn, ni);
return 1;
}
- next_rate = ieee80211_mira_get_txrate(next_mcs);
+ next_rate = ieee80211_mira_get_txrate(next_mcs, sgi);
if (g->measured >= next_rate + IEEE80211_MIRA_RATE_THRESHOLD) {
ieee80211_mira_trigger_next_rateset(mn, ni);
return 1;
@@ -823,9 +802,9 @@ void
ieee80211_mira_trigger_next_rateset(struct ieee80211_mira_node *mn,
struct ieee80211_node *ni)
{
- const struct ieee80211_mira_rateset *rsnext;
+ const struct ieee80211_ht_rateset *rsnext;
- rsnext = ieee80211_mira_next_rateset(mn, ni->ni_txmcs);
+ rsnext = ieee80211_mira_next_rateset(mn, ni);
if (rsnext) {
ieee80211_mira_probe_next_rateset(mn, ni, rsnext);
mn->probing |= IEEE80211_MIRA_PROBING_INTER;
@@ -860,7 +839,7 @@ ieee80211_mira_best_rate(struct ieee8021
#ifdef MIRA_DEBUG
if (mn->best_mcs != best) {
DPRINTF(("MCS %d is best; MCS{Mbps|probe interval}:", best));
- for (i = 0; i < IEEE80211_MIRA_NUM_MCS; i++) {
+ for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
struct ieee80211_mira_goodput_stats *g = &mn->g[i];
if ((mn->valid_rates & (1 << i)) == 0)
continue;
@@ -1013,8 +992,7 @@ ieee80211_mira_valid_rates(struct ieee80
uint32_t valid_mcs = 0;
int i;
- for (i = 0;
- i < MIN(IEEE80211_MIRA_NUM_MCS, IEEE80211_HT_NUM_MCS); i++) {
+ for (i = 0; i < IEEE80211_HT_RATESET_NUM_MCS; i++) {
if (!isset(ni->ni_rxmcs, i))
continue;
if (!ieee80211_mira_valid_tx_mcs(ic, i))
@@ -1026,13 +1004,13 @@ ieee80211_mira_valid_rates(struct ieee80
}
uint32_t
-ieee80211_mira_mcs_below(struct ieee80211_mira_node *mn, int mcs)
+ieee80211_mira_mcs_below(struct ieee80211_mira_node *mn, int mcs, int sgi)
{
- const struct ieee80211_mira_rateset *rs;
+ const struct ieee80211_ht_rateset *rs;
uint32_t mcs_mask;
int i;
- rs = ieee80211_mira_get_rateset(mcs);
+ rs = ieee80211_mira_get_rateset(mcs, sgi);
mcs_mask = (1 << rs->min_mcs);
for (i = rs->min_mcs + 1; i < mcs; i++) {
if ((mn->valid_rates & (1 << i)) == 0)
@@ -1048,7 +1026,7 @@ ieee80211_mira_choose(struct ieee80211_m
struct ieee80211_node *ni)
{
struct ieee80211_mira_goodput_stats *g = &mn->g[ni->ni_txmcs];
- int s;
+ int s, sgi = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
s = splnet();
@@ -1112,7 +1090,7 @@ ieee80211_mira_choose(struct ieee80211_m
#ifdef MIRA_AGGRESSIVE_DOWNWARDS_PROBING
/* Allow for probing all the way down within this rateset. */
mn->candidate_rates = ieee80211_mira_mcs_below(mn,
- ni->ni_txmcs);
+ ni->ni_txmcs, sgi);
#else
/* Probe the lower candidate rate to see if it's any better. */
mn->candidate_rates =
Index: net80211/ieee80211_mira.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_mira.h,v
retrieving revision 1.3
diff -u -p -r1.3 ieee80211_mira.h
--- net80211/ieee80211_mira.h 12 Jan 2017 18:06:57 -0000 1.3
+++ net80211/ieee80211_mira.h 22 Jan 2019 13:32:49 -0000
@@ -26,9 +26,6 @@
* http://www.cs.ucla.edu/wing/publication/papers/Pefkianakis.MOBICOM10.pdf
*/
-/* The number of data rates MiRA can choose from. */
-#define IEEE80211_MIRA_NUM_RATES 32 /* XXX limited to MCS 0-31 */
-
/*
* Goodput statistics struct. Measures the effective data rate of an MCS
* index and contains data related to time-based probing to a new rate.
@@ -88,7 +85,7 @@ struct ieee80211_mira_node {
int best_mcs;
/* Goodput statistics for each MCS. */
- struct ieee80211_mira_goodput_stats g[IEEE80211_MIRA_NUM_RATES];
+ struct ieee80211_mira_goodput_stats g[IEEE80211_HT_RATESET_NUM_MCS];
};
/* Initialize rate control state. */
Index: net80211/ieee80211_node.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v
retrieving revision 1.160
diff -u -p -r1.160 ieee80211_node.c
--- net80211/ieee80211_node.c 18 Jan 2019 20:28:40 -0000 1.160
+++ net80211/ieee80211_node.c 22 Jan 2019 14:30:23 -0000
@@ -2146,7 +2146,8 @@ ieee80211_clear_htcaps(struct ieee80211_
ni->ni_txbfcaps = 0;
ni->ni_aselcaps = 0;
- ni->ni_flags &= ~IEEE80211_NODE_HT;
+ ni->ni_flags &= ~(IEEE80211_NODE_HT | IEEE80211_NODE_HT_SGI20 |
+ IEEE80211_NODE_HT_SGI40);
}
#endif
Index: net80211/ieee80211_node.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_node.h,v
retrieving revision 1.77
diff -u -p -r1.77 ieee80211_node.h
--- net80211/ieee80211_node.h 13 Aug 2018 15:19:52 -0000 1.77
+++ net80211/ieee80211_node.h 22 Jan 2019 15:22:29 -0000
@@ -51,6 +51,43 @@ extern const struct ieee80211_rateset ie
extern const struct ieee80211_rateset ieee80211_std_rateset_11b;
extern const struct ieee80211_rateset ieee80211_std_rateset_11g;
+/* Index into ieee80211_std_rateset_11n[] array. */
+#define IEEE80211_HT_RATESET_SISO 0
+#define IEEE80211_HT_RATESET_SISO_SGI 1
+#define IEEE80211_HT_RATESET_MIMO2 2
+#define IEEE80211_HT_RATESET_MIMO2_SGI 3
+#define IEEE80211_HT_RATESET_MIMO3 4
+#define IEEE80211_HT_RATESET_MIMO3_SGI 5
+#define IEEE80211_HT_RATESET_MIMO4 6
+#define IEEE80211_HT_RATESET_MIMO4_SGI 7
+#define IEEE80211_HT_NUM_RATESETS 8
+
+/* Maximum number of rates in a HT rateset. */
+#define IEEE80211_HT_RATESET_MAX_NRATES 8
+
+/* Number of MCS indices represented by struct ieee80211_ht_rateset. */
+#define IEEE80211_HT_RATESET_NUM_MCS 32
+
+struct ieee80211_ht_rateset {
+ uint32_t nrates;
+ uint32_t rates[IEEE80211_HT_RATESET_MAX_NRATES]; /* 500 kbit/s units */
+
+ /*
+ * This bitmask can only express MCS 0 - MCS 31.
+ * IEEE 802.11 defined 77 HT MCS in total but common hardware
+ * implementations tend to support MCS index 0 through 31 only.
+ */
+ uint32_t mcs_mask;
+
+ /* Range of MCS indices represented in this rateset. */
+ int min_mcs;
+ int max_mcs;
+
+ int sgi;
+};
+
+extern const struct ieee80211_ht_rateset ieee80211_std_ratesets_11n[];
+
enum ieee80211_node_state {
IEEE80211_STA_CACHE, /* cached node */
IEEE80211_STA_BSS, /* ic->ic_bss, the network we joined */
@@ -297,6 +334,8 @@ struct ieee80211_node {
#define IEEE80211_NODE_SA_QUERY 0x0800 /* SA Query in progress
*/
#define IEEE80211_NODE_SA_QUERY_FAILED 0x1000 /* last SA Query failed */
#define IEEE80211_NODE_RSN_NEW_PTK 0x2000 /* expecting a new PTK */
+#define IEEE80211_NODE_HT_SGI20 0x4000 /* SGI on 20 MHz
negotiated */
+#define IEEE80211_NODE_HT_SGI40 0x8000 /* SGI on 40 MHz
negotiated */
/* If not NULL, this function gets called when ni_refcnt hits zero. */
void (*ni_unref_cb)(struct ieee80211com *,
@@ -363,6 +402,22 @@ static inline int
ieee80211_node_supports_ht(struct ieee80211_node *ni)
{
return (ni->ni_rxmcs[0] & 0xff);
+}
+
+/* Check if the peer supports HT short guard interval (SGI) on 20 MHz. */
+static inline int
+ieee80211_node_supports_ht_sgi20(struct ieee80211_node *ni)
+{
+ return ieee80211_node_supports_ht(ni) &&
+ (ni->ni_htcaps & IEEE80211_HTCAP_SGI20);
+}
+
+/* Check if the peer supports HT short guard interval (SGI) on 40 MHz. */
+static inline int
+ieee80211_node_supports_ht_sgi40(struct ieee80211_node *ni)
+{
+ return ieee80211_node_supports_ht(ni) &&
+ (ni->ni_htcaps & IEEE80211_HTCAP_SGI40);
}
struct ieee80211com;
Index: net80211/ieee80211_proto.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_proto.c,v
retrieving revision 1.91
diff -u -p -r1.91 ieee80211_proto.c
--- net80211/ieee80211_proto.c 12 Nov 2018 16:36:54 -0000 1.91
+++ net80211/ieee80211_proto.c 22 Jan 2019 14:31:44 -0000
@@ -543,7 +543,8 @@ ieee80211_ht_negotiate(struct ieee80211c
{
int i;
- ni->ni_flags &= ~IEEE80211_NODE_HT;
+ ni->ni_flags &= ~(IEEE80211_NODE_HT | IEEE80211_NODE_HT_SGI20 |
+ IEEE80211_NODE_HT_SGI40);
/* Check if we support HT. */
if ((ic->ic_modecaps & (1 << IEEE80211_MODE_11N)) == 0)
@@ -590,6 +591,8 @@ ieee80211_ht_negotiate(struct ieee80211c
}
ni->ni_flags |= IEEE80211_NODE_HT;
+
+ /* Flags IEEE8021_NODE_HT_SGI20/40 are set by drivers if supported. */
}
void