diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-03-01 08:13:12 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-03-01 08:13:12 +0000 |
commit | e826a25aebe3aae1673a3788255fc95d4b8e40a0 (patch) | |
tree | b9956430965d7eb43ec68b230e44f70287cb6e55 | |
parent | aa21243eb375f73fd9bb774b507b89fe1991c1c9 (diff) |
Improve handling of HT protection for 'mode 11n' hostap.
Consider the mere presence of HTCAP IEs as indicator of 11n support,
rather than checking advertised Rx MCS. Fixes some devices being
misclassified as 11a/g, causing HT protection to be enabled even
though it is not needed.
Use CTS-to-self frames for HT protection instead of RTS/CTS.
These changes make my athn(4) AR9280 hostap perform much better.
ok phessler@
-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 */ |