diff options
-rw-r--r-- | sys/net80211/ieee80211_node.c | 44 | ||||
-rw-r--r-- | sys/net80211/ieee80211_node.h | 8 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 4 |
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 */ |