diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index 9b53c93e21ef..e9130ef5bc95 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -3449,13 +3449,30 @@ printies(const u_int8_t *vp, int ielen, int maxcols) static void printmimo(const struct ieee80211_mimo_info *mi) { - /* NB: don't muddy display unless there's something to show */ - if (mi->rssi[0] != 0 || mi->rssi[1] != 0 || mi->rssi[2] != 0) { - /* XXX ignore EVM for now */ - printf(" (rssi %.1f:%.1f:%.1f nf %d:%d:%d)", - mi->rssi[0] / 2.0, mi->rssi[1] / 2.0, mi->rssi[2] / 2.0, - mi->noise[0], mi->noise[1], mi->noise[2]); + int i; + int r = 0; + + for (i = 0; i < IEEE80211_MAX_CHAINS; i++) { + if (mi->ch[i].rssi != 0) { + r = 1; + break; + } } + + /* NB: don't muddy display unless there's something to show */ + if (r == 0) + return; + + /* XXX TODO: ignore EVM; secondary channels for now */ + printf(" (rssi %.1f:%.1f:%.1f:%.1f nf %d:%d:%d:%d)", + mi->ch[0].rssi[0] / 2.0, + mi->ch[1].rssi[0] / 2.0, + mi->ch[2].rssi[0] / 2.0, + mi->ch[3].rssi[0] / 2.0, + mi->ch[0].noise[0], + mi->ch[1].noise[0], + mi->ch[2].noise[0], + mi->ch[3].noise[0]); } static void diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index a40e6223d5da..56d71e8029e9 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -4402,6 +4402,13 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) tid = 0; } ac = M_WME_GETAC(m); + + /* + * XXX TODO: Group addressed frames aren't aggregated and must + * go to the normal non-aggregation queue, and have a NONQOS TID + * assigned from net80211. + */ + if (m->m_flags & M_AMPDU_MPDU) { uint16_t seqno; struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac]; diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 1027eb0524db..79172aaf7bd7 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -2434,13 +2434,13 @@ mwl_node_getmimoinfo(const struct ieee80211_node *ni, if (mn->mn_ai.rssi_c > rssi_max) rssi_max = mn->mn_ai.rssi_c; - CVT(mi->rssi[0], mn->mn_ai.rssi_a); - CVT(mi->rssi[1], mn->mn_ai.rssi_b); - CVT(mi->rssi[2], mn->mn_ai.rssi_c); + CVT(mi->ch[0].rssi[0], mn->mn_ai.rssi_a); + CVT(mi->ch[1].rssi[0], mn->mn_ai.rssi_b); + CVT(mi->ch[2].rssi[0], mn->mn_ai.rssi_c); - mi->noise[0] = mn->mn_ai.nf_a; - mi->noise[1] = mn->mn_ai.nf_b; - mi->noise[2] = mn->mn_ai.nf_c; + mi->ch[0].noise[0] = mn->mn_ai.nf_a; + mi->ch[1].noise[0] = mn->mn_ai.nf_b; + mi->ch[2].noise[0] = mn->mn_ai.nf_c; #undef CVT } diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h index e7ae5d0cb4fd..9434f3a60641 100644 --- a/sys/net80211/_ieee80211.h +++ b/sys/net80211/_ieee80211.h @@ -443,17 +443,26 @@ struct ieee80211_regdomain { /* * MIMO antenna/radio state. */ - +#define IEEE80211_MAX_CHAINS 4 /* - * XXX This doesn't yet export both ctl/ext chain details - * XXX TODO: IEEE80211_MAX_CHAINS is defined in _freebsd.h, not here; - * figure out how to pull it in! + * This is the number of sub-channels for a channel. + * 0 - pri20 + * 1 - sec20 (HT40, VHT40) + * 2 - sec40 (VHT80) + * 3 - sec80 (VHT80+80, VHT160) */ +#define IEEE80211_MAX_CHAIN_PRISEC 4 +#define IEEE80211_MAX_EVM_DWORDS 16 /* 16 pilots, 4 chains */ +#define IEEE80211_MAX_EVM_PILOTS 16 /* 468 subcarriers, 16 pilots */ + +struct ieee80211_mimo_chan_info { + int8_t rssi[IEEE80211_MAX_CHAIN_PRISEC]; + int8_t noise[IEEE80211_MAX_CHAIN_PRISEC]; +}; + struct ieee80211_mimo_info { - int8_t rssi[3]; /* per-antenna rssi */ - int8_t noise[3]; /* per-antenna noise floor */ - uint8_t pad[2]; - uint32_t evm[3]; /* EVM data */ + struct ieee80211_mimo_chan_info ch[IEEE80211_MAX_CHAINS]; + uint32_t evm[IEEE80211_MAX_EVM_DWORDS]; }; /* @@ -523,4 +532,94 @@ struct ieee80211_mimo_info { "\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \ "\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS\32TXLDPC" +/* + * RX status notification - which fields are valid. + */ +#define IEEE80211_R_NF 0x00000001 /* global NF value valid */ +#define IEEE80211_R_RSSI 0x00000002 /* global RSSI value valid */ +#define IEEE80211_R_C_CHAIN 0x00000004 /* RX chain count valid */ +#define IEEE80211_R_C_NF 0x00000008 /* per-chain NF value valid */ +#define IEEE80211_R_C_RSSI 0x00000010 /* per-chain RSSI value valid */ +#define IEEE80211_R_C_EVM 0x00000020 /* per-chain EVM valid */ +#define IEEE80211_R_C_HT40 0x00000040 /* RX'ed packet is 40mhz, pilots 4,5 valid */ +#define IEEE80211_R_FREQ 0x00000080 /* Freq value populated, MHz */ +#define IEEE80211_R_IEEE 0x00000100 /* IEEE value populated */ +#define IEEE80211_R_BAND 0x00000200 /* Frequency band populated */ +#define IEEE80211_R_TSF32 0x00004000 /* 32 bit TSF */ +#define IEEE80211_R_TSF64 0x00008000 /* 64 bit TSF */ +#define IEEE80211_R_TSF_START 0x00010000 /* TSF is sampled at start of frame */ +#define IEEE80211_R_TSF_END 0x00020000 /* TSF is sampled at end of frame */ + +/* + * RX status notification - describe the packet. + */ +#define IEEE80211_RX_F_STBC 0x00000001 +#define IEEE80211_RX_F_LDPC 0x00000002 +#define IEEE80211_RX_F_AMSDU 0x00000004 /* This is the start of an decap AMSDU list */ +#define IEEE80211_RX_F_AMSDU_MORE 0x00000008 /* This is another decap AMSDU frame in the batch */ +#define IEEE80211_RX_F_AMPDU 0x00000010 /* This is the start of an decap AMPDU list */ +#define IEEE80211_RX_F_AMPDU_MORE 0x00000020 /* This is another decap AMPDU frame in the batch */ +#define IEEE80211_RX_F_FAIL_FCSCRC 0x00000040 /* Failed CRC/FCS */ +#define IEEE80211_RX_F_FAIL_MIC 0x00000080 /* Failed MIC check */ +#define IEEE80211_RX_F_DECRYPTED 0x00000100 /* Hardware decrypted */ +#define IEEE80211_RX_F_IV_STRIP 0x00000200 /* Decrypted; IV stripped */ +#define IEEE80211_RX_F_MMIC_STRIP 0x00000400 /* Decrypted; MMIC stripped */ +#define IEEE80211_RX_F_SHORTGI 0x00000800 /* This is a short-GI frame */ +#define IEEE80211_RX_F_CCK 0x00001000 +#define IEEE80211_RX_F_OFDM 0x00002000 +#define IEEE80211_RX_F_HT 0x00004000 +#define IEEE80211_RX_F_VHT 0x00008000 + +/* Channel width */ +#define IEEE80211_RX_FW_20MHZ 1 +#define IEEE80211_RX_FW_40MHZ 2 +#define IEEE80211_RX_FW_80MHZ 3 + +/* PHY type */ +#define IEEE80211_RX_FP_11B 1 +#define IEEE80211_RX_FP_11G 2 +#define IEEE80211_RX_FP_11A 3 +#define IEEE80211_RX_FP_11NA 4 +#define IEEE80211_RX_FP_11NG 5 + +struct ieee80211_rx_stats { + uint32_t r_flags; /* IEEE80211_R_* flags */ + uint32_t c_pktflags; /* IEEE80211_RX_F_* flags */ + + uint64_t c_rx_tsf; /* 32 or 64 bit TSF */ + + /* All DWORD aligned */ + int16_t c_nf_ctl[IEEE80211_MAX_CHAINS]; /* per-chain NF */ + int16_t c_nf_ext[IEEE80211_MAX_CHAINS]; /* per-chain NF */ + int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ + int16_t c_rssi_ext[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ + + /* 32 bits */ + uint8_t c_nf; /* global NF */ + uint8_t c_rssi; /* global RSSI */ + uint8_t c_chain; /* number of RX chains involved */ + uint8_t c_rate; /* legacy; 11n rate code; VHT MCS */ + + /* 32 bits */ + uint16_t c_freq; /* Frequency, MHz */ + uint8_t c_ieee; /* Channel */ + uint8_t c_width; /* channel width, FW flags above */ + + /* Force alignment to DWORD */ + union { + uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS]; + /* per-chain, per-pilot EVM values */ + uint32_t __aln[8]; + } evm; + + /* 32 bits */ + uint8_t c_phytype; /* PHY type, FW flags above */ + uint8_t c_vhtnss; /* VHT - number of spatial streams */ + uint8_t c_pad2[2]; +}; + +struct ieee80211_rx_params { + struct ieee80211_rx_stats params; +}; + #endif /* _NET80211__IEEE80211_H_ */ diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 57ab9d906b3b..2a0b7396951c 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -622,98 +622,9 @@ int ieee80211_add_xmit_params(struct mbuf *m, int ieee80211_get_xmit_params(struct mbuf *m, struct ieee80211_bpf_params *); -/* - * Note: this is fine for 3x3 (and 4x4) 11n HT40; - * but getting EVM information for VHT80, VHT160 - * will involve more than 6 EVM pilots. - */ -#define IEEE80211_MAX_CHAINS 4 -#define IEEE80211_MAX_EVM_PILOTS 6 +struct ieee80211_rx_params; +struct ieee80211_rx_stats; -#define IEEE80211_R_NF 0x00000001 /* global NF value valid */ -#define IEEE80211_R_RSSI 0x00000002 /* global RSSI value valid */ -#define IEEE80211_R_C_CHAIN 0x00000004 /* RX chain count valid */ -#define IEEE80211_R_C_NF 0x00000008 /* per-chain NF value valid */ -#define IEEE80211_R_C_RSSI 0x00000010 /* per-chain RSSI value valid */ -#define IEEE80211_R_C_EVM 0x00000020 /* per-chain EVM valid */ -#define IEEE80211_R_C_HT40 0x00000040 /* RX'ed packet is 40mhz, pilots 4,5 valid */ -#define IEEE80211_R_FREQ 0x00000080 /* Freq value populated, MHz */ -#define IEEE80211_R_IEEE 0x00000100 /* IEEE value populated */ -#define IEEE80211_R_BAND 0x00000200 /* Frequency band populated */ -#define IEEE80211_R_TSF32 0x00004000 /* 32 bit TSF */ -#define IEEE80211_R_TSF64 0x00008000 /* 64 bit TSF */ -#define IEEE80211_R_TSF_START 0x00010000 /* TSF is sampled at start of frame */ -#define IEEE80211_R_TSF_END 0x00020000 /* TSF is sampled at end of frame */ - -/* RX packet flags - describe the kind of frame */ -#define IEEE80211_RX_F_STBC 0x00000001 -#define IEEE80211_RX_F_LDPC 0x00000002 -#define IEEE80211_RX_F_AMSDU 0x00000004 /* This is the start of an decap AMSDU list */ -#define IEEE80211_RX_F_AMSDU_MORE 0x00000008 /* This is another decap AMSDU frame in the batch */ -#define IEEE80211_RX_F_AMPDU 0x00000010 /* This is the start of an decap AMPDU list */ -#define IEEE80211_RX_F_AMPDU_MORE 0x00000020 /* This is another decap AMPDU frame in the batch */ -#define IEEE80211_RX_F_FAIL_FCSCRC 0x00000040 /* Failed CRC/FCS */ -#define IEEE80211_RX_F_FAIL_MIC 0x00000080 /* Failed MIC check */ -#define IEEE80211_RX_F_DECRYPTED 0x00000100 /* Hardware decrypted */ -#define IEEE80211_RX_F_IV_STRIP 0x00000200 /* Decrypted; IV stripped */ -#define IEEE80211_RX_F_MMIC_STRIP 0x00000400 /* Decrypted; MMIC stripped */ -#define IEEE80211_RX_F_SHORTGI 0x00000800 /* This is a short-GI frame */ -#define IEEE80211_RX_F_CCK 0x00001000 -#define IEEE80211_RX_F_OFDM 0x00002000 -#define IEEE80211_RX_F_HT 0x00004000 -#define IEEE80211_RX_F_VHT 0x00008000 - -/* Channel width */ -#define IEEE80211_RX_FW_20MHZ 1 -#define IEEE80211_RX_FW_40MHZ 2 -#define IEEE80211_RX_FW_80MHZ 3 - -/* PHY type */ -#define IEEE80211_RX_FP_11B 1 -#define IEEE80211_RX_FP_11G 2 -#define IEEE80211_RX_FP_11A 3 -#define IEEE80211_RX_FP_11NA 4 -#define IEEE80211_RX_FP_11NG 5 - -struct ieee80211_rx_stats { - uint32_t r_flags; /* IEEE80211_R_* flags */ - uint32_t c_pktflags; /* IEEE80211_RX_F_* flags */ - - uint64_t c_rx_tsf; /* 32 or 64 bit TSF */ - - /* All DWORD aligned */ - int16_t c_nf_ctl[IEEE80211_MAX_CHAINS]; /* per-chain NF */ - int16_t c_nf_ext[IEEE80211_MAX_CHAINS]; /* per-chain NF */ - int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ - int16_t c_rssi_ext[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ - - /* 32 bits */ - uint8_t c_nf; /* global NF */ - uint8_t c_rssi; /* global RSSI */ - uint8_t c_chain; /* number of RX chains involved */ - uint8_t c_rate; /* legacy; 11n rate code; VHT MCS */ - - /* 32 bits */ - uint16_t c_freq; /* Frequency, MHz */ - uint8_t c_ieee; /* Channel */ - uint8_t c_width; /* channel width, FW flags above */ - - /* Force alignment to DWORD */ - union { - uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS]; - /* per-chain, per-pilot EVM values */ - uint32_t __aln[8]; - } evm; - - /* 32 bits */ - uint8_t c_phytype; /* PHY type, FW flags above */ - uint8_t c_vhtnss; /* VHT - number of spatial streams */ - uint8_t c_pad2[2]; -}; - -struct ieee80211_rx_params { - struct ieee80211_rx_stats params; -}; int ieee80211_add_rx_params(struct mbuf *m, const struct ieee80211_rx_stats *rxs); int ieee80211_get_rx_params(struct mbuf *m, diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index 65ff6ba0b5d2..9b1d8ed68a01 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -1318,15 +1318,16 @@ node_getmimoinfo(const struct ieee80211_node *ni, bzero(info, sizeof(*info)); - for (i = 0; i < ni->ni_mimo_chains; i++) { + for (i = 0; i < MIN(IEEE80211_MAX_CHAINS, ni->ni_mimo_chains); i++) { + /* Note: for now, just pri20 channel info */ avgrssi = ni->ni_mimo_rssi_ctl[i]; if (avgrssi == IEEE80211_RSSI_DUMMY_MARKER) { - info->rssi[i] = 0; + info->ch[i].rssi[0] = 0; } else { rssi = IEEE80211_RSSI_GET(avgrssi); - info->rssi[i] = rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; + info->ch[i].rssi[0] = rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; } - info->noise[i] = ni->ni_mimo_noise_ctl[i]; + info->ch[i].noise[0] = ni->ni_mimo_noise_ctl[i]; } /* XXX ext radios? */