diff options
Diffstat (limited to 'sys/net80211')
| -rw-r--r-- | sys/net80211/ieee80211.c | 28 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_crypto.c | 87 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_crypto.h | 105 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_ddb.c | 2 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_freebsd.h | 33 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_ht.c | 20 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_hwmp.c | 2 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_mesh.c | 2 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_node.c | 4 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_node.h | 34 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_output.c | 17 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_phy.c | 32 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_phy.h | 8 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_proto.c | 2 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_sta.c | 2 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_var.h | 5 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_vht.c | 22 | ||||
| -rw-r--r-- | sys/net80211/ieee80211_vht.h | 4 |
18 files changed, 315 insertions, 94 deletions
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 2b7cf635b9f5..1299f86ebdc7 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -2689,13 +2689,18 @@ ieee80211_channel_type_char(const struct ieee80211_channel *c) return 'f'; } -/* - * Determine whether the given key in the given VAP is a global key. +/** + * @brief Determine whether the given key in the given VAP is a global key. + * * (key index 0..3, shared between all stations on a VAP.) * * This is either a WEP key or a GROUP key. * * Note this will NOT return true if it is a IGTK key. + * + * @param vap the current VAP + * @param key ieee80211_key to use/check + * @returns true if it's a global/WEP key, false otherwise */ bool ieee80211_is_key_global(const struct ieee80211vap *vap, @@ -2705,8 +2710,23 @@ ieee80211_is_key_global(const struct ieee80211vap *vap, key < &vap->iv_nw_keys[IEEE80211_WEP_NKID]); } -/* - * Determine whether the given key in the given VAP is a unicast key. +/** + * @brief Determine whether the given key in the given VAP is a unicast key. + * + * This only returns true if it's a unicast key. + * + * Note: For now net80211 only supports a single unicast key, stored in + * an ieee80211_node entry. + * + * Code should use this to know if it's a unicast key and then call + * ieee80211_crypto_get_keyid() to get the 802.11 key ID (0..3 for + * unicast/global keys, 4..5 for IGTK keys.) Since the unicast + * and global key indexes "overlap", callers will need to check + * both the type and id. + * + * @param vap the current VAP + * @param key ieee80211_key to use/check + * @returns true if the key is a unicast key, false if it is not */ bool ieee80211_is_key_unicast(const struct ieee80211vap *vap, diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c index 1e63ca46f28f..566f0b2e0c23 100644 --- a/sys/net80211/ieee80211_crypto.c +++ b/sys/net80211/ieee80211_crypto.c @@ -611,11 +611,15 @@ ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key) return dev_key_set(vap, key); } -/* - * Return index if the key is a WEP key (0..3); -1 otherwise. +/** + * @brief Return index if the key is a WEP key (0..3); -1 otherwise. * * This is different to "get_keyid" which defaults to returning * 0 for unicast keys; it assumes that it won't be used for WEP. + * + * @param vap the current VAP + * @param k ieee80211_key to check + * @returns 0..3 if it's a global/WEP key, -1 otherwise. */ int ieee80211_crypto_get_key_wepidx(const struct ieee80211vap *vap, @@ -628,8 +632,18 @@ ieee80211_crypto_get_key_wepidx(const struct ieee80211vap *vap, return (-1); } -/* - * Note: only supports a single unicast key (0). +/** + * @brief Return the index of a unicast, global or IGTK key. + * + * Return the index of a key. For unicast keys the index is 0..1. + * For global/WEP keys it's 0..3. For IGTK keys its 4..5. + * + * TODO: support >1 unicast key + * TODO: support IGTK keys + * + * @param vap the current VAP + * @param k ieee80211_key to check + * @returns 0..3 for a WEP/global key, 0..1 for unicast key, 4..5 for IGTK key */ uint8_t ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k) @@ -641,6 +655,19 @@ ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k) return (0); } +/** + * @param Return the key to use for encrypting an mbuf frame to a node + * + * This routine chooses a suitable key used to encrypt the given frame with. + * It doesn't do the encryption; it only chooses the key. If a key is not + * available then the routine will return NULL. + * + * It's up to the caller to enforce whether a key is absolutely required or not. + * + * @param ni The ieee80211_node to send the frame to + * @param m the mbuf to encrypt + * @returns the ieee80211_key to encrypt with, or NULL if there's no suitable key + */ struct ieee80211_key * ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m) { @@ -676,8 +703,28 @@ ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m) return &ni->ni_ucastkey; } -/* - * Add privacy headers appropriate for the specified key. +/** + * @brief Privacy encapsulate and encrypt the given mbuf. + * + * This routine handles the mechanics of encryption - expanding the + * mbuf to add privacy headers, IV, ICV, MIC, MMIC, and then encrypts + * the given mbuf if required. + * + * This should be called by the driver in its TX path as part of + * encapsulation before passing frames to the hardware/firmware + * queues. + * + * Drivers/hardware which does its own entirely offload path + * should still call this for completeness - it indicates to the + * driver that the frame itself should be encrypted. + * + * The driver should have set capability bits in the attach / + * key allocation path to disable various encapsulation/encryption + * features. + * + * @param ni ieee80211_node for this frame + * @param mbuf mbuf to modify + * @returns the key used if the frame is to be encrypted, NULL otherwise */ struct ieee80211_key * ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) @@ -693,9 +740,31 @@ ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m) return NULL; } -/* - * Validate and strip privacy headers (and trailer) for a - * received frame that has the WEP/Privacy bit set. +/** + * @brief Decapsulate and validate an encrypted frame. + * + * This handles an encrypted frame (one with the privacy bit set.) + * It also obeys the key / config / receive packet flags for how + * the driver says its already been processed. + * + * Unlike ieee80211_crypto_encap(), this isn't called in the driver. + * Instead, drivers passed the potentially decrypted frame - fully, + * partial, or not at all - and net80211 will call this as appropriate. + * + * This handles NICs (like ath(4)) which have a variable size between + * the 802.11 header and 802.11 payload due to DMA alignment / encryption + * engine concerns. + * + * If the frame was decrypted and validated successfully then 1 is returned + * and the mbuf can be treated as an 802.11 frame. If it is not decrypted + * successfully or it was decrypted but failed validation/checks, then + * 0 is returned. + * + * @param ni ieee80211_node for received frame + * @param m mbuf frame to receive + * @param hdrlen length of the 802.11 header, including trailing null bytes + * @param key pointer to ieee80211_key that will be set if appropriate + * @returns 0 if the frame wasn't decrypted/validated, 1 if decrypted/validated. */ int ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen, diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h index 89b8b4f9daa4..48115da586b5 100644 --- a/sys/net80211/ieee80211_crypto.h +++ b/sys/net80211/ieee80211_crypto.h @@ -94,6 +94,7 @@ struct ieee80211_key { ieee80211_keyix wk_keyix; /* h/w key index */ ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */ + /* TODO: deprecate direct access to wk_key, wk_txmic, wk_rxmic */ uint8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; #define wk_txmic wk_key+IEEE80211_KEYBUF_SIZE+0 /* XXX can't () right */ #define wk_rxmic wk_key+IEEE80211_KEYBUF_SIZE+8 /* XXX can't () right */ @@ -300,5 +301,109 @@ void ieee80211_notify_michael_failure(struct ieee80211vap *, uint16_t ieee80211_crypto_init_aad(const struct ieee80211_frame *, uint8_t *, int); +/** + * @brief Return the key data. + * + * This returns a pointer to the key data. Note it does not + * guarantee the TX/RX MIC will be immediately after the key. + * Callers must use ieee80211_crypto_get_key_txmic_data() + * and ieee80211_crypto_get_key_rxmic_data() for that. + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns NULL if no key data is available, or a pointer + * to the key data. + */ +static inline const uint8_t * +ieee80211_crypto_get_key_data(const struct ieee80211_key *k) +{ + return (k->wk_key); +} + +/** + * @brief Return the key length in bytes. + * + * This doesn't include any TX/RX MIC (eg from TKIP). + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns the key length (without any MIC) in bytes + */ +static inline const uint16_t +ieee80211_crypto_get_key_len(const struct ieee80211_key *k) +{ + return (k->wk_keylen); +} + +/** + * @brief Return the TX MIC data. + * + * This returns a pointer to the TX MIC data. + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns NULL if no key data is available, or a pointer + * to the TX MIC data. + */ +static inline const uint8_t * +ieee80211_crypto_get_key_txmic_data(const struct ieee80211_key *k) +{ + return (k->wk_txmic); +} + +/** + * @brief Return the TX MIC length in bytes. + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns the TX MIC length in bytes + */ +static inline const uint16_t +ieee80211_crypto_get_key_txmic_len(const struct ieee80211_key *k) +{ + return (k->wk_cipher->ic_miclen); +} + +/** + * @brief Return the RX MIC data. + * + * This returns a pointer to the RX MIC data. + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns NULL if no key data is available, or a pointer + * to the RX MIC data. + */ +static inline const uint8_t * +ieee80211_crypto_get_key_rxmic_data(const struct ieee80211_key *k) +{ + return (k->wk_rxmic); +} + +/** + * @brief Return the RX MIC length in bytes. + * + * Note: there's no locking; this needs to be called in + * a situation where the ieee80211_key won't disappear. + * + * @param k ieee80211_key + * @returns the RX MIC length in bytes + */ +static inline const uint16_t +ieee80211_crypto_get_key_rxmic_len(const struct ieee80211_key *k) +{ + return (k->wk_cipher->ic_miclen); +} + #endif /* defined(__KERNEL__) || defined(_KERNEL) */ #endif /* _NET80211_IEEE80211_CRYPTO_H_ */ diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c index d96d7988a864..1dd8e38b9896 100644 --- a/sys/net80211/ieee80211_ddb.c +++ b/sys/net80211/ieee80211_ddb.c @@ -296,7 +296,7 @@ _db_show_sta(const struct ieee80211_node *ni) ni->ni_htparam, ni->ni_htctlchan, ni->ni_ht2ndchan); db_printf("\thtopmode 0x%x htstbc 0x%x chw %d (%s)\n", ni->ni_htopmode, ni->ni_htstbc, - ni->ni_chw, ieee80211_ni_chw_to_str(ni->ni_chw)); + ni->ni_chw, net80211_ni_chw_to_str(ni->ni_chw)); /* XXX ampdu state */ for (i = 0; i < WME_NUM_TID; i++) diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h index 141b13f9f740..954801d95787 100644 --- a/sys/net80211/ieee80211_freebsd.h +++ b/sys/net80211/ieee80211_freebsd.h @@ -93,12 +93,22 @@ typedef struct { } while (0) #define IEEE80211_TX_LOCK_OBJ(_ic) (&(_ic)->ic_txlock.mtx) #define IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK(_ic) mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_UNLOCK(_ic) mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)) -#define IEEE80211_TX_LOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED) -#define IEEE80211_TX_UNLOCK_ASSERT(_ic) \ - mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED) +#define IEEE80211_TX_LOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_UNLOCK(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic)); \ + } while (0); +#define IEEE80211_TX_LOCK_ASSERT(_ic) do { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED); \ + } while (0) +#define IEEE80211_TX_UNLOCK_ASSERT(_ic) { \ + if (!IEEE80211_CONF_SEQNO_OFFLOAD(_ic)) \ + mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED); \ + } while (0) /* * Stageq / ni_tx_superg lock @@ -331,11 +341,16 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen); #define M_AGE_SUB(m,adj) (m->m_pkthdr.csum_data -= adj) /* - * Store the sequence number. + * Store / retrieve the sequence number in an mbuf. + * + * The sequence number being stored/retreived is the 12 bit + * base sequence number, not the 16 bit sequence number field. + * I.e., it's from 0..4095 inclusive, with no 4 bit padding for + * fragment numbers. */ #define M_SEQNO_SET(m, seqno) \ - ((m)->m_pkthdr.tso_segsz = (seqno)) -#define M_SEQNO_GET(m) ((m)->m_pkthdr.tso_segsz) + ((m)->m_pkthdr.tso_segsz = ((seqno) % IEEE80211_SEQ_RANGE)) +#define M_SEQNO_GET(m) (((m)->m_pkthdr.tso_segsz) % IEEE80211_SEQ_RANGE) #define MTAG_ABI_NET80211 1132948340 /* net80211 ABI */ diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c index c28f124648a1..a8a767785fce 100644 --- a/sys/net80211/ieee80211_ht.c +++ b/sys/net80211/ieee80211_ht.c @@ -167,7 +167,7 @@ static ieee80211_send_action_func ht_send_action_ba_delba; static ieee80211_send_action_func ht_send_action_ht_txchwidth; static void -ieee80211_ht_init(void) +ieee80211_ht_init(void *dummy __unused) { /* * Setup HT parameters that depends on the clock frequency. @@ -1476,7 +1476,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI20; if (IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { ni->ni_htcap |= IEEE80211_HTCAP_CHWIDTH40; - ni->ni_chw = IEEE80211_STA_RX_BW_40; + ni->ni_chw = NET80211_STA_RX_BW_40; if (IEEE80211_IS_CHAN_HT40U(ni->ni_chan)) ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_ABOVE; else if (IEEE80211_IS_CHAN_HT40D(ni->ni_chan)) @@ -1484,7 +1484,7 @@ ieee80211_ht_wds_init(struct ieee80211_node *ni) if (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40) ni->ni_htcap |= IEEE80211_HTCAP_SHORTGI40; } else { - ni->ni_chw = IEEE80211_STA_RX_BW_20; + ni->ni_chw = NET80211_STA_RX_BW_20; ni->ni_ht2ndchan = IEEE80211_HTINFO_2NDCHAN_NONE; } ni->ni_htctlchan = ni->ni_chan->ic_ieee; @@ -1580,7 +1580,7 @@ ieee80211_ht_node_join(struct ieee80211_node *ni) if (ni->ni_flags & IEEE80211_NODE_HT) { vap->iv_ht_sta_assoc++; - if (ni->ni_chw == IEEE80211_STA_RX_BW_40) + if (ni->ni_chw == NET80211_STA_RX_BW_40) vap->iv_ht40_sta_assoc++; } htinfo_update(vap); @@ -1598,7 +1598,7 @@ ieee80211_ht_node_leave(struct ieee80211_node *ni) if (ni->ni_flags & IEEE80211_NODE_HT) { vap->iv_ht_sta_assoc--; - if (ni->ni_chw == IEEE80211_STA_RX_BW_40) + if (ni->ni_chw == NET80211_STA_RX_BW_40) vap->iv_ht40_sta_assoc--; } htinfo_update(vap); @@ -1827,7 +1827,7 @@ htinfo_update_chw(struct ieee80211_node *ni, int htflags, int vhtflags) done: /* update node's (11n) tx channel width */ ni->ni_chw = IEEE80211_IS_CHAN_HT40(ni->ni_chan) ? - IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; + NET80211_STA_RX_BW_40 : NET80211_STA_RX_BW_20; return (ret); } @@ -1933,7 +1933,7 @@ ieee80211_vht_get_vhtflags(struct ieee80211_node *ni, uint32_t htflags) { #define _RETURN_CHAN_BITS(_cb) \ do { \ - IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, \ + if (0) IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N, ni, \ "%s:%d: selected %b", __func__, __LINE__, \ (_cb), IEEE80211_CHAN_BITS); \ return (_cb); \ @@ -2689,11 +2689,11 @@ ht_recv_action_ht_txchwidth(struct ieee80211_node *ni, * here. */ chw = (frm[2] == IEEE80211_A_HT_TXCHWIDTH_2040) ? - IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; + NET80211_STA_RX_BW_40 : NET80211_STA_RX_BW_20; IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni, "%s: HT txchwidth, width %d%s (%s)", __func__, - chw, ni->ni_chw != chw ? "*" : "", ieee80211_ni_chw_to_str(chw)); + chw, ni->ni_chw != chw ? "*" : "", net80211_ni_chw_to_str(chw)); if (chw != ni->ni_chw) { /* XXX does this need to change the ht40 station count? */ ni->ni_chw = chw; @@ -3832,5 +3832,5 @@ ieee80211_ht_check_tx_ht40(const struct ieee80211_node *ni) return (IEEE80211_IS_CHAN_HT40(bss_chan) && IEEE80211_IS_CHAN_HT40(ni->ni_chan) && - (ni->ni_chw == IEEE80211_STA_RX_BW_40)); + (ni->ni_chw == NET80211_STA_RX_BW_40)); } diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c index b69210768c54..084e67da13db 100644 --- a/sys/net80211/ieee80211_hwmp.c +++ b/sys/net80211/ieee80211_hwmp.c @@ -212,7 +212,7 @@ SYSCTL_PROC(_net_wlan_hwmp, OID_AUTO, inact, "mesh route inactivity timeout (ms)"); static void -ieee80211_hwmp_init(void) +ieee80211_hwmp_init(void *dummy __unused) { /* Default values as per amendment */ ieee80211_hwmp_pathtimeout = msecs_to_ticks(5*1000); diff --git a/sys/net80211/ieee80211_mesh.c b/sys/net80211/ieee80211_mesh.c index 3f0410a69e3c..7f2e8bdcb963 100644 --- a/sys/net80211/ieee80211_mesh.c +++ b/sys/net80211/ieee80211_mesh.c @@ -548,7 +548,7 @@ mesh_gatemode_cb(void *arg) } static void -ieee80211_mesh_init(void) +ieee80211_mesh_init(void *dummy __unused) { memset(mesh_proto_paths, 0, sizeof(mesh_proto_paths)); diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index a201d1b278f0..49ba00299fee 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -2673,7 +2673,7 @@ ieee80211_dump_node(struct ieee80211_node_table *nt __unused, ni->ni_htctlchan, ni->ni_ht2ndchan); net80211_printf("\thtopmode %x htstbc %x htchw %d (%s)\n", ni->ni_htopmode, ni->ni_htstbc, - ni->ni_chw, ieee80211_ni_chw_to_str(ni->ni_chw)); + ni->ni_chw, net80211_ni_chw_to_str(ni->ni_chw)); net80211_printf("\tvhtcap %x freq1 %d freq2 %d vhtbasicmcs %x\n", ni->ni_vhtcap, (int) ni->ni_vht_chan1, (int) ni->ni_vht_chan2, (int) ni->ni_vht_basicmcs); @@ -2831,7 +2831,7 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp) ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", /* XXX update for VHT string */ ni->ni_flags & IEEE80211_NODE_HT ? - (ni->ni_chw == IEEE80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", + (ni->ni_chw == NET80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h index ef25fa0d7fdd..f1246dd12419 100644 --- a/sys/net80211/ieee80211_node.h +++ b/sys/net80211/ieee80211_node.h @@ -109,33 +109,33 @@ enum ieee80211_mesh_mlstate { "\20\1IDLE\2OPENSNT\2OPENRCV\3CONFIRMRCV\4ESTABLISHED\5HOLDING" /* - * This structure is shared with LinuxKPI 802.11 code describing up-to - * which channel width the station can receive. + * This enum was shared with the LinuxKPI enum ieee80211_sta_rx_bandwidth + * describing up-to which channel width the station can receive. * Rather than using hardcoded MHz values for the channel width use an enum with * flags. This allows us to keep the uint8_t slot for ni_chw in - * struct ieee80211_node and means we do not have to sync to the value for - * LinuxKPI. + * struct ieee80211_node it means we do not have to sync to the value for + * LinuxKPI (just the names). * * NB: BW_20 needs to 0 and values need to be sorted! Cannot make it * bitfield-alike for use with %b. */ -enum ieee80211_sta_rx_bw { - IEEE80211_STA_RX_BW_20 = 0x00, - IEEE80211_STA_RX_BW_40, - IEEE80211_STA_RX_BW_80, - IEEE80211_STA_RX_BW_160, - IEEE80211_STA_RX_BW_320, +enum net80211_sta_rx_bw { + NET80211_STA_RX_BW_20 = 0x00, + NET80211_STA_RX_BW_40, + NET80211_STA_RX_BW_80, + NET80211_STA_RX_BW_160, + NET80211_STA_RX_BW_320, } __packed; static inline const char * -ieee80211_ni_chw_to_str(enum ieee80211_sta_rx_bw bw) +net80211_ni_chw_to_str(enum net80211_sta_rx_bw bw) { switch (bw) { - case IEEE80211_STA_RX_BW_20: return ("BW_20"); - case IEEE80211_STA_RX_BW_40: return ("BW_40"); - case IEEE80211_STA_RX_BW_80: return ("BW_80"); - case IEEE80211_STA_RX_BW_160: return ("BW_160"); - case IEEE80211_STA_RX_BW_320: return ("BW_320"); + case NET80211_STA_RX_BW_20: return ("BW_20"); + case NET80211_STA_RX_BW_40: return ("BW_40"); + case NET80211_STA_RX_BW_80: return ("BW_80"); + case NET80211_STA_RX_BW_160: return ("BW_160"); + case NET80211_STA_RX_BW_320: return ("BW_320"); } } @@ -285,7 +285,7 @@ struct ieee80211_node { uint8_t ni_ht2ndchan; /* HT 2nd channel */ uint8_t ni_htopmode; /* HT operating mode */ uint8_t ni_htstbc; /* HT */ - enum ieee80211_sta_rx_bw ni_chw; /* negotiated channel width */ + enum net80211_sta_rx_bw ni_chw; /* negotiated channel width */ struct ieee80211_htrateset ni_htrates; /* negotiated ht rate set */ struct ieee80211_tx_ampdu ni_tx_ampdu[WME_NUM_TID]; struct ieee80211_rx_ampdu ni_rx_ampdu[WME_NUM_TID]; diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index afe83ea0805c..116fc76a9ce1 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -974,7 +974,7 @@ ieee80211_send_setup( /* NB: zero out i_seq field (for s/w encryption etc) */ *(uint16_t *)&wh->i_seq[0] = 0; - } else + } else if (!IEEE80211_CONF_SEQNO_OFFLOAD(ni->ni_ic)) ieee80211_output_seqno_assign(ni, tid, m); if (IEEE80211_IS_MULTICAST(wh->i_addr1)) @@ -1082,6 +1082,12 @@ ieee80211_send_nulldata(struct ieee80211_node *ni) uint8_t *frm; int ret; + /* Don't send NULL frames if we've been configured not to do so. */ + if ((ic->ic_flags_ext & IEEE80211_FEXT_NO_NULLDATA) != 0) { + ieee80211_node_decref(ni); + return (0); + } + if (vap->iv_state == IEEE80211_S_CAC) { IEEE80211_NOTE(vap, IEEE80211_MSG_OUTPUT | IEEE80211_MSG_DOTH, ni, "block %s frame in CAC state", "null data"); @@ -1810,7 +1816,8 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, * and we don't need the TX lock held. */ if ((m->m_flags & M_AMPDU_MPDU) == 0) { - ieee80211_output_seqno_assign(ni, tid, m); + if (!IEEE80211_CONF_SEQNO_OFFLOAD(ic)) + ieee80211_output_seqno_assign(ni, tid, m); } else { /* * NB: don't assign a sequence # to potential @@ -1828,7 +1835,9 @@ ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni, *(uint16_t *)wh->i_seq = 0; } } else { - ieee80211_output_seqno_assign(ni, IEEE80211_NONQOS_TID, m); + if (!IEEE80211_CONF_SEQNO_OFFLOAD(ic)) + ieee80211_output_seqno_assign(ni, IEEE80211_NONQOS_TID, + m); /* * XXX TODO: we shouldn't allow EAPOL, etc that would * be forced to be non-QoS traffic to be A-MSDU encapsulated. @@ -3856,6 +3865,8 @@ ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast) * If the driver identifies it does its own TX seqno management then * we can skip this (and still not do the TX seqno.) */ + + /* TODO: IEEE80211_CONF_SEQNO_OFFLOAD() */ ieee80211_output_beacon_seqno_assign(ni, m); /* XXX faster to recalculate entirely or just changes? */ diff --git a/sys/net80211/ieee80211_phy.c b/sys/net80211/ieee80211_phy.c index eb96d74a2bd9..b4d9b16907d2 100644 --- a/sys/net80211/ieee80211_phy.c +++ b/sys/net80211/ieee80211_phy.c @@ -348,7 +348,7 @@ ieee80211_setup_ratetable(struct ieee80211_rate_table *rt) /* Setup all rate tables */ static void -ieee80211_phy_init(void) +ieee80211_phy_init(void *dummy __unused) { static struct ieee80211_rate_table * const ratetables[] = { &ieee80211_half_table, @@ -658,26 +658,26 @@ static uint16_t ieee80211_vht_mcs_allowed_list_160[] = { * * See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details. * - * @param bw channel bandwidth, via enum ieee80211_sta_rx_bw + * @param bw channel bandwidth, via enum net80211_sta_rx_bw * @param nss number of spatial streams, 1..8 * @returns bitmask of valid MCS rates from 0..9 */ uint16_t -ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw bw, uint8_t nss) +ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw bw, uint8_t nss) { if (nss == 0 || nss > 8) return (0); switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: return (ieee80211_vht_mcs_allowed_list_20[nss - 1]); - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: return (ieee80211_vht_mcs_allowed_list_40[nss - 1]); - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: return (ieee80211_vht_mcs_allowed_list_80[nss - 1]); - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: return (ieee80211_vht_mcs_allowed_list_160[nss - 1]); - case IEEE80211_STA_RX_BW_320: + case NET80211_STA_RX_BW_320: /* invalid for VHT */ return (0); } @@ -689,14 +689,14 @@ ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw bw, uint8_t nss) * * See 802.11-2020 21.5 (Parameters for VHT-MCSs) for more details. * - * @param bw channel bandwidth, via enum ieee80211_sta_rx_bw + * @param bw channel bandwidth, via enum net80211_sta_rx_bw * @param nss number of spatial streams, 1..8 * @param mcs MCS rate, 0..9 * @retval true if the NSS / MCS / bandwidth combination is valid * @retval false if the NSS / MCS / bandwidth combination is not valid */ bool -ieee80211_phy_vht_validate_mcs(enum ieee80211_sta_rx_bw bw, uint8_t nss, +ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) { uint16_t mask; @@ -737,7 +737,7 @@ static struct mcs_entry mcs_entries[] = { /** * @brief Calculate the bitrate of the given VHT MCS rate. * - * @param bw Channel bandwidth (enum ieee80211_sta_rx_bw) + * @param bw Channel bandwidth (enum net80211_sta_rx_bw) * @param nss Number of spatial streams, 1..8 * @param mcs MCS, 0..9 * @param is_shortgi True if short guard-interval (400nS) @@ -746,7 +746,7 @@ static struct mcs_entry mcs_entries[] = { * @returns The bitrate in kbit/sec. */ uint32_t -ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw bw, +ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs, bool is_shortgi) { uint32_t sym_len, n_carriers; @@ -773,16 +773,16 @@ ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw bw, * See 802.11-2020 Table 21-5 (Timing-related constraints.) */ switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: n_carriers = 52; break; - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: n_carriers = 108; break; - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: n_carriers = 234; break; - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: n_carriers = 468; break; default: diff --git a/sys/net80211/ieee80211_phy.h b/sys/net80211/ieee80211_phy.h index 749b082e34e9..391c8bfc5010 100644 --- a/sys/net80211/ieee80211_phy.h +++ b/sys/net80211/ieee80211_phy.h @@ -221,13 +221,13 @@ uint32_t ieee80211_compute_duration_ht(uint32_t frameLen, uint16_t rate, int streams, int isht40, int isShortGI); -enum ieee80211_sta_rx_bw; +enum net80211_sta_rx_bw; -uint16_t ieee80211_phy_vht_get_mcs_mask(enum ieee80211_sta_rx_bw, +uint16_t ieee80211_phy_vht_get_mcs_mask(enum net80211_sta_rx_bw, uint8_t); -bool ieee80211_phy_vht_validate_mcs(enum ieee80211_sta_rx_bw, +bool ieee80211_phy_vht_validate_mcs(enum net80211_sta_rx_bw, uint8_t, uint8_t); -uint32_t ieee80211_phy_vht_get_mcs_kbit(enum ieee80211_sta_rx_bw, +uint32_t ieee80211_phy_vht_get_mcs_kbit(enum net80211_sta_rx_bw, uint8_t, uint8_t, bool); #endif /* _KERNEL */ diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c index 0c161d98a55a..4918bf7d025f 100644 --- a/sys/net80211/ieee80211_proto.c +++ b/sys/net80211/ieee80211_proto.c @@ -459,7 +459,7 @@ static const struct ieee80211_authenticator auth_internal = { * Setup internal authenticators once; they are never unregistered. */ static void -ieee80211_auth_setup(void) +ieee80211_auth_setup(void *dummy __unused) { ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal); ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal); diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c index 463a8b16773b..19e5ffe9a367 100644 --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -1934,7 +1934,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, vap->iv_flags&IEEE80211_F_USEPROT ? ", protection" : "", ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "", ni->ni_flags & IEEE80211_NODE_HT ? - (ni->ni_chw == IEEE80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", + (ni->ni_chw == NET80211_STA_RX_BW_40 ? ", HT40" : ", HT20") : "", ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "", ni->ni_flags & IEEE80211_NODE_AMSDU ? " (+AMSDU)" : "", ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" : diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index a0293f814899..7b45261f59b1 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -700,13 +700,14 @@ MALLOC_DECLARE(M_80211_VAP); #define IEEE80211_FEXT_QUIET_IE 0x00800000 /* STATUS: quiet IE in a beacon has been added */ #define IEEE80211_FEXT_UAPSD 0x01000000 /* CONF: enable U-APSD */ #define IEEE80211_FEXT_AMPDU_OFFLOAD 0x02000000 /* CONF: driver/fw handles AMPDU[-TX] itself */ +#define IEEE80211_FEXT_NO_NULLDATA 0x04000000 /* CONF: don't originate NULL data frames from net80211 */ #define IEEE80211_FEXT_BITS \ "\20\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \ "\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \ "\20BPF\21WDSLEGACY\22PROBECHAN\23UNIQMAC\24SCAN_OFFLOAD\25SEQNO_OFFLOAD" \ "\26FRAG_OFFLOAD\27VHT" \ - "\30QUIET_IE\31UAPSD\32AMPDU_OFFLOAD" + "\30QUIET_IE\31UAPSD\32AMPDU_OFFLOAD\33NO_NULLDATA" /* ic_flags_ht/iv_flags_ht */ #define IEEE80211_FHT_NONHT_PR 0x00000001 /* STATUS: non-HT sta present */ @@ -1012,7 +1013,7 @@ ieee80211_get_node_txpower(struct ieee80211_node *ni) * Debugging facilities compiled in when IEEE80211_DEBUG is defined. * * The intent is that any problem in the net80211 layer can be - * diagnosed by inspecting the statistics (dumped by the wlanstats + * diagnosed by inspecting the statistics (dumped by the wlanstat * program) and/or the msgs generated by net80211. Messages are * broken into functional classes and can be controlled with the * wlandebug program. Certain of these msg groups are for facilities diff --git a/sys/net80211/ieee80211_vht.c b/sys/net80211/ieee80211_vht.c index de0b691d4d2a..095c4108c768 100644 --- a/sys/net80211/ieee80211_vht.c +++ b/sys/net80211/ieee80211_vht.c @@ -102,7 +102,7 @@ vht_send_action_placeholder(struct ieee80211_node *ni, } static void -ieee80211_vht_init(void) +ieee80211_vht_init(void *dummy __unused) { ieee80211_recv_action_register(IEEE80211_ACTION_CAT_VHT, @@ -974,7 +974,7 @@ ieee80211_vht_check_tx_vht40(const struct ieee80211_node *ni) return (IEEE80211_IS_CHAN_VHT40(bss_chan) && IEEE80211_IS_CHAN_VHT40(ni->ni_chan) && - (ni->ni_chw == IEEE80211_STA_RX_BW_40)); + (ni->ni_chw == NET80211_STA_RX_BW_40)); } /* @@ -1003,7 +1003,7 @@ ieee80211_vht_check_tx_vht80(const struct ieee80211_node *ni) */ return (IEEE80211_IS_CHAN_VHT80(bss_chan) && IEEE80211_IS_CHAN_VHT80(ni->ni_chan) && - (ni->ni_chw != IEEE80211_STA_RX_BW_20)); + (ni->ni_chw != NET80211_STA_RX_BW_20)); } /* @@ -1030,7 +1030,7 @@ ieee80211_vht_check_tx_vht160(const struct ieee80211_node *ni) * If a HT TX width action frame sets it to 20MHz * then reject doing 160MHz. */ - if (ni->ni_chw == IEEE80211_STA_RX_BW_20) + if (ni->ni_chw == NET80211_STA_RX_BW_20) return (false); if (IEEE80211_IS_CHAN_VHT160(bss_chan) && @@ -1062,19 +1062,19 @@ ieee80211_vht_check_tx_vht160(const struct ieee80211_node *ni) */ bool ieee80211_vht_check_tx_bw(const struct ieee80211_node *ni, - enum ieee80211_sta_rx_bw bw) + enum net80211_sta_rx_bw bw) { switch (bw) { - case IEEE80211_STA_RX_BW_20: + case NET80211_STA_RX_BW_20: return (ieee80211_vht_check_tx_vht(ni)); - case IEEE80211_STA_RX_BW_40: + case NET80211_STA_RX_BW_40: return (ieee80211_vht_check_tx_vht40(ni)); - case IEEE80211_STA_RX_BW_80: + case NET80211_STA_RX_BW_80: return (ieee80211_vht_check_tx_vht80(ni)); - case IEEE80211_STA_RX_BW_160: + case NET80211_STA_RX_BW_160: return (ieee80211_vht_check_tx_vht160(ni)); - case IEEE80211_STA_RX_BW_320: + case NET80211_STA_RX_BW_320: return (false); default: return (false); @@ -1096,7 +1096,7 @@ ieee80211_vht_check_tx_bw(const struct ieee80211_node *ni, */ bool ieee80211_vht_node_check_tx_valid_mcs(const struct ieee80211_node *ni, - enum ieee80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) + enum net80211_sta_rx_bw bw, uint8_t nss, uint8_t mcs) { uint8_t mc; diff --git a/sys/net80211/ieee80211_vht.h b/sys/net80211/ieee80211_vht.h index a1529df4a85b..b9b19fbc6008 100644 --- a/sys/net80211/ieee80211_vht.h +++ b/sys/net80211/ieee80211_vht.h @@ -65,8 +65,8 @@ void ieee80211_vht_get_vhtinfo_ie(struct ieee80211_node *ni, bool ieee80211_vht_check_tx_vht(const struct ieee80211_node *); bool ieee80211_vht_check_tx_bw(const struct ieee80211_node *, - enum ieee80211_sta_rx_bw); + enum net80211_sta_rx_bw); bool ieee80211_vht_node_check_tx_valid_mcs(const struct ieee80211_node *, - enum ieee80211_sta_rx_bw bw, uint8_t, uint8_t); + enum net80211_sta_rx_bw bw, uint8_t, uint8_t); #endif /* _NET80211_IEEE80211_VHT_H_ */ |
