-/* $OpenBSD: ar5008.c,v 1.68 2021/10/03 20:19:55 kettenis Exp $ */
+/* $OpenBSD: ar5008.c,v 1.69 2021/10/11 09:01:05 stsp Exp $ */
/*-
* Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
/* Update rate control statistics. */
if ((ni->ni_flags & IEEE80211_NODE_HT) && ic->ic_fixed_mcs == -1) {
const struct ieee80211_ht_rateset *rs =
- ieee80211_ra_get_ht_rateset(bf->bf_txmcs,
+ ieee80211_ra_get_ht_rateset(bf->bf_txmcs, 0 /* chan40 */,
ieee80211_node_supports_ht_sgi20(ni));
unsigned int retries = 0, i;
int mcs = bf->bf_txmcs;
-/* $OpenBSD: if_iwm.c,v 1.374 2021/10/07 08:15:04 stsp Exp $ */
+/* $OpenBSD: if_iwm.c,v 1.375 2021/10/11 09:01:05 stsp Exp $ */
/*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
int mcs = txmcs;
const struct ieee80211_ht_rateset *rs =
ieee80211_ra_get_ht_rateset(txmcs,
- ieee80211_node_supports_ht_sgi20(ni));
+ ieee80211_node_supports_ht_chan40(ni),
+ ieee80211_ra_use_ht_sgi(ni));
unsigned int retries = 0, i;
in->lq_rate_mismatch = 0;
-/* $OpenBSD: if_iwn.c,v 1.249 2021/08/19 06:02:04 stsp Exp $ */
+/* $OpenBSD: if_iwn.c,v 1.250 2021/10/11 09:01:05 stsp Exp $ */
/*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
struct iwn_node *wn = (void *)ni;
int mcs = rate;
const struct ieee80211_ht_rateset *rs =
- ieee80211_ra_get_ht_rateset(rate,
- ieee80211_node_supports_ht_sgi20(ni));
+ ieee80211_ra_get_ht_rateset(rate, 0 /* chan40 */,
+ ieee80211_ra_use_ht_sgi(ni));
unsigned int retries = 0, i;
/*
-/* $OpenBSD: ieee80211.c,v 1.84 2020/06/08 09:09:58 stsp Exp $ */
+/* $OpenBSD: ieee80211.c,v 1.85 2021/10/11 09:01:06 stsp Exp $ */
/* $NetBSD: ieee80211.c,v 1.19 2004/06/06 05:45:29 dyoung Exp $ */
/*-
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},
+ { 8, { 13, 26, 39, 52, 78, 104, 117, 130 },
+ 0x000000ff, 0, 7, 0, 0},
/* MCS 0-7, 20MHz channel, SGI */
- { 8, { 14, 29, 43, 58, 87, 116, 130, 144 }, 0x000000ff, 0, 7, 1 },
+ { 8, { 14, 29, 43, 58, 87, 116, 130, 144 },
+ 0x000000ff, 0, 7, 0, 1 },
/* MCS 8-15, 20MHz channel, no SGI */
- { 8, { 26, 52, 78, 104, 156, 208, 234, 260 }, 0x0000ff00, 8, 15, 0 },
+ { 8, { 26, 52, 78, 104, 156, 208, 234, 260 },
+ 0x0000ff00, 8, 15, 0, 0 },
/* MCS 8-15, 20MHz channel, SGI */
- { 8, { 29, 58, 87, 116, 173, 231, 261, 289 }, 0x0000ff00, 8, 15, 1 },
+ { 8, { 29, 58, 87, 116, 173, 231, 261, 289 },
+ 0x0000ff00, 8, 15, 0, 1 },
/* MCS 16-23, 20MHz channel, no SGI */
- { 8, { 39, 78, 117, 156, 234, 312, 351, 390 }, 0x00ff0000, 16, 23, 0 },
+ { 8, { 39, 78, 117, 156, 234, 312, 351, 390 },
+ 0x00ff0000, 16, 23, 0, 0 },
/* MCS 16-23, 20MHz channel, SGI */
- { 8, { 43, 87, 130, 173, 260, 347, 390, 433 }, 0x00ff0000, 16, 23, 1 },
+ { 8, { 43, 87, 130, 173, 260, 347, 390, 433 },
+ 0x00ff0000, 16, 23, 0, 1 },
/* MCS 24-31, 20MHz channel, no SGI */
- { 8, { 52, 104, 156, 208, 312, 416, 468, 520 }, 0xff000000, 24, 31, 0 },
+ { 8, { 52, 104, 156, 208, 312, 416, 468, 520 },
+ 0xff000000, 24, 31, 0, 0 },
/* MCS 24-31, 20MHz channel, SGI */
- { 8, { 58, 116, 173, 231, 347, 462, 520, 578 }, 0xff000000, 24, 31, 1 },
+ { 8, { 58, 116, 173, 231, 347, 462, 520, 578 },
+ 0xff000000, 24, 31, 0, 1 },
+
+ /* MCS 0-7, 40MHz channel, no SGI */
+ { 8, { 27, 54, 81, 108, 162, 216, 243, 270 },
+ 0x000000ff, 0, 7, 1, 0 },
+
+ /* MCS 0-7, 40MHz channel, SGI */
+ { 8, { 30, 60, 90, 120, 180, 240, 270, 300 },
+ 0x000000ff, 0, 7, 1, 1 },
+
+ /* MCS 8-15, 40MHz channel, no SGI */
+ { 8, { 54, 108, 192, 216, 324, 432, 486, 540 },
+ 0x0000ff00, 8, 15, 1, 0 },
+
+ /* MCS 8-15, 40MHz channel, SGI */
+ { 8, { 60, 120, 180, 240, 360, 480, 540, 600 },
+ 0x0000ff00, 8, 15, 1, 1 },
+
+ /* MCS 16-23, 40MHz channel, no SGI */
+ { 8, { 81, 162, 243, 324, 486, 648, 729, 810 },
+ 0x00ff0000, 16, 23, 1, 0 },
+
+ /* MCS 16-23, 40MHz channel, SGI */
+ { 8, { 90, 180, 270, 360, 540, 720, 810, 900 },
+ 0x00ff0000, 16, 23, 1, 1 },
+
+ /* MCS 24-31, 40MHz channel, no SGI */
+ { 8, { 108, 216, 324, 432, 324, 864, 972, 1080 },
+ 0xff000000, 24, 31, 1, 0 },
+
+ /* MCS 24-31, 40MHz channel, SGI */
+ { 8, { 120, 240, 360, 480, 520, 960, 1080, 1200 },
+ 0xff000000, 24, 31, 1, 1 },
};
const struct ieee80211_vht_rateset ieee80211_std_ratesets_11ac[] = {
-/* $OpenBSD: ieee80211_node.h,v 1.88 2021/04/25 15:32:21 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.89 2021/10/11 09:01:06 stsp Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
#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
+#define IEEE80211_HT_RATESET_SISO_40 8
+#define IEEE80211_HT_RATESET_SISO_SGI40 9
+#define IEEE80211_HT_RATESET_MIMO2_40 10
+#define IEEE80211_HT_RATESET_MIMO2_SGI40 11
+#define IEEE80211_HT_RATESET_MIMO3_40 12
+#define IEEE80211_HT_RATESET_MIMO3_SGI40 13
+#define IEEE80211_HT_RATESET_MIMO4_40 14
+#define IEEE80211_HT_RATESET_MIMO4_SGI40 15
+#define IEEE80211_HT_NUM_RATESETS 16
/* Maximum number of rates in a HT rateset. */
#define IEEE80211_HT_RATESET_MAX_NRATES 8
int min_mcs;
int max_mcs;
+ int chan40;
int sgi;
};
(ni->ni_htcaps & IEEE80211_HTCAP_SGI40);
}
+/* Check if the peer can receive frames sent on a 40 MHz channel. */
+static inline int
+ieee80211_node_supports_ht_chan40(struct ieee80211_node *ni)
+{
+ return (ieee80211_node_supports_ht(ni) &&
+ (ni->ni_htcaps & IEEE80211_HTCAP_CBW20_40) &&
+ (ni->ni_htop0 & IEEE80211_HTOP0_CHW));
+}
+
struct ieee80211com;
typedef void ieee80211_iter_func(void *, struct ieee80211_node *);
-/* $OpenBSD: ieee80211_proto.c,v 1.104 2021/09/23 15:40:41 stsp Exp $ */
+/* $OpenBSD: ieee80211_proto.c,v 1.105 2021/10/11 09:01:06 stsp Exp $ */
/* $NetBSD: ieee80211_proto.c,v 1.8 2004/04/30 23:58:20 dyoung Exp $ */
/*-
ni->ni_flags |= IEEE80211_NODE_HT;
- /* Flags IEEE8021_NODE_HT_SGI20/40 are set by drivers if supported. */
+ if (ieee80211_node_supports_ht_sgi20(ni) &&
+ (ic->ic_htcaps & IEEE80211_HTCAP_SGI20))
+ ni->ni_flags |= IEEE80211_NODE_HT_SGI20;
+ if (ieee80211_node_supports_ht_sgi40(ni) &&
+ (ic->ic_htcaps & IEEE80211_HTCAP_SGI40))
+ ni->ni_flags |= IEEE80211_NODE_HT_SGI40;
}
void
-/* $OpenBSD: ieee80211_ra.c,v 1.3 2021/05/03 08:46:28 stsp Exp $ */
+/* $OpenBSD: ieee80211_ra.c,v 1.4 2021/10/11 09:01:06 stsp Exp $ */
/*
* Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>
#endif /* RA_DEBUG */
const struct ieee80211_ht_rateset *
-ieee80211_ra_get_ht_rateset(int mcs, int sgi20)
+ieee80211_ra_get_ht_rateset(int mcs, int chan40, int sgi)
{
const struct ieee80211_ht_rateset *rs;
int i;
for (i = 0; i < IEEE80211_HT_NUM_RATESETS; i++) {
rs = &ieee80211_std_ratesets_11n[i];
- if (sgi20 != rs->sgi)
- continue;
- if (mcs >= rs->min_mcs && mcs <= rs->max_mcs)
+ if (chan40 == rs->chan40 && sgi == rs->sgi &&
+ mcs >= rs->min_mcs && mcs <= rs->max_mcs)
return rs;
}
panic("MCS %d is not part of any rateset", mcs);
}
+int
+ieee80211_ra_use_ht_sgi(struct ieee80211_node *ni)
+{
+ if ((ni->ni_chan->ic_flags & IEEE80211_CHAN_40MHZ) &&
+ ieee80211_node_supports_ht_chan40(ni)) {
+ if (ni->ni_flags & IEEE80211_NODE_HT_SGI40)
+ return 1;
+ } else if (ni->ni_flags & IEEE80211_NODE_HT_SGI20)
+ return 1;
+
+ return 0;
+}
+
/*
* Update goodput statistics.
*/
uint64_t
-ieee80211_ra_get_txrate(int mcs, int sgi20)
+ieee80211_ra_get_txrate(int mcs, int chan40, int sgi)
{
const struct ieee80211_ht_rateset *rs;
uint64_t txrate;
- rs = ieee80211_ra_get_ht_rateset(mcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(mcs, chan40, sgi);
txrate = rs->rates[mcs - rs->min_mcs];
txrate <<= RA_FP_SHIFT; /* convert to fixed-point */
txrate *= 500; /* convert to kbit/s */
{
const struct ieee80211_ht_rateset *rs;
int i, next;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
+ ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
if (ni->ni_txmcs == rs->min_mcs)
return rs->min_mcs;
{
const struct ieee80211_ht_rateset *rs;
int i, next;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
+ ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
if (ni->ni_txmcs == rs->max_mcs)
return rs->max_mcs;
{
const struct ieee80211_ht_rateset *rs, *rsnext;
int next;
+ int chan40 = ieee80211_node_supports_ht_chan40(ni);
+ int sgi = ieee80211_ra_use_ht_sgi(ni);
int mcs = ni->ni_txmcs;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rs = ieee80211_ra_get_ht_rateset(mcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(mcs, chan40, sgi);
if (rn->probing & IEEE80211_RA_PROBING_UP) {
- if (rs->max_mcs == 7) /* MCS 0-7 */
- next = sgi20 ? IEEE80211_HT_RATESET_MIMO2_SGI :
- IEEE80211_HT_RATESET_MIMO2;
- else if (rs->max_mcs == 15) /* MCS 8-15 */
- next = sgi20 ? IEEE80211_HT_RATESET_MIMO3_SGI :
- IEEE80211_HT_RATESET_MIMO3;
- else if (rs->max_mcs == 23) /* MCS 16-23 */
- next = sgi20 ? IEEE80211_HT_RATESET_MIMO4_SGI :
- IEEE80211_HT_RATESET_MIMO4;
- else /* MCS 24-31 */
+ if (rs->max_mcs == 7) { /* MCS 0-7 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI40 :
+ IEEE80211_HT_RATESET_MIMO2_40;
+ else
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
+ IEEE80211_HT_RATESET_MIMO2;
+ } else if (rs->max_mcs == 15) { /* MCS 8-15 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI40 :
+ IEEE80211_HT_RATESET_MIMO3_40;
+ else
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
+ IEEE80211_HT_RATESET_MIMO3;
+ } else if (rs->max_mcs == 23) { /* MCS 16-23 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI40 :
+ IEEE80211_HT_RATESET_MIMO4_40;
+ else
+ next = sgi ? IEEE80211_HT_RATESET_MIMO4_SGI :
+ IEEE80211_HT_RATESET_MIMO4;
+ } else /* MCS 24-31 */
return NULL;
} else if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
- if (rs->min_mcs == 24) /* MCS 24-31 */
- next = sgi20 ? IEEE80211_HT_RATESET_MIMO3_SGI :
- IEEE80211_HT_RATESET_MIMO3;
- else if (rs->min_mcs == 16) /* MCS 16-23 */
- next = sgi20 ? IEEE80211_HT_RATESET_MIMO2_SGI :
- IEEE80211_HT_RATESET_MIMO2;
- else if (rs->min_mcs == 8) /* MCS 8-15 */
- next = sgi20 ? IEEE80211_HT_RATESET_SISO_SGI :
- IEEE80211_HT_RATESET_SISO;
- else /* MCS 0-7 */
+ if (rs->min_mcs == 24) { /* MCS 24-31 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI40 :
+ IEEE80211_HT_RATESET_MIMO3_40;
+ else
+ next = sgi ? IEEE80211_HT_RATESET_MIMO3_SGI :
+ IEEE80211_HT_RATESET_MIMO3;
+ } else if (rs->min_mcs == 16) { /* MCS 16-23 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI40 :
+ IEEE80211_HT_RATESET_MIMO2_40;
+ else
+ next = sgi ? IEEE80211_HT_RATESET_MIMO2_SGI :
+ IEEE80211_HT_RATESET_MIMO2;
+ } else if (rs->min_mcs == 8) { /* MCS 8-15 */
+ if (chan40)
+ next = sgi ? IEEE80211_HT_RATESET_SISO_SGI40 :
+ IEEE80211_HT_RATESET_SISO_40;
+ else
+ 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__, rn->probing);
const struct ieee80211_ht_rateset *rs;
struct ieee80211_ra_goodput_stats *g;
int best_mcs, i;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
/* Find most recently measured best MCS from the current rateset. */
- rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs,
+ ieee80211_node_supports_ht_chan40(ni), ieee80211_ra_use_ht_sgi(ni));
best_mcs = ieee80211_ra_best_mcs_in_rateset(rn, rs);
/* Switch to the next rateset. */
struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
int next_mcs, best_mcs;
uint64_t next_rate;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
+ int chan40 = ieee80211_node_supports_ht_chan40(ni);
+ int sgi = ieee80211_ra_use_ht_sgi(ni);
rn->probed_rates = (rn->probed_rates | (1 << ni->ni_txmcs));
/* Check if the min/max MCS in this rateset has been probed. */
- rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, chan40, sgi);
if (rn->probing & IEEE80211_RA_PROBING_DOWN) {
if (ni->ni_txmcs == rs->min_mcs ||
rn->probed_rates & (1 << rs->min_mcs)) {
ieee80211_ra_trigger_next_rateset(rn, ni);
return 1;
}
- next_rate = ieee80211_ra_get_txrate(next_mcs, sgi20);
+ next_rate = ieee80211_ra_get_txrate(next_mcs, chan40, sgi);
if (g->loss == 0 &&
g->measured >= next_rate + IEEE80211_RA_RATE_THRESHOLD) {
ieee80211_ra_trigger_next_rateset(rn, ni);
{
static const uint64_t alpha = RA_FP_1 / 8; /* 1/8 = 0.125 */
static const uint64_t beta = RA_FP_1 / 4; /* 1/4 = 0.25 */
- int s, sgi20;
+ int s;
struct ieee80211_ra_goodput_stats *g;
uint64_t sfer, rate, delta;
g->nprobe_fail = 0;
g->nprobe_pkts = 0;
- sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
- rate = ieee80211_ra_get_txrate(mcs, sgi20);
+ rate = ieee80211_ra_get_txrate(mcs,
+ ieee80211_node_supports_ht_chan40(ni),
+ ieee80211_ra_use_ht_sgi(ni));
g->loss = sfer * 100;
g->measured = RA_FP_MUL(RA_FP_1 - sfer, rate);
{
struct ieee80211_ra_goodput_stats *g = &rn->g[ni->ni_txmcs];
int s;
- int sgi20 = (ni->ni_flags & IEEE80211_NODE_HT_SGI20) ? 1 : 0;
+ int chan40 = ieee80211_node_supports_ht_chan40(ni);
+ int sgi = ieee80211_ra_use_ht_sgi(ni);
const struct ieee80211_ht_rateset *rs, *rsnext;
s = splnet();
rn->valid_probes = 0;
}
- rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, sgi20);
+ rs = ieee80211_ra_get_ht_rateset(ni->ni_txmcs, chan40, sgi);
if ((g->measured >> RA_FP_SHIFT) == 0LL ||
(g->average >= 3 * g->stddeviation &&
g->measured < g->average - 3 * g->stddeviation)) {
-/* $OpenBSD: ieee80211_ra.h,v 1.1 2021/03/12 16:26:27 stsp Exp $ */
+/* $OpenBSD: ieee80211_ra.h,v 1.2 2021/10/11 09:01:06 stsp Exp $ */
/*
* Copyright (c) 2021 Christian Ehrhardt <ehrhardt@genua.de>
void ieee80211_ra_choose(struct ieee80211_ra_node *,
struct ieee80211com *, struct ieee80211_node *);
-/* Get the HT rateset for a particular HT MCS with SGI20 on/off. */
+/* Get the HT rateset for a particular HT MCS with 40MHz and/or SGI on/off. */
const struct ieee80211_ht_rateset * ieee80211_ra_get_ht_rateset(int mcs,
- int sgi20);
+ int chan40, int sgi);
+
+/* Check whether SGI should be used. */
+int ieee80211_ra_use_ht_sgi(struct ieee80211_node *);
-/* $OpenBSD: ieee80211_var.h,v 1.105 2021/09/23 15:13:47 stsp Exp $ */
+/* $OpenBSD: ieee80211_var.h,v 1.106 2021/10/11 09:01:06 stsp Exp $ */
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
/*-
#define IEEE80211_CHAN_XR 0x1000 /* Extended range OFDM channel */
#define IEEE80211_CHAN_HT 0x2000 /* 11n/HT channel */
#define IEEE80211_CHAN_VHT 0x4000 /* 11ac/VHT channel */
+#define IEEE80211_CHAN_40MHZ 0x8000 /* use of 40 MHz is allowed */
/*
* Useful combinations of channel characteristics.