Re: ieee80211_stats userland vs. kernel
On Tue, Mar 08, 2022 at 02:38:39PM -0700, Theo de Raadt wrote: > Stefan Sperling wrote: > > In this case it is not ifconfig, but netstat -W iwm0. > > Which is a debugging tool, like netstat -s. > > We don't care when netstat breaks Alright, then this diff is indeed not necessary.
Re: ieee80211_stats userland vs. kernel
Stefan Sperling wrote: > On Tue, Mar 08, 2022 at 12:58:27PM -0700, Theo de Raadt wrote: > > Claudio Jeker wrote: > > > > > Honestly I think this is overkill. There is no stat struct where we do > > > this dance. It is accepted that netstat needs to keep in sync for these > > > structs to work. Why is it necessary to disconnect the kernel and userland > > > for this? > > > > Actually there is a major one: it is how ps works. > > > > I think the problem is when this struct is changed, ifconfig becomes > > unusable? > > In this case it is not ifconfig, but netstat -W iwm0. > Which is a debugging tool, like netstat -s. We don't care when netstat breaks But we really care when ifconfig breaks, in particular in the area of the "media" command related things.
Re: ieee80211_stats userland vs. kernel
On Tue, Mar 08, 2022 at 12:58:27PM -0700, Theo de Raadt wrote: > Claudio Jeker wrote: > > > Honestly I think this is overkill. There is no stat struct where we do > > this dance. It is accepted that netstat needs to keep in sync for these > > structs to work. Why is it necessary to disconnect the kernel and userland > > for this? > > Actually there is a major one: it is how ps works. > > I think the problem is when this struct is changed, ifconfig becomes unusable? In this case it is not ifconfig, but netstat -W iwm0. Which is a debugging tool, like netstat -s.
Re: ieee80211_stats userland vs. kernel
Claudio Jeker wrote: > Honestly I think this is overkill. There is no stat struct where we do > this dance. It is accepted that netstat needs to keep in sync for these > structs to work. Why is it necessary to disconnect the kernel and userland > for this? Actually there is a major one: it is how ps works. I think the problem is when this struct is changed, ifconfig becomes unusable? Making a different userland & kernel struct might not solve it, unless some games are played. For instance, append extra pads for future extension, so that the ioctl can still get at the data when fields are used. Discourage changing the types/sizes of fields. When a field is removed, change it into a pad rather than shuffling the struct. Eventually we'll hit a flag day. But with this current design, I think we'll trip into kernel:userland ABI breakage too easily, and it just needs some clever policy around the struct to ensure it doesn't cause that breakage.
Re: ieee80211_stats userland vs. kernel
On Tue, Mar 08, 2022 at 07:17:33PM +0100, Stefan Sperling wrote: > On Tue, Mar 08, 2022 at 03:55:48PM +0100, Stefan Sperling wrote: > > On Mon, Mar 07, 2022 at 03:04:06PM -0700, Theo de Raadt wrote: > > > > For now, the structs are identical so the code copying data out is > > > > kept simple. > > > > > > I think this is unwise, and you should write the field-by-field copying > > > function at the same time, otherwise this is just asking for trouble. > > > You really cannot wait until an intentional change. > > > > Sure, here it is. > > On second thought, avoiding the malloc/free dance is better. > The struct is still small enough to fit on the stack. > > diff refs/heads/master refs/heads/statsreq > blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49 > blob + 62938001ed22fc133a0c98e27ef5690c978e21f3 > --- sys/net80211/ieee80211_ioctl.c > +++ sys/net80211/ieee80211_ioctl.c > @@ -55,6 +55,8 @@ void ieee80211_node2req(struct ieee80211com *, > const struct ieee80211_node *, struct ieee80211_nodereq *); > void ieee80211_req2node(struct ieee80211com *, > const struct ieee80211_nodereq *, struct ieee80211_node *); > +void ieee80211_stats2req(struct ieee80211_statsreq *, > + struct ieee80211_stats *); > > void > ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, > @@ -180,6 +182,89 @@ ieee80211_req2node(struct ieee80211com *ic, const stru > } > > void > +ieee80211_stats2req(struct ieee80211_statsreq *req, > +struct ieee80211_stats *stats) > +{ > + memset(req, 0, sizeof(*req)); > + > + req->is_rx_badversion = stats->is_rx_badversion; > + req->is_rx_tooshort = stats->is_rx_tooshort; > + req->is_rx_wrongbss = stats->is_rx_wrongbss; > + req->is_rx_dup = stats->is_rx_dup; > + req->is_rx_wrongdir = stats->is_rx_wrongdir; > + req->is_rx_mcastecho = stats->is_rx_mcastecho; > + req->is_rx_notassoc = stats->is_rx_notassoc; > + req->is_rx_nowep = stats->is_rx_nowep; > + req->is_rx_unencrypted = stats->is_rx_unencrypted; > + req->is_rx_wepfail = stats->is_rx_wepfail; > + req->is_rx_decap = stats->is_rx_decap; > + req->is_rx_mgtdiscard = stats->is_rx_mgtdiscard; > + req->is_rx_ctl = stats->is_rx_ctl; > + req->is_rx_rstoobig = stats->is_rx_rstoobig; > + req->is_rx_elem_missing = stats->is_rx_elem_missing; > + req->is_rx_elem_toobig = stats->is_rx_elem_toobig; > + req->is_rx_elem_toosmall = stats->is_rx_elem_toosmall; > + req->is_rx_badchan = stats->is_rx_badchan; > + req->is_rx_chanmismatch = stats->is_rx_chanmismatch; > + req->is_rx_nodealloc = stats->is_rx_nodealloc; > + req->is_rx_ssidmismatch = stats->is_rx_ssidmismatch; > + req->is_rx_auth_unsupported = stats->is_rx_auth_unsupported; > + req->is_rx_auth_fail = stats->is_rx_auth_fail; > + req->is_rx_assoc_bss = stats->is_rx_assoc_bss; > + req->is_rx_assoc_notauth = stats->is_rx_assoc_notauth; > + req->is_rx_assoc_capmismatch = stats->is_rx_assoc_capmismatch; > + req->is_rx_assoc_norate = stats->is_rx_assoc_norate; > + req->is_rx_deauth = stats->is_rx_deauth; > + req->is_rx_disassoc = stats->is_rx_disassoc; > + req->is_rx_badsubtype = stats->is_rx_badsubtype; > + req->is_rx_nombuf = stats->is_rx_nombuf; > + req->is_rx_decryptcrc = stats->is_rx_decryptcrc; > + req->is_rx_ahdemo_mgt = stats->is_rx_ahdemo_mgt; > + req->is_rx_bad_auth = stats->is_rx_bad_auth; > + req->is_tx_nombuf = stats->is_tx_nombuf; > + req->is_tx_nonode = stats->is_tx_nonode; > + req->is_tx_unknownmgt = stats->is_tx_unknownmgt; > + req->is_scan_active = stats->is_scan_active; > + req->is_scan_passive = stats->is_scan_passive; > + req->is_node_timeout = stats->is_node_timeout; > + req->is_crypto_nomem = stats->is_crypto_nomem; > + req->is_rx_assoc_badrsnie = stats->is_rx_assoc_badrsnie; > + req->is_rx_unauth = stats->is_rx_unauth; > + req->is_tx_noauth = stats->is_tx_noauth; > + req->is_rx_eapol_key = stats->is_rx_eapol_key; > + req->is_rx_eapol_replay = stats->is_rx_eapol_replay; > + req->is_rx_eapol_badmic = stats->is_rx_eapol_badmic; > + req->is_rx_remmicfail = stats->is_rx_remmicfail; > + req->is_rx_locmicfail = stats->is_rx_locmicfail; > + req->is_tkip_replays = stats->is_tkip_replays; > + req->is_tkip_icv_errs = stats->is_tkip_icv_errs; > + req->is_ccmp_replays = stats->is_ccmp_replays; > + req->is_ccmp_dec_errs = stats->is_ccmp_dec_errs; > + req->is_cmac_replays = stats->is_cmac_replays; > + req->is_cmac_icv_errs = stats->is_cmac_icv_errs; > + req->is_pbac_errs = stats->is_pbac_errs; > + req->is_ht_nego_no_mandatory_mcs = stats->is_ht_nego_no_mandatory_mcs; > + req->is_ht_nego_no_basic_mcs = stats->is_ht_nego_no_basic_mcs; > + req->is_ht_nego_bad_crypto = stats->is_ht_nego_bad_crypto; > + req->is_ht_prot_change = stats->is_ht_prot_change; > + req->is_ht_rx_ba_agreements =
Re: ieee80211_stats userland vs. kernel
On Tue, Mar 08, 2022 at 03:55:48PM +0100, Stefan Sperling wrote: > On Mon, Mar 07, 2022 at 03:04:06PM -0700, Theo de Raadt wrote: > > > For now, the structs are identical so the code copying data out is > > > kept simple. > > > > I think this is unwise, and you should write the field-by-field copying > > function at the same time, otherwise this is just asking for trouble. > > You really cannot wait until an intentional change. > > Sure, here it is. On second thought, avoiding the malloc/free dance is better. The struct is still small enough to fit on the stack. diff refs/heads/master refs/heads/statsreq blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49 blob + 62938001ed22fc133a0c98e27ef5690c978e21f3 --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -55,6 +55,8 @@ void ieee80211_node2req(struct ieee80211com *, const struct ieee80211_node *, struct ieee80211_nodereq *); voidieee80211_req2node(struct ieee80211com *, const struct ieee80211_nodereq *, struct ieee80211_node *); +void ieee80211_stats2req(struct ieee80211_statsreq *, + struct ieee80211_stats *); void ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, @@ -180,6 +182,89 @@ ieee80211_req2node(struct ieee80211com *ic, const stru } void +ieee80211_stats2req(struct ieee80211_statsreq *req, +struct ieee80211_stats *stats) +{ + memset(req, 0, sizeof(*req)); + + req->is_rx_badversion = stats->is_rx_badversion; + req->is_rx_tooshort = stats->is_rx_tooshort; + req->is_rx_wrongbss = stats->is_rx_wrongbss; + req->is_rx_dup = stats->is_rx_dup; + req->is_rx_wrongdir = stats->is_rx_wrongdir; + req->is_rx_mcastecho = stats->is_rx_mcastecho; + req->is_rx_notassoc = stats->is_rx_notassoc; + req->is_rx_nowep = stats->is_rx_nowep; + req->is_rx_unencrypted = stats->is_rx_unencrypted; + req->is_rx_wepfail = stats->is_rx_wepfail; + req->is_rx_decap = stats->is_rx_decap; + req->is_rx_mgtdiscard = stats->is_rx_mgtdiscard; + req->is_rx_ctl = stats->is_rx_ctl; + req->is_rx_rstoobig = stats->is_rx_rstoobig; + req->is_rx_elem_missing = stats->is_rx_elem_missing; + req->is_rx_elem_toobig = stats->is_rx_elem_toobig; + req->is_rx_elem_toosmall = stats->is_rx_elem_toosmall; + req->is_rx_badchan = stats->is_rx_badchan; + req->is_rx_chanmismatch = stats->is_rx_chanmismatch; + req->is_rx_nodealloc = stats->is_rx_nodealloc; + req->is_rx_ssidmismatch = stats->is_rx_ssidmismatch; + req->is_rx_auth_unsupported = stats->is_rx_auth_unsupported; + req->is_rx_auth_fail = stats->is_rx_auth_fail; + req->is_rx_assoc_bss = stats->is_rx_assoc_bss; + req->is_rx_assoc_notauth = stats->is_rx_assoc_notauth; + req->is_rx_assoc_capmismatch = stats->is_rx_assoc_capmismatch; + req->is_rx_assoc_norate = stats->is_rx_assoc_norate; + req->is_rx_deauth = stats->is_rx_deauth; + req->is_rx_disassoc = stats->is_rx_disassoc; + req->is_rx_badsubtype = stats->is_rx_badsubtype; + req->is_rx_nombuf = stats->is_rx_nombuf; + req->is_rx_decryptcrc = stats->is_rx_decryptcrc; + req->is_rx_ahdemo_mgt = stats->is_rx_ahdemo_mgt; + req->is_rx_bad_auth = stats->is_rx_bad_auth; + req->is_tx_nombuf = stats->is_tx_nombuf; + req->is_tx_nonode = stats->is_tx_nonode; + req->is_tx_unknownmgt = stats->is_tx_unknownmgt; + req->is_scan_active = stats->is_scan_active; + req->is_scan_passive = stats->is_scan_passive; + req->is_node_timeout = stats->is_node_timeout; + req->is_crypto_nomem = stats->is_crypto_nomem; + req->is_rx_assoc_badrsnie = stats->is_rx_assoc_badrsnie; + req->is_rx_unauth = stats->is_rx_unauth; + req->is_tx_noauth = stats->is_tx_noauth; + req->is_rx_eapol_key = stats->is_rx_eapol_key; + req->is_rx_eapol_replay = stats->is_rx_eapol_replay; + req->is_rx_eapol_badmic = stats->is_rx_eapol_badmic; + req->is_rx_remmicfail = stats->is_rx_remmicfail; + req->is_rx_locmicfail = stats->is_rx_locmicfail; + req->is_tkip_replays = stats->is_tkip_replays; + req->is_tkip_icv_errs = stats->is_tkip_icv_errs; + req->is_ccmp_replays = stats->is_ccmp_replays; + req->is_ccmp_dec_errs = stats->is_ccmp_dec_errs; + req->is_cmac_replays = stats->is_cmac_replays; + req->is_cmac_icv_errs = stats->is_cmac_icv_errs; + req->is_pbac_errs = stats->is_pbac_errs; + req->is_ht_nego_no_mandatory_mcs = stats->is_ht_nego_no_mandatory_mcs; + req->is_ht_nego_no_basic_mcs = stats->is_ht_nego_no_basic_mcs; + req->is_ht_nego_bad_crypto = stats->is_ht_nego_bad_crypto; + req->is_ht_prot_change = stats->is_ht_prot_change; + req->is_ht_rx_ba_agreements = stats->is_ht_rx_ba_agreements; + req->is_ht_tx_ba_agreements = stats->is_ht_tx_ba_agreements; + req->is_ht_rx_frame_below_ba_winstart
Re: ieee80211_stats userland vs. kernel
On Mon, Mar 07, 2022 at 03:04:06PM -0700, Theo de Raadt wrote: > > For now, the structs are identical so the code copying data out is > > kept simple. > > I think this is unwise, and you should write the field-by-field copying > function at the same time, otherwise this is just asking for trouble. > You really cannot wait until an intentional change. Sure, here it is. diff 0ed925b6612724f216b84360a04117aad1c6df9b 6615def0a9e782a7fd930d75fda1ae4ec0f90dd2 blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49 blob + d4f6b536b2eb2165f85f9df7c08a1cee36a428a4 --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -55,6 +55,7 @@ void ieee80211_node2req(struct ieee80211com *, const struct ieee80211_node *, struct ieee80211_nodereq *); voidieee80211_req2node(struct ieee80211com *, const struct ieee80211_nodereq *, struct ieee80211_node *); +struct ieee80211_statsreq *ieee80211_stats2req(struct ieee80211_stats *); void ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni, @@ -179,6 +180,94 @@ ieee80211_req2node(struct ieee80211com *ic, const stru ni->ni_state = nr->nr_state; } +struct ieee80211_statsreq * +ieee80211_stats2req(struct ieee80211_stats *stats) +{ + struct ieee80211_statsreq *req; + + req = malloc(sizeof(*req), M_DEVBUF, M_ZERO | M_WAITOK | M_CANFAIL); + if (req == NULL) + return NULL; + + req->is_rx_badversion = stats->is_rx_badversion; + req->is_rx_tooshort = stats->is_rx_tooshort; + req->is_rx_wrongbss = stats->is_rx_wrongbss; + req->is_rx_dup = stats->is_rx_dup; + req->is_rx_wrongdir = stats->is_rx_wrongdir; + req->is_rx_mcastecho = stats->is_rx_mcastecho; + req->is_rx_notassoc = stats->is_rx_notassoc; + req->is_rx_nowep = stats->is_rx_nowep; + req->is_rx_unencrypted = stats->is_rx_unencrypted; + req->is_rx_wepfail = stats->is_rx_wepfail; + req->is_rx_decap = stats->is_rx_decap; + req->is_rx_mgtdiscard = stats->is_rx_mgtdiscard; + req->is_rx_ctl = stats->is_rx_ctl; + req->is_rx_rstoobig = stats->is_rx_rstoobig; + req->is_rx_elem_missing = stats->is_rx_elem_missing; + req->is_rx_elem_toobig = stats->is_rx_elem_toobig; + req->is_rx_elem_toosmall = stats->is_rx_elem_toosmall; + req->is_rx_badchan = stats->is_rx_badchan; + req->is_rx_chanmismatch = stats->is_rx_chanmismatch; + req->is_rx_nodealloc = stats->is_rx_nodealloc; + req->is_rx_ssidmismatch = stats->is_rx_ssidmismatch; + req->is_rx_auth_unsupported = stats->is_rx_auth_unsupported; + req->is_rx_auth_fail = stats->is_rx_auth_fail; + req->is_rx_assoc_bss = stats->is_rx_assoc_bss; + req->is_rx_assoc_notauth = stats->is_rx_assoc_notauth; + req->is_rx_assoc_capmismatch = stats->is_rx_assoc_capmismatch; + req->is_rx_assoc_norate = stats->is_rx_assoc_norate; + req->is_rx_deauth = stats->is_rx_deauth; + req->is_rx_disassoc = stats->is_rx_disassoc; + req->is_rx_badsubtype = stats->is_rx_badsubtype; + req->is_rx_nombuf = stats->is_rx_nombuf; + req->is_rx_decryptcrc = stats->is_rx_decryptcrc; + req->is_rx_ahdemo_mgt = stats->is_rx_ahdemo_mgt; + req->is_rx_bad_auth = stats->is_rx_bad_auth; + req->is_tx_nombuf = stats->is_tx_nombuf; + req->is_tx_nonode = stats->is_tx_nonode; + req->is_tx_unknownmgt = stats->is_tx_unknownmgt; + req->is_scan_active = stats->is_scan_active; + req->is_scan_passive = stats->is_scan_passive; + req->is_node_timeout = stats->is_node_timeout; + req->is_crypto_nomem = stats->is_crypto_nomem; + req->is_rx_assoc_badrsnie = stats->is_rx_assoc_badrsnie; + req->is_rx_unauth = stats->is_rx_unauth; + req->is_tx_noauth = stats->is_tx_noauth; + req->is_rx_eapol_key = stats->is_rx_eapol_key; + req->is_rx_eapol_replay = stats->is_rx_eapol_replay; + req->is_rx_eapol_badmic = stats->is_rx_eapol_badmic; + req->is_rx_remmicfail = stats->is_rx_remmicfail; + req->is_rx_locmicfail = stats->is_rx_locmicfail; + req->is_tkip_replays = stats->is_tkip_replays; + req->is_tkip_icv_errs = stats->is_tkip_icv_errs; + req->is_ccmp_replays = stats->is_ccmp_replays; + req->is_ccmp_dec_errs = stats->is_ccmp_dec_errs; + req->is_cmac_replays = stats->is_cmac_replays; + req->is_cmac_icv_errs = stats->is_cmac_icv_errs; + req->is_pbac_errs = stats->is_pbac_errs; + req->is_ht_nego_no_mandatory_mcs = stats->is_ht_nego_no_mandatory_mcs; + req->is_ht_nego_no_basic_mcs = stats->is_ht_nego_no_basic_mcs; + req->is_ht_nego_bad_crypto = stats->is_ht_nego_bad_crypto; + req->is_ht_prot_change = stats->is_ht_prot_change; + req->is_ht_rx_ba_agreements = stats->is_ht_rx_ba_agreements; + req->is_ht_tx_ba_agreements = stats->is_ht_tx_ba_agreements; + req->is_ht_rx_frame_below_ba_winstart = +
Re: ieee80211_stats userland vs. kernel
> For now, the structs are identical so the code copying data out is > kept simple. I think this is unwise, and you should write the field-by-field copying function at the same time, otherwise this is just asking for trouble. You really cannot wait until an intentional change.
ieee80211_stats userland vs. kernel
There is another net80211 ioctl which shares a struct between kernel and userland: struct ieee80211_stats shown by the netstat -W command. While it is trivial to recompile netstat when this struct is changed, giving the kernel a separate struct type would allow us to add, change, or remove counters in the kernel without impacting userland immediately. Is this worth it? For now, the structs are identical so the code copying data out is kept simple. The struct is quite large and we could probably get rid of some of these counters without losing useful debugging information, but that is a separate problem. Warning: This diff seems to overflow miniroot71.img on amd64, breaking 'make release' builds without further changes. diff 7f506de28f9813c0e2213a45686e27166679219e 64e5109ffcdce254aca22d4a8a40991e792c0738 blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49 blob + a3a734d32123ff96870e24efeb30651bfd0b50be --- sys/net80211/ieee80211_ioctl.c +++ sys/net80211/ieee80211_ioctl.c @@ -810,17 +810,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t break; } break; -#if 0 - case SIOCG80211ZSTATS: -#endif case SIOCG80211STATS: ifr = (struct ifreq *)data; error = copyout(>ic_stats, ifr->ifr_data, - sizeof(ic->ic_stats)); -#if 0 - if (cmd == SIOCG80211ZSTATS) - memset(>ic_stats, 0, sizeof(ic->ic_stats)); -#endif + MIN(sizeof(struct ieee80211_statsreq), + sizeof(struct ieee80211_stats))); break; case SIOCS80211TXPOWER: if ((error = suser(curproc)) != 0) blob - 65e93c23da2d86c0ad259f77b7c9affc85d9038b blob + fa95ad15b809e16868e2eba4dba66568b5a66cfe --- sys/net80211/ieee80211_ioctl.h +++ sys/net80211/ieee80211_ioctl.h @@ -37,8 +37,8 @@ * IEEE 802.11 ioctls. */ -/* per-interface statistics */ -struct ieee80211_stats { +/* per-interface statistics, corresponds to struct ieee80211_stats */ +struct ieee80211_statsreq { u_int32_t is_rx_badversion; /* rx frame with bad version */ u_int32_t is_rx_tooshort; /* rx frame too short */ u_int32_t is_rx_wrongbss; /* rx from wrong bssid */ blob - 161853a629887a1aa997480d605d4febd66dd2db blob + d8845bfc6aa1331110ca22ec949a00932645907e --- sys/net80211/ieee80211_var.h +++ sys/net80211/ieee80211_var.h @@ -214,6 +214,81 @@ struct ieee80211_defrag { struct ieee80211_node_switch_bss_arg; +/* per-interface statistics */ +struct ieee80211_stats { + u_int32_t is_rx_badversion; /* rx frame with bad version */ + u_int32_t is_rx_tooshort; /* rx frame too short */ + u_int32_t is_rx_wrongbss; /* rx from wrong bssid */ + u_int32_t is_rx_dup; /* rx discard 'cuz dup */ + u_int32_t is_rx_wrongdir; /* rx w/ wrong direction */ + u_int32_t is_rx_mcastecho;/* rx discard 'cuz mcast echo */ + u_int32_t is_rx_notassoc; /* rx discard 'cuz sta !assoc */ + u_int32_t is_rx_nowep;/* rx w/ wep but wep !config */ + u_int32_t is_rx_unencrypted; /* rx w/o wep but wep config */ + u_int32_t is_rx_wepfail; /* rx wep processing failed */ + u_int32_t is_rx_decap;/* rx decapsulation failed */ + u_int32_t is_rx_mgtdiscard; /* rx discard mgt frames */ + u_int32_t is_rx_ctl; /* rx discard ctrl frames */ + u_int32_t is_rx_rstoobig; /* rx rate set truncated */ + u_int32_t is_rx_elem_missing; /* rx required element missing*/ + u_int32_t is_rx_elem_toobig; /* rx element too big */ + u_int32_t is_rx_elem_toosmall;/* rx element too small */ + u_int32_t is_rx_badchan; /* rx frame w/ invalid chan */ + u_int32_t is_rx_chanmismatch; /* rx frame chan mismatch */ + u_int32_t is_rx_nodealloc;/* rx frame dropped */ + u_int32_t is_rx_ssidmismatch; /* rx frame ssid mismatch */ + u_int32_t is_rx_auth_unsupported; /* rx w/ unsupported auth alg */ + u_int32_t is_rx_auth_fail;/* rx sta auth failure */ + u_int32_t is_rx_assoc_bss;/* rx assoc from wrong bssid */ + u_int32_t is_rx_assoc_notauth;/* rx assoc w/o auth */ + u_int32_t is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */ + u_int32_t is_rx_assoc_norate; /* rx assoc w/ no rate match */ + u_int32_t is_rx_deauth; /* rx deauthentication */ + u_int32_t is_rx_disassoc; /* rx disassociation */ + u_int32_t is_rx_badsubtype; /* rx frame w/ unknown subtype*/ + u_int32_t is_rx_nombuf; /* rx