summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net80211/ieee80211_node.c44
-rw-r--r--sys/net80211/ieee80211_node.h8
-rw-r--r--sys/net80211/ieee80211_var.h4
3 files changed, 39 insertions, 17 deletions
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index d6794f3c981..a7dfefce36c 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.c,v 1.161 2019/01/23 10:08:49 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.c,v 1.162 2019/03/01 08:13:11 stsp Exp $ */
/* $NetBSD: ieee80211_node.c,v 1.14 2004/05/09 09:18:47 dyoung Exp $ */
/*-
@@ -894,11 +894,15 @@ ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
int aci;
/*
- * Default to non-member HT protection. This will be updated
- * later based on the number of non-HT nodes in the node cache.
+ * Configure HT protection. This will be updated later
+ * based on the number of non-HT nodes in the node cache.
*/
- ni->ni_htop1 = IEEE80211_HTPROT_NONMEMBER;
- ic->ic_protmode = IEEE80211_PROT_RTSCTS;
+ ic->ic_protmode = IEEE80211_PROT_NONE;
+ ni->ni_htop1 = IEEE80211_HTPROT_NONE;
+ /* Disallow Greenfield mode. None of our drivers support it. */
+ ni->ni_htop1 |= IEEE80211_HTOP1_NONGF_STA;
+ if (ic->ic_update_htprot)
+ ic->ic_update_htprot(ic, ni);
/* Configure QoS EDCA parameters. */
for (aci = 0; aci < EDCA_NUM_AC; aci++) {
@@ -1985,7 +1989,14 @@ ieee80211_clean_nodes(struct ieee80211com *ic, int cache_timeout)
#ifndef IEEE80211_STA_ONLY
nnodes++;
if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {
- if (!ieee80211_node_supports_ht(ni)) {
+ /*
+ * Check if node supports 802.11n.
+ * Only require HT capabilities IE for this check.
+ * Nodes might never reveal their supported MCS to us
+ * unless they go through a full association sequence.
+ * ieee80211_node_supports_ht() could misclassify them.
+ */
+ if ((ni->ni_flags & IEEE80211_NODE_HTCAP) == 0) {
nonht++;
if (ni->ni_state == IEEE80211_STA_ASSOC)
nonhtassoc++;
@@ -2031,7 +2042,7 @@ ieee80211_clean_nodes(struct ieee80211com *ic, int cache_timeout)
#ifndef IEEE80211_STA_ONLY
nnodes--;
if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {
- if (!ieee80211_node_supports_ht(ni)) {
+ if ((ni->ni_flags & IEEE80211_NODE_HTCAP) == 0) {
nonht--;
if (ni->ni_state == IEEE80211_STA_ASSOC)
nonhtassoc--;
@@ -2052,16 +2063,20 @@ ieee80211_clean_nodes(struct ieee80211com *ic, int cache_timeout)
#ifndef IEEE80211_STA_ONLY
if ((ic->ic_flags & IEEE80211_F_HTON) && cache_timeout) {
+ uint16_t htop1 = ic->ic_bss->ni_htop1;
+
/* Update HT protection settings. */
if (nonht) {
- protmode = IEEE80211_PROT_RTSCTS;
+ protmode = IEEE80211_PROT_CTSONLY;
if (nonhtassoc)
htprot = IEEE80211_HTPROT_NONHT_MIXED;
else
htprot = IEEE80211_HTPROT_NONMEMBER;
}
- if (ic->ic_bss->ni_htop1 != htprot) {
- ic->ic_bss->ni_htop1 = htprot;
+ if ((htop1 & IEEE80211_HTOP1_PROT_MASK) != htprot) {
+ htop1 &= ~IEEE80211_HTOP1_PROT_MASK;
+ htop1 |= htprot;
+ ic->ic_bss->ni_htop1 |= htop1;
ic->ic_protmode = protmode;
if (ic->ic_update_htprot)
ic->ic_update_htprot(ic, ic->ic_bss);
@@ -2128,6 +2143,8 @@ ieee80211_setup_htcaps(struct ieee80211_node *ni, const uint8_t *data,
ni->ni_txbfcaps = (data[21] | (data[22] << 8) | (data[23] << 16) |
(data[24] << 24));
ni->ni_aselcaps = data[25];
+
+ ni->ni_flags |= IEEE80211_NODE_HTCAP;
}
#ifndef IEEE80211_STA_ONLY
@@ -2147,7 +2164,7 @@ ieee80211_clear_htcaps(struct ieee80211_node *ni)
ni->ni_aselcaps = 0;
ni->ni_flags &= ~(IEEE80211_NODE_HT | IEEE80211_NODE_HT_SGI20 |
- IEEE80211_NODE_HT_SGI40);
+ IEEE80211_NODE_HT_SGI40 | IEEE80211_NODE_HTCAP);
}
#endif
@@ -2262,7 +2279,10 @@ ieee80211_node_join_ht(struct ieee80211com *ic, struct ieee80211_node *ni)
/* Update HT protection setting. */
if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) {
- ic->ic_bss->ni_htop1 = IEEE80211_HTPROT_NONHT_MIXED;
+ uint16_t htop1 = ic->ic_bss->ni_htop1;
+ htop1 &= ~IEEE80211_HTOP1_PROT_MASK;
+ htop1 |= IEEE80211_HTPROT_NONHT_MIXED;
+ ic->ic_bss->ni_htop1 = htop1;
if (ic->ic_update_htprot)
ic->ic_update_htprot(ic, ic->ic_bss);
}
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index a012f6cb745..0b891938db0 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_node.h,v 1.79 2019/02/19 08:12:30 stsp Exp $ */
+/* $OpenBSD: ieee80211_node.h,v 1.80 2019/03/01 08:13:11 stsp Exp $ */
/* $NetBSD: ieee80211_node.h,v 1.9 2004/04/30 22:57:32 dyoung Exp $ */
/*-
@@ -368,6 +368,7 @@ struct ieee80211_node {
#define IEEE80211_NODE_HT_SGI20 0x4000 /* SGI on 20 MHz negotiated */
#define IEEE80211_NODE_HT_SGI40 0x8000 /* SGI on 40 MHz negotiated */
#define IEEE80211_NODE_VHT 0x10000 /* VHT negotiated */
+#define IEEE80211_NODE_HTCAP 0x20000 /* claims to support HT */
/* If not NULL, this function gets called when ni_refcnt hits zero. */
void (*ni_unref_cb)(struct ieee80211com *,
@@ -427,13 +428,14 @@ ieee80211_unref_node(struct ieee80211_node **ni)
/*
* Check if the peer supports HT.
- * Require at least one of the mandatory MCS.
+ * Require a HT capabilities IE and at least one of the mandatory MCS.
* MCS 0-7 are mandatory but some APs have particular MCS disabled.
*/
static inline int
ieee80211_node_supports_ht(struct ieee80211_node *ni)
{
- return (ni->ni_rxmcs[0] & 0xff);
+ return ((ni->ni_flags & IEEE80211_NODE_HTCAP) &&
+ ni->ni_rxmcs[0] & 0xff);
}
/* Check if the peer supports HT short guard interval (SGI) on 20 MHz. */
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index a18fa240524..eaf7649c4db 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ieee80211_var.h,v 1.94 2019/02/19 08:12:30 stsp Exp $ */
+/* $OpenBSD: ieee80211_var.h,v 1.95 2019/03/01 08:13:11 stsp Exp $ */
/* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */
/*-
@@ -255,7 +255,7 @@ struct ieee80211com {
enum ieee80211_state ic_state; /* 802.11 state */
u_int32_t *ic_aid_bitmap;
u_int16_t ic_max_aid;
- enum ieee80211_protmode ic_protmode; /* 802.11g protection mode */
+ enum ieee80211_protmode ic_protmode; /* 802.11g/n protection mode */
struct ifmedia ic_media; /* interface media config */
caddr_t ic_rawbpf; /* packet filter structure */
struct ieee80211_node *ic_bss; /* information for this node */