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?
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 14:33:03 -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,10 @@ 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 (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 14:50:50 -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