diff options
-rw-r--r-- | net/mac80211/sta_info.h | 10 | ||||
-rw-r--r-- | net/mac80211/tx.c | 40 |
2 files changed, 44 insertions, 6 deletions
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 0602363ff63b..c821fe47c2d1 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -241,6 +241,8 @@ struct sta_ampdu_mlme { /* Value to indicate no TID reservation */ #define IEEE80211_TID_UNRESERVED 0xff +#define IEEE80211_FAST_XMIT_MAX_IV 18 + /** * struct ieee80211_fast_tx - TX fastpath information * @key: key to use for hw crypto @@ -252,15 +254,17 @@ struct sta_ampdu_mlme { * @band: band this will be transmitted on, for tx_info * @rcu_head: RCU head to free this struct * - * Try to keep this struct small so it fits into a single cacheline. + * This struct is small enough so that the common case (maximum crypto + * header length of 8 like for CCMP/GCMP) fits into a single 64-byte + * cache line. */ struct ieee80211_fast_tx { struct ieee80211_key *key; - u8 hdr[30 + 2 + IEEE80211_CCMP_HDR_LEN + - sizeof(rfc1042_header)]; u8 hdr_len; u8 sa_offs, da_offs, pn_offs; u8 band; + u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV + + sizeof(rfc1042_header)]; struct rcu_head rcu_head; }; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index d983683a8a13..39e80c3f4726 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2535,10 +2535,11 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) if (!build.key) build.key = rcu_access_pointer(sdata->default_unicast_key); if (build.key) { - bool gen_iv, iv_spc; + bool gen_iv, iv_spc, mmic; gen_iv = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV; iv_spc = build.key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE; + mmic = build.key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC; /* don't handle software crypto */ if (!(build.key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) @@ -2567,9 +2568,42 @@ void ieee80211_check_fast_xmit(struct sta_info *sta) if (gen_iv || iv_spc) build.hdr_len += IEEE80211_GCMP_HDR_LEN; break; - default: - /* don't do fast-xmit for these ciphers (yet) */ + case WLAN_CIPHER_SUITE_TKIP: + /* cannot handle MMIC or IV generation in xmit-fast */ + if (mmic || gen_iv) + goto out; + if (iv_spc) + build.hdr_len += IEEE80211_TKIP_IV_LEN; + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + /* cannot handle IV generation in fast-xmit */ + if (gen_iv) + goto out; + if (iv_spc) + build.hdr_len += IEEE80211_WEP_IV_LEN; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + WARN(1, + "management cipher suite 0x%x enabled for data\n", + build.key->conf.cipher); goto out; + default: + /* we don't know how to generate IVs for this at all */ + if (WARN_ON(gen_iv)) + goto out; + /* pure hardware keys are OK, of course */ + if (!(build.key->flags & KEY_FLAG_CIPHER_SCHEME)) + break; + /* cipher scheme might require space allocation */ + if (iv_spc && + build.key->conf.iv_len > IEEE80211_FAST_XMIT_MAX_IV) + goto out; + if (iv_spc) + build.hdr_len += build.key->conf.iv_len; } fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |