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;