Stefan Sperling
2016-01-20 21:04:11 UTC
This diff makes us keep track of changes in the network's HT protection
settings. These settings are advertised in beacons and change dynamically
based on the nature of clients associated to an AP at a given moment.
Tracking these changes is rather important.
If a non-11n client associates to an AP which previously had 11n clients
only, we must update our wireless device's configuration accordingly or
the new client might damage frames we send out.
Index: dev/pci/if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.75
diff -u -p -r1.75 if_iwm.c
--- dev/pci/if_iwm.c 7 Jan 2016 23:08:38 -0000 1.75
+++ dev/pci/if_iwm.c 20 Jan 2016 20:42:23 -0000
@@ -294,6 +294,8 @@ int iwm_nvm_read_section(struct iwm_soft
uint16_t *);
void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const);
void iwm_setup_ht_rates(struct iwm_softc *);
+void iwm_htprot_task(void *);
+void iwm_update_htprot(struct ieee80211com *, const struct ieee80211_node *);
int iwm_ampdu_rx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
void iwm_ampdu_rx_stop(struct ieee80211com *,
@@ -2602,6 +2604,34 @@ iwm_mvm_sta_rx_agg(struct iwm_softc *sc,
}
void
+iwm_htprot_task(void *arg)
+{
+ struct iwm_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct iwm_node *in = (void *)ic->ic_bss;
+ int error;
+
+ /* This call updates HT protection based on in->in_ni.ni_htop1. */
+ error = iwm_mvm_mac_ctxt_changed(sc, in);
+ if (error != 0)
+ printf("%s: could not change HT protection: error %d\n",
+ DEVNAME(sc), error);
+}
+
+/*
+ * This function is called by upper layer when HT protection settings in
+ * beacons have changed.
+ */
+void
+iwm_update_htprot(struct ieee80211com *ic, const struct ieee80211_node *ni)
+{
+ struct iwm_softc *sc = ic->ic_softc;
+
+ /* assumes that ni == ic->ic_bss */
+ task_add(systq, &sc->htprot_task);
+}
+
+void
iwm_ba_task(void *arg)
{
struct iwm_softc *sc = arg;
@@ -5878,6 +5908,7 @@ iwm_stop(struct ifnet *ifp, int disable)
task_del(sc->sc_eswq, &sc->sc_eswk);
task_del(systq, &sc->setrates_task);
task_del(systq, &sc->ba_task);
+ task_del(systq, &sc->htprot_task);
sc->sc_newstate(ic, IEEE80211_S_INIT, -1);
@@ -6586,6 +6617,7 @@ iwm_preinit(struct iwm_softc *sc)
/* Override 802.11 state transition machine. */
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = iwm_newstate;
+ ic->ic_update_htprot = iwm_update_htprot;
ic->ic_ampdu_rx_start = iwm_ampdu_rx_start;
ic->ic_ampdu_rx_stop = iwm_ampdu_rx_stop;
#ifdef notyet
@@ -6822,6 +6854,7 @@ iwm_attach(struct device *parent, struct
task_set(&sc->newstate_task, iwm_newstate_task, sc);
task_set(&sc->setrates_task, iwm_setrates_task, sc);
task_set(&sc->ba_task, iwm_ba_task, sc);
+ task_set(&sc->htprot_task, iwm_htprot_task, sc);
/*
* We cannot read the MAC address without loading the
Index: dev/pci/if_iwmvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.15
diff -u -p -r1.15 if_iwmvar.h
--- dev/pci/if_iwmvar.h 5 Jan 2016 18:41:15 -0000 1.15
+++ dev/pci/if_iwmvar.h 20 Jan 2016 17:37:06 -0000
@@ -376,6 +376,9 @@ struct iwm_softc {
int ba_tid;
uint16_t ba_ssn;
+ /* Task for HT protection updates. */
+ struct task htprot_task;
+
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_size_t sc_sz;
Index: dev/pci/if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.157
diff -u -p -r1.157 if_iwn.c
--- dev/pci/if_iwn.c 13 Jan 2016 14:39:35 -0000 1.157
+++ dev/pci/if_iwn.c 20 Jan 2016 20:45:40 -0000
@@ -226,6 +226,8 @@ int iwn_set_key(struct ieee80211com *,
struct ieee80211_key *);
void iwn_delete_key(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_key *);
+void iwn_update_htprot(struct ieee80211com *,
+ const struct ieee80211_node *);
int iwn_ampdu_rx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
void iwn_ampdu_rx_stop(struct ieee80211com *,
@@ -515,6 +517,7 @@ iwn_attach(struct device *parent, struct
ic->ic_updateedca = iwn_updateedca;
ic->ic_set_key = iwn_set_key;
ic->ic_delete_key = iwn_delete_key;
+ ic->ic_update_htprot = iwn_update_htprot;
ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
#ifdef notyet
@@ -5009,6 +5012,44 @@ iwn_delete_key(struct ieee80211com *ic,
node.kid = 0xff;
DPRINTF(("delete keys for node %d\n", node.id));
(void)ops->add_node(sc, &node, 1);
+}
+
+/*
+ * This function is called by upper layer when HT protection settings in
+ * beacons have changed.
+ */
+void
+iwn_update_htprot(struct ieee80211com *ic, const struct ieee80211_node *ni)
+{
+ struct iwn_softc *sc = ic->ic_softc;
+ struct iwn_rxon_assoc cmd;
+ enum ieee80211_htprot htprot;
+ int error;
+
+ memset(&cmd, 0, sizeof cmd);
+
+ /* Copy settings from RXON configuration. */
+ cmd.flags = sc->rxon.flags;
+ cmd.filter = sc->rxon.filter;
+ cmd.cck_mask = sc->rxon.cck_mask;
+ cmd.ofdm_mask = sc->rxon.ofdm_mask;
+ cmd.ht_single_mask = sc->rxon.ht_single_mask;
+ cmd.ht_dual_mask = sc->rxon.ht_dual_mask;
+ cmd.ht_triple_mask = sc->rxon.ht_triple_mask;
+ cmd.rxchain = sc->rxon.rxchain;
+ cmd.acquisition = sc->rxon.acquisition;
+
+ /* Update HT protection setting. */
+ htprot = ((ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
+ IEEE80211_HTOP1_PROT_SHIFT);
+ cmd.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3));
+ cmd.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot));
+
+ /* Use the RXON_ASSOC command since we're already associated. */
+ error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof cmd, 1);
+ if (error != 0)
+ printf("%s: could not change HT protection: error %d\n",
+ sc->sc_dev.dv_xname, error);
}
/*
Index: dev/pci/if_iwnreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.51
diff -u -p -r1.51 if_iwnreg.h
--- dev/pci/if_iwnreg.h 7 Jan 2016 23:08:38 -0000 1.51
+++ dev/pci/if_iwnreg.h 20 Jan 2016 20:09:13 -0000
@@ -529,6 +529,22 @@ struct iwn_rxon {
#define IWN4965_RXONSZ (sizeof (struct iwn_rxon) - 6)
#define IWN5000_RXONSZ (sizeof (struct iwn_rxon))
+/* Structure for command IWN_CMD_RXON_ASSOC. */
+struct iwn_rxon_assoc {
+ uint32_t flags;
+ uint32_t filter;
+ uint8_t cck_mask;
+ uint8_t ofdm_mask;
+ uint16_t reserved1;
+ uint8_t ht_single_mask;
+ uint8_t ht_dual_mask;
+ uint8_t ht_triple_mask;
+ uint8_t reserved2;
+ uint16_t rxchain;
+ uint16_t acquisition;
+ uint32_t reserved3;
+} __packed;
+
/* Structure for command IWN_CMD_ASSOCIATE. */
struct iwn_assoc {
uint32_t flags;
Index: net80211/ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.151
diff -u -p -r1.151 ieee80211_input.c
--- net80211/ieee80211_input.c 7 Jan 2016 23:22:31 -0000 1.151
+++ net80211/ieee80211_input.c 20 Jan 2016 20:52:08 -0000
@@ -1577,10 +1577,14 @@ ieee80211_recv_probe_resp(struct ieee802
} else
is_new = 0;
+ if (htcaps)
+ ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
+ if (htop)
+ ieee80211_setup_htop(ni, htop + 2, htop[1]);
+
/*
* When operating in station mode, check for state updates
- * while we're associated. We consider only 11g stuff right
- * now.
+ * while we're associated.
*/
if (ic->ic_opmode == IEEE80211_M_STA &&
ic->ic_state == IEEE80211_S_RUN &&
@@ -1599,6 +1603,22 @@ ieee80211_recv_probe_resp(struct ieee802
ic->ic_flags &= ~IEEE80211_F_USEPROT;
ic->ic_bss->ni_erp = erp;
}
+ if (ic->ic_bss->ni_flags & IEEE80211_NODE_HT) {
+ enum ieee80211_htprot htprot_last, htprot;
+ htprot_last =
+ ((ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK)
+ >> IEEE80211_HTOP1_PROT_SHIFT);
+ htprot = ((ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
+ IEEE80211_HTOP1_PROT_SHIFT);
+ if (htprot_last != htprot) {
+ DPRINTF(("[%s] htprot change: was %d, now %d\n",
+ ether_sprintf((u_int8_t *)wh->i_addr2),
+ htprot_last, htprot));
+ ic->ic_bss->ni_htop1 = ni->ni_htop1;
+ ic->ic_update_htprot(ic, ic->ic_bss);
+ }
+ }
+
/*
* Check if AP short slot time setting has changed
* since last beacon and give the driver a chance to
@@ -1679,10 +1699,6 @@ ieee80211_recv_probe_resp(struct ieee802
ni->ni_erp = erp;
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
- if (htcaps)
- ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
- if (htop)
- ieee80211_setup_htop(ni, htop + 2, htop[1]);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_IBSS && is_new && isprobe) {
/*
Index: net80211/ieee80211_var.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.70
diff -u -p -r1.70 ieee80211_var.h
--- net80211/ieee80211_var.h 12 Jan 2016 09:28:09 -0000 1.70
+++ net80211/ieee80211_var.h 20 Jan 2016 19:18:40 -0000
@@ -213,6 +213,8 @@ struct ieee80211com {
struct ieee80211_node *, u_int8_t);
void (*ic_ampdu_rx_stop)(struct ieee80211com *,
struct ieee80211_node *, u_int8_t);
+ void (*ic_update_htprot)(struct ieee80211com *,
+ const struct ieee80211_node *);
u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];
struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
settings. These settings are advertised in beacons and change dynamically
based on the nature of clients associated to an AP at a given moment.
Tracking these changes is rather important.
If a non-11n client associates to an AP which previously had 11n clients
only, we must update our wireless device's configuration accordingly or
the new client might damage frames we send out.
Index: dev/pci/if_iwm.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
retrieving revision 1.75
diff -u -p -r1.75 if_iwm.c
--- dev/pci/if_iwm.c 7 Jan 2016 23:08:38 -0000 1.75
+++ dev/pci/if_iwm.c 20 Jan 2016 20:42:23 -0000
@@ -294,6 +294,8 @@ int iwm_nvm_read_section(struct iwm_soft
uint16_t *);
void iwm_init_channel_map(struct iwm_softc *, const uint16_t * const);
void iwm_setup_ht_rates(struct iwm_softc *);
+void iwm_htprot_task(void *);
+void iwm_update_htprot(struct ieee80211com *, const struct ieee80211_node *);
int iwm_ampdu_rx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
void iwm_ampdu_rx_stop(struct ieee80211com *,
@@ -2602,6 +2604,34 @@ iwm_mvm_sta_rx_agg(struct iwm_softc *sc,
}
void
+iwm_htprot_task(void *arg)
+{
+ struct iwm_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct iwm_node *in = (void *)ic->ic_bss;
+ int error;
+
+ /* This call updates HT protection based on in->in_ni.ni_htop1. */
+ error = iwm_mvm_mac_ctxt_changed(sc, in);
+ if (error != 0)
+ printf("%s: could not change HT protection: error %d\n",
+ DEVNAME(sc), error);
+}
+
+/*
+ * This function is called by upper layer when HT protection settings in
+ * beacons have changed.
+ */
+void
+iwm_update_htprot(struct ieee80211com *ic, const struct ieee80211_node *ni)
+{
+ struct iwm_softc *sc = ic->ic_softc;
+
+ /* assumes that ni == ic->ic_bss */
+ task_add(systq, &sc->htprot_task);
+}
+
+void
iwm_ba_task(void *arg)
{
struct iwm_softc *sc = arg;
@@ -5878,6 +5908,7 @@ iwm_stop(struct ifnet *ifp, int disable)
task_del(sc->sc_eswq, &sc->sc_eswk);
task_del(systq, &sc->setrates_task);
task_del(systq, &sc->ba_task);
+ task_del(systq, &sc->htprot_task);
sc->sc_newstate(ic, IEEE80211_S_INIT, -1);
@@ -6586,6 +6617,7 @@ iwm_preinit(struct iwm_softc *sc)
/* Override 802.11 state transition machine. */
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = iwm_newstate;
+ ic->ic_update_htprot = iwm_update_htprot;
ic->ic_ampdu_rx_start = iwm_ampdu_rx_start;
ic->ic_ampdu_rx_stop = iwm_ampdu_rx_stop;
#ifdef notyet
@@ -6822,6 +6854,7 @@ iwm_attach(struct device *parent, struct
task_set(&sc->newstate_task, iwm_newstate_task, sc);
task_set(&sc->setrates_task, iwm_setrates_task, sc);
task_set(&sc->ba_task, iwm_ba_task, sc);
+ task_set(&sc->htprot_task, iwm_htprot_task, sc);
/*
* We cannot read the MAC address without loading the
Index: dev/pci/if_iwmvar.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwmvar.h,v
retrieving revision 1.15
diff -u -p -r1.15 if_iwmvar.h
--- dev/pci/if_iwmvar.h 5 Jan 2016 18:41:15 -0000 1.15
+++ dev/pci/if_iwmvar.h 20 Jan 2016 17:37:06 -0000
@@ -376,6 +376,9 @@ struct iwm_softc {
int ba_tid;
uint16_t ba_ssn;
+ /* Task for HT protection updates. */
+ struct task htprot_task;
+
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
bus_size_t sc_sz;
Index: dev/pci/if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.157
diff -u -p -r1.157 if_iwn.c
--- dev/pci/if_iwn.c 13 Jan 2016 14:39:35 -0000 1.157
+++ dev/pci/if_iwn.c 20 Jan 2016 20:45:40 -0000
@@ -226,6 +226,8 @@ int iwn_set_key(struct ieee80211com *,
struct ieee80211_key *);
void iwn_delete_key(struct ieee80211com *, struct ieee80211_node *,
struct ieee80211_key *);
+void iwn_update_htprot(struct ieee80211com *,
+ const struct ieee80211_node *);
int iwn_ampdu_rx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
void iwn_ampdu_rx_stop(struct ieee80211com *,
@@ -515,6 +517,7 @@ iwn_attach(struct device *parent, struct
ic->ic_updateedca = iwn_updateedca;
ic->ic_set_key = iwn_set_key;
ic->ic_delete_key = iwn_delete_key;
+ ic->ic_update_htprot = iwn_update_htprot;
ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
#ifdef notyet
@@ -5009,6 +5012,44 @@ iwn_delete_key(struct ieee80211com *ic,
node.kid = 0xff;
DPRINTF(("delete keys for node %d\n", node.id));
(void)ops->add_node(sc, &node, 1);
+}
+
+/*
+ * This function is called by upper layer when HT protection settings in
+ * beacons have changed.
+ */
+void
+iwn_update_htprot(struct ieee80211com *ic, const struct ieee80211_node *ni)
+{
+ struct iwn_softc *sc = ic->ic_softc;
+ struct iwn_rxon_assoc cmd;
+ enum ieee80211_htprot htprot;
+ int error;
+
+ memset(&cmd, 0, sizeof cmd);
+
+ /* Copy settings from RXON configuration. */
+ cmd.flags = sc->rxon.flags;
+ cmd.filter = sc->rxon.filter;
+ cmd.cck_mask = sc->rxon.cck_mask;
+ cmd.ofdm_mask = sc->rxon.ofdm_mask;
+ cmd.ht_single_mask = sc->rxon.ht_single_mask;
+ cmd.ht_dual_mask = sc->rxon.ht_dual_mask;
+ cmd.ht_triple_mask = sc->rxon.ht_triple_mask;
+ cmd.rxchain = sc->rxon.rxchain;
+ cmd.acquisition = sc->rxon.acquisition;
+
+ /* Update HT protection setting. */
+ htprot = ((ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
+ IEEE80211_HTOP1_PROT_SHIFT);
+ cmd.flags &= ~htole32(IWN_RXON_HT_PROTMODE(3));
+ cmd.flags |= htole32(IWN_RXON_HT_PROTMODE(htprot));
+
+ /* Use the RXON_ASSOC command since we're already associated. */
+ error = iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof cmd, 1);
+ if (error != 0)
+ printf("%s: could not change HT protection: error %d\n",
+ sc->sc_dev.dv_xname, error);
}
/*
Index: dev/pci/if_iwnreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwnreg.h,v
retrieving revision 1.51
diff -u -p -r1.51 if_iwnreg.h
--- dev/pci/if_iwnreg.h 7 Jan 2016 23:08:38 -0000 1.51
+++ dev/pci/if_iwnreg.h 20 Jan 2016 20:09:13 -0000
@@ -529,6 +529,22 @@ struct iwn_rxon {
#define IWN4965_RXONSZ (sizeof (struct iwn_rxon) - 6)
#define IWN5000_RXONSZ (sizeof (struct iwn_rxon))
+/* Structure for command IWN_CMD_RXON_ASSOC. */
+struct iwn_rxon_assoc {
+ uint32_t flags;
+ uint32_t filter;
+ uint8_t cck_mask;
+ uint8_t ofdm_mask;
+ uint16_t reserved1;
+ uint8_t ht_single_mask;
+ uint8_t ht_dual_mask;
+ uint8_t ht_triple_mask;
+ uint8_t reserved2;
+ uint16_t rxchain;
+ uint16_t acquisition;
+ uint32_t reserved3;
+} __packed;
+
/* Structure for command IWN_CMD_ASSOCIATE. */
struct iwn_assoc {
uint32_t flags;
Index: net80211/ieee80211_input.c
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_input.c,v
retrieving revision 1.151
diff -u -p -r1.151 ieee80211_input.c
--- net80211/ieee80211_input.c 7 Jan 2016 23:22:31 -0000 1.151
+++ net80211/ieee80211_input.c 20 Jan 2016 20:52:08 -0000
@@ -1577,10 +1577,14 @@ ieee80211_recv_probe_resp(struct ieee802
} else
is_new = 0;
+ if (htcaps)
+ ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
+ if (htop)
+ ieee80211_setup_htop(ni, htop + 2, htop[1]);
+
/*
* When operating in station mode, check for state updates
- * while we're associated. We consider only 11g stuff right
- * now.
+ * while we're associated.
*/
if (ic->ic_opmode == IEEE80211_M_STA &&
ic->ic_state == IEEE80211_S_RUN &&
@@ -1599,6 +1603,22 @@ ieee80211_recv_probe_resp(struct ieee802
ic->ic_flags &= ~IEEE80211_F_USEPROT;
ic->ic_bss->ni_erp = erp;
}
+ if (ic->ic_bss->ni_flags & IEEE80211_NODE_HT) {
+ enum ieee80211_htprot htprot_last, htprot;
+ htprot_last =
+ ((ic->ic_bss->ni_htop1 & IEEE80211_HTOP1_PROT_MASK)
+ >> IEEE80211_HTOP1_PROT_SHIFT);
+ htprot = ((ni->ni_htop1 & IEEE80211_HTOP1_PROT_MASK) >>
+ IEEE80211_HTOP1_PROT_SHIFT);
+ if (htprot_last != htprot) {
+ DPRINTF(("[%s] htprot change: was %d, now %d\n",
+ ether_sprintf((u_int8_t *)wh->i_addr2),
+ htprot_last, htprot));
+ ic->ic_bss->ni_htop1 = ni->ni_htop1;
+ ic->ic_update_htprot(ic, ic->ic_bss);
+ }
+ }
+
/*
* Check if AP short slot time setting has changed
* since last beacon and give the driver a chance to
@@ -1679,10 +1699,6 @@ ieee80211_recv_probe_resp(struct ieee802
ni->ni_erp = erp;
/* NB: must be after ni_chan is setup */
ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT);
- if (htcaps)
- ieee80211_setup_htcaps(ni, htcaps + 2, htcaps[1]);
- if (htop)
- ieee80211_setup_htop(ni, htop + 2, htop[1]);
#ifndef IEEE80211_STA_ONLY
if (ic->ic_opmode == IEEE80211_M_IBSS && is_new && isprobe) {
/*
Index: net80211/ieee80211_var.h
===================================================================
RCS file: /cvs/src/sys/net80211/ieee80211_var.h,v
retrieving revision 1.70
diff -u -p -r1.70 ieee80211_var.h
--- net80211/ieee80211_var.h 12 Jan 2016 09:28:09 -0000 1.70
+++ net80211/ieee80211_var.h 20 Jan 2016 19:18:40 -0000
@@ -213,6 +213,8 @@ struct ieee80211com {
struct ieee80211_node *, u_int8_t);
void (*ic_ampdu_rx_stop)(struct ieee80211com *,
struct ieee80211_node *, u_int8_t);
+ void (*ic_update_htprot)(struct ieee80211com *,
+ const struct ieee80211_node *);
u_int8_t ic_myaddr[IEEE80211_ADDR_LEN];
struct ieee80211_rateset ic_sup_rates[IEEE80211_MODE_MAX];
struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];