Commit c93622b5 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-next-for-davem-2018-07-24' of...

Merge tag 'mac80211-next-for-davem-2018-07-24' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next



Johannes Berg says:

====================
Only a few things:
 * HE (802.11ax) support in HWSIM
 * bypass TXQ with NDP frames as they're special
 * convert ahash -> shash in lib80211 TKIP
 * avoid playing with tailroom counter defer unless
   needed to avoid issues in some cases
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a527d3f7 133bf90d
Loading
Loading
Loading
Loading
+123 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211
 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
 * Copyright (c) 2011, Javier Lopez <jlopex@gmail.com>
 * Copyright (c) 2016 - 2017 Intel Deutschland GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
@@ -2517,6 +2518,123 @@ out_err:
	nlmsg_free(mcast_skb);
}

static const struct ieee80211_sband_iftype_data he_capa_2ghz = {
	/* TODO: should we support other types, e.g., P2P?*/
	.types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
	.he_cap = {
		.has_he = true,
		.he_cap_elem = {
			.mac_cap_info[0] =
				IEEE80211_HE_MAC_CAP0_HTC_HE,
			.mac_cap_info[1] =
				IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
				IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8,
			.mac_cap_info[2] =
				IEEE80211_HE_MAC_CAP2_BSR |
				IEEE80211_HE_MAC_CAP2_MU_CASCADING |
				IEEE80211_HE_MAC_CAP2_ACK_EN,
			.mac_cap_info[3] =
				IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU |
				IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
				IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2,
			.mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU,
			.phy_cap_info[0] =
				IEEE80211_HE_PHY_CAP0_DUAL_BAND,
			.phy_cap_info[1] =
				IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
				IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
				IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
				IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS,
			.phy_cap_info[2] =
				IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
				IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
				IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
				IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
				IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,

			/* Leave all the other PHY capability bytes unset, as
			 * DCM, beam forming, RU and PPE threshold information
			 * are not supported
			 */
		},
		.he_mcs_nss_supp = {
			.rx_mcs_80 = cpu_to_le16(0xfffa),
			.tx_mcs_80 = cpu_to_le16(0xfffa),
			.rx_mcs_160 = cpu_to_le16(0xffff),
			.tx_mcs_160 = cpu_to_le16(0xffff),
			.rx_mcs_80p80 = cpu_to_le16(0xffff),
			.tx_mcs_80p80 = cpu_to_le16(0xffff),
		},
	},
};

static const struct ieee80211_sband_iftype_data he_capa_5ghz = {
	/* TODO: should we support other types, e.g., P2P?*/
	.types_mask = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP),
	.he_cap = {
		.has_he = true,
		.he_cap_elem = {
			.mac_cap_info[0] =
				IEEE80211_HE_MAC_CAP0_HTC_HE,
			.mac_cap_info[1] =
				IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
				IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_QOS_8,
			.mac_cap_info[2] =
				IEEE80211_HE_MAC_CAP2_BSR |
				IEEE80211_HE_MAC_CAP2_MU_CASCADING |
				IEEE80211_HE_MAC_CAP2_ACK_EN,
			.mac_cap_info[3] =
				IEEE80211_HE_MAC_CAP3_GRP_ADDR_MULTI_STA_BA_DL_MU |
				IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
				IEEE80211_HE_MAC_CAP3_MAX_A_AMPDU_LEN_EXP_VHT_2,
			.mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU,
			.phy_cap_info[0] =
				IEEE80211_HE_PHY_CAP0_DUAL_BAND |
				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
				IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G,
			.phy_cap_info[1] =
				IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
				IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
				IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
				IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_MAX_NSTS,
			.phy_cap_info[2] =
				IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
				IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
				IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
				IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
				IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,

			/* Leave all the other PHY capability bytes unset, as
			 * DCM, beam forming, RU and PPE threshold information
			 * are not supported
			 */
		},
		.he_mcs_nss_supp = {
			.rx_mcs_80 = cpu_to_le16(0xfffa),
			.tx_mcs_80 = cpu_to_le16(0xfffa),
			.rx_mcs_160 = cpu_to_le16(0xfffa),
			.tx_mcs_160 = cpu_to_le16(0xfffa),
			.rx_mcs_80p80 = cpu_to_le16(0xfffa),
			.tx_mcs_80p80 = cpu_to_le16(0xfffa),
		},
	},
};

static void mac80211_hswim_he_capab(struct ieee80211_supported_band *sband)
{
	if (sband->band == NL80211_BAND_2GHZ)
		sband->iftype_data =
			(struct ieee80211_sband_iftype_data *)&he_capa_2ghz;
	else if (sband->band == NL80211_BAND_5GHZ)
		sband->iftype_data =
			(struct ieee80211_sband_iftype_data *)&he_capa_5ghz;
	else
		return;

	sband->n_iftype_data = 1;
}

static int mac80211_hwsim_new_radio(struct genl_info *info,
				    struct hwsim_new_radio_params *param)
{
@@ -2678,6 +2796,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,

	for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
		struct ieee80211_supported_band *sband = &data->bands[band];

		sband->band = band;

		switch (band) {
		case NL80211_BAND_2GHZ:
			sband->channels = data->channels_2ghz;
@@ -2734,6 +2855,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
		sband->ht_cap.mcs.rx_mask[1] = 0xff;
		sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;

		mac80211_hswim_he_capab(sband);

		hw->wiphy->bands[band] = sband;
	}

+1 −1
Original line number Diff line number Diff line
@@ -495,7 +495,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
		goto out_unlock;
	}

	ieee80211_key_free(key, true);
	ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION);

	ret = 0;
 out_unlock:
+15 −9
Original line number Diff line number Diff line
@@ -656,11 +656,15 @@ int ieee80211_key_link(struct ieee80211_key *key,
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_key *old_key;
	int idx, ret;
	bool pairwise;

	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
	idx = key->conf.keyidx;
	int idx = key->conf.keyidx;
	bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
	/*
	 * We want to delay tailroom updates only for station - in that
	 * case it helps roaming speed, but in other cases it hurts and
	 * can cause warnings to appear.
	 */
	bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
	int ret;

	mutex_lock(&sdata->local->key_mtx);

@@ -688,14 +692,14 @@ int ieee80211_key_link(struct ieee80211_key *key,
	increment_tailroom_need_count(sdata);

	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
	ieee80211_key_destroy(old_key, true);
	ieee80211_key_destroy(old_key, delay_tailroom);

	ieee80211_debugfs_key_add(key);

	if (!local->wowlan) {
		ret = ieee80211_key_enable_hw_accel(key);
		if (ret)
			ieee80211_key_free(key, true);
			ieee80211_key_free(key, delay_tailroom);
	} else {
		ret = 0;
	}
@@ -930,7 +934,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
		ieee80211_key_replace(key->sdata, key->sta,
				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				key, NULL);
		__ieee80211_key_destroy(key, true);
		__ieee80211_key_destroy(key, key->sdata->vif.type ==
					NL80211_IFTYPE_STATION);
	}

	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
@@ -940,7 +945,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
		ieee80211_key_replace(key->sdata, key->sta,
				key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
				key, NULL);
		__ieee80211_key_destroy(key, true);
		__ieee80211_key_destroy(key, key->sdata->vif.type ==
					NL80211_IFTYPE_STATION);
	}

	mutex_unlock(&local->key_mtx);
+1 −1
Original line number Diff line number Diff line
@@ -1249,7 +1249,7 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
	    (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
		return NULL;

	if (!ieee80211_is_data(hdr->frame_control))
	if (!ieee80211_is_data_present(hdr->frame_control))
		return NULL;

	if (sta) {
+30 −25
Original line number Diff line number Diff line
@@ -65,9 +65,9 @@ struct lib80211_tkip_data {
	int key_idx;

	struct crypto_skcipher *rx_tfm_arc4;
	struct crypto_ahash *rx_tfm_michael;
	struct crypto_shash *rx_tfm_michael;
	struct crypto_skcipher *tx_tfm_arc4;
	struct crypto_ahash *tx_tfm_michael;
	struct crypto_shash *tx_tfm_michael;

	/* scratch buffers for virt_to_page() (crypto API) */
	u8 rx_hdr[16], tx_hdr[16];
@@ -106,8 +106,7 @@ static void *lib80211_tkip_init(int key_idx)
		goto fail;
	}

	priv->tx_tfm_michael = crypto_alloc_ahash("michael_mic", 0,
						  CRYPTO_ALG_ASYNC);
	priv->tx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
	if (IS_ERR(priv->tx_tfm_michael)) {
		priv->tx_tfm_michael = NULL;
		goto fail;
@@ -120,8 +119,7 @@ static void *lib80211_tkip_init(int key_idx)
		goto fail;
	}

	priv->rx_tfm_michael = crypto_alloc_ahash("michael_mic", 0,
						  CRYPTO_ALG_ASYNC);
	priv->rx_tfm_michael = crypto_alloc_shash("michael_mic", 0, 0);
	if (IS_ERR(priv->rx_tfm_michael)) {
		priv->rx_tfm_michael = NULL;
		goto fail;
@@ -131,9 +129,9 @@ static void *lib80211_tkip_init(int key_idx)

      fail:
	if (priv) {
		crypto_free_ahash(priv->tx_tfm_michael);
		crypto_free_shash(priv->tx_tfm_michael);
		crypto_free_skcipher(priv->tx_tfm_arc4);
		crypto_free_ahash(priv->rx_tfm_michael);
		crypto_free_shash(priv->rx_tfm_michael);
		crypto_free_skcipher(priv->rx_tfm_arc4);
		kfree(priv);
	}
@@ -145,9 +143,9 @@ static void lib80211_tkip_deinit(void *priv)
{
	struct lib80211_tkip_data *_priv = priv;
	if (_priv) {
		crypto_free_ahash(_priv->tx_tfm_michael);
		crypto_free_shash(_priv->tx_tfm_michael);
		crypto_free_skcipher(_priv->tx_tfm_arc4);
		crypto_free_ahash(_priv->rx_tfm_michael);
		crypto_free_shash(_priv->rx_tfm_michael);
		crypto_free_skcipher(_priv->rx_tfm_arc4);
	}
	kfree(priv);
@@ -510,29 +508,36 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
	return keyidx;
}

static int michael_mic(struct crypto_ahash *tfm_michael, u8 * key, u8 * hdr,
static int michael_mic(struct crypto_shash *tfm_michael, u8 *key, u8 *hdr,
		       u8 *data, size_t data_len, u8 *mic)
{
	AHASH_REQUEST_ON_STACK(req, tfm_michael);
	struct scatterlist sg[2];
	SHASH_DESC_ON_STACK(desc, tfm_michael);
	int err;

	if (tfm_michael == NULL) {
		pr_warn("%s(): tfm_michael == NULL\n", __func__);
		return -1;
	}
	sg_init_table(sg, 2);
	sg_set_buf(&sg[0], hdr, 16);
	sg_set_buf(&sg[1], data, data_len);

	if (crypto_ahash_setkey(tfm_michael, key, 8))
	desc->tfm = tfm_michael;
	desc->flags = 0;

	if (crypto_shash_setkey(tfm_michael, key, 8))
		return -1;

	ahash_request_set_tfm(req, tfm_michael);
	ahash_request_set_callback(req, 0, NULL, NULL);
	ahash_request_set_crypt(req, sg, mic, data_len + 16);
	err = crypto_ahash_digest(req);
	ahash_request_zero(req);
	err = crypto_shash_init(desc);
	if (err)
		goto out;
	err = crypto_shash_update(desc, hdr, 16);
	if (err)
		goto out;
	err = crypto_shash_update(desc, data, data_len);
	if (err)
		goto out;
	err = crypto_shash_final(desc, mic);

out:
	shash_desc_zero(desc);
	return err;
}

@@ -654,9 +659,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv)
{
	struct lib80211_tkip_data *tkey = priv;
	int keyidx;
	struct crypto_ahash *tfm = tkey->tx_tfm_michael;
	struct crypto_shash *tfm = tkey->tx_tfm_michael;
	struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4;
	struct crypto_ahash *tfm3 = tkey->rx_tfm_michael;
	struct crypto_shash *tfm3 = tkey->rx_tfm_michael;
	struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4;

	keyidx = tkey->key_idx;