This diff cannot be tested yet -- I'm looking for OKs only :-) Manage the HT protection setting if acting as hostap with 11n enabled.
For now we flip-flop only between non-member protection and non-HT protection. Running a HT network without protection would require monitoring environmental conditions (e.g. foreign beacons) which make HT protection necessary. The ic_update_htprot driver function becomes optional because it won't be needed by all drivers. Only call it if the driver has set a function pointer. Index: ieee80211_input.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v retrieving revision 1.180 diff -u -p -r1.180 ieee80211_input.c --- ieee80211_input.c 21 Sep 2016 12:21:27 -0000 1.180 +++ ieee80211_input.c 9 Jan 2017 10:07:34 -0000 @@ -1612,7 +1612,8 @@ ieee80211_recv_probe_resp(struct ieee802 htprot_last, htprot)); ic->ic_stats.is_ht_prot_change++; ic->ic_bss->ni_htop1 = ni->ni_htop1; - ic->ic_update_htprot(ic, ic->ic_bss); + if (ic->ic_update_htprot) + ic->ic_update_htprot(ic, ic->ic_bss); } } Index: ieee80211_node.c =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_node.c,v retrieving revision 1.108 diff -u -p -r1.108 ieee80211_node.c --- ieee80211_node.c 9 Jan 2017 09:31:18 -0000 1.108 +++ ieee80211_node.c 9 Jan 2017 10:07:57 -0000 @@ -353,6 +353,16 @@ ieee80211_create_ibss(struct ieee80211co ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; if (ic->ic_flags & IEEE80211_F_WEPON) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; + if (ic->ic_flags & IEEE80211_F_HTON) { + /* + * Default to non-member HT protection until we have a way + * of picking up information from the environment (such as + * beacons from other networks) which proves that only HT + * STAs are on the air. + */ + ni->ni_htop1 = IEEE80211_HTPROT_NONMEMBER; + ic->ic_protmode = IEEE80211_PROT_RTSCTS; + } if (ic->ic_flags & IEEE80211_F_RSNON) { struct ieee80211_key *k; @@ -1423,7 +1433,15 @@ ieee80211_needs_auth(struct ieee80211com void ieee80211_node_join_ht(struct ieee80211com *ic, struct ieee80211_node *ni) { - /* TBD */ + enum ieee80211_htprot; + + /* Update HT protection setting. */ + if ((ni->ni_flags & IEEE80211_NODE_HT) == 0) { + ic->ic_nonhtsta++; + ic->ic_bss->ni_htop1 = IEEE80211_HTPROT_NONHT_MIXED; + if (ic->ic_update_htprot) + ic->ic_update_htprot(ic, ic->ic_bss); + } } /* @@ -1712,6 +1730,16 @@ ieee80211_node_leave(struct ieee80211com if (ni->ni_flags & IEEE80211_NODE_HT) ieee80211_node_leave_ht(ic, ni); + else if (ic->ic_flags & IEEE80211_F_HTON) { + if (ic->ic_nonhtsta == 0) + panic("bogus non-HT station count %d", ic->ic_nonhtsta); + if (--ic->ic_nonhtsta == 0) { + /* All associated stations now support HT. */ + ic->ic_bss->ni_htop1 = IEEE80211_HTPROT_NONMEMBER; + if (ic->ic_update_htprot) + ic->ic_update_htprot(ic, ic->ic_bss); + } + } if (ic->ic_node_leave != NULL) (*ic->ic_node_leave)(ic, ni); Index: ieee80211_var.h =================================================================== RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v retrieving revision 1.73 diff -u -p -r1.73 ieee80211_var.h --- ieee80211_var.h 17 Dec 2016 18:35:54 -0000 1.73 +++ ieee80211_var.h 8 Jan 2017 21:11:30 -0000 @@ -310,6 +310,9 @@ struct ieee80211com { u_int ic_dtim_period; u_int ic_dtim_count; +#ifndef IEEE80211_STA_ONLY + u_int16_t ic_nonhtsta; /* # non-HT stations */ +#endif u_int32_t ic_txbfcaps; u_int16_t ic_htcaps; u_int8_t ic_ampdu_params;