* [PATCH v3 2/2] mac80211_hwsim: allow configurable cipher types
[not found] <20181017211624.7338-1-james.prestwood@linux.intel.com>
@ 2018-10-17 21:16 ` James Prestwood
2018-10-25 17:50 ` [PATCH v3 1/2] mac80211_hwsim: allow setting iftype support James Prestwood
1 sibling, 0 replies; 2+ messages in thread
From: James Prestwood @ 2018-10-17 21:16 UTC (permalink / raw)
To: linux-wireless; +Cc: James Prestwood
The mac80211_hwsim driver does not specify supported cipher types, which
in turn enables all ciphers to be supported in software. (see
net/mac80211/main.c:ieee80211_init_cipher_suites). Allowing ciphers
to be configurable is valuable for simulating older drivers that may
not support all ciphers.
This patch adds a new attribute:
- HWSIM_ATTR_CIPHER_SUPPORT
A u32 array/list of supported cipher types
This only allows enabling/disabling cipher types listed in the (new)
"hwsim_ciphers" array in mac80211_hwsim.c. Any unknown cipher type
will result in -EINVAL.
Signed-off-by: James Prestwood <james.prestwood@linux.intel.com>
---
drivers/net/wireless/mac80211_hwsim.c | 64 +++++++++++++++++++++++++++
drivers/net/wireless/mac80211_hwsim.h | 2 +
2 files changed, 66 insertions(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 2799eb247b7e..69596eb255d7 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -371,6 +371,20 @@ static const struct ieee80211_rate hwsim_rates[] = {
{ .bitrate = 540 }
};
+static const u32 hwsim_ciphers[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_CCMP_256,
+ WLAN_CIPHER_SUITE_GCMP,
+ WLAN_CIPHER_SUITE_GCMP_256,
+ WLAN_CIPHER_SUITE_AES_CMAC,
+ WLAN_CIPHER_SUITE_BIP_CMAC_256,
+ WLAN_CIPHER_SUITE_BIP_GMAC_128,
+ WLAN_CIPHER_SUITE_BIP_GMAC_256,
+};
+
#define OUI_QCA 0x001374
#define QCA_NL80211_SUBCMD_TEST 1
enum qca_nl80211_vendor_subcmds {
@@ -474,6 +488,8 @@ struct mac80211_hwsim_data {
struct ieee80211_iface_limit if_limits[3];
int n_if_limits;
+ u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
+
struct mac_address addresses[2];
int channels, idx;
bool use_chanctx;
@@ -602,6 +618,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
[HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
[HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN },
[HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 },
+ [HWSIM_ATTR_CIPHER_SUPPORT] = { .type = NLA_BINARY },
};
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
@@ -2375,6 +2392,8 @@ struct hwsim_new_radio_params {
bool no_vif;
const u8 *perm_addr;
u32 iftypes;
+ u32 *ciphers;
+ u8 n_ciphers;
};
static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
@@ -2638,6 +2657,13 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
hw->wiphy->iface_combinations = &data->if_combination;
hw->wiphy->n_iface_combinations = 1;
+ if (param->ciphers) {
+ memcpy(data->ciphers, param->ciphers,
+ param->n_ciphers * sizeof(u32));
+ hw->wiphy->cipher_suites = data->ciphers;
+ hw->wiphy->n_cipher_suites = param->n_ciphers;
+ }
+
INIT_DELAYED_WORK(&data->roc_start, hw_roc_start);
INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
@@ -3185,6 +3211,29 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2,
return 0;
}
+/* ensures ciphers only include ciphers listed in 'hwsim_ciphers' array */
+static int hwsim_validate_ciphers(const u32 *ciphers, int n_ciphers)
+{
+ int i;
+
+ for (i = 0; i < n_ciphers; i++) {
+ int j;
+ int found = 0;
+
+ for (j = 0; j < ARRAY_SIZE(hwsim_ciphers); j++) {
+ if (ciphers[i] == hwsim_ciphers[j]) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ return -1;
+ }
+
+ return 0;
+}
+
static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
struct hwsim_new_radio_params param = { 0 };
@@ -3267,6 +3316,21 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
param.p2p_device = true;
}
+ if (info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]) {
+ param.ciphers = nla_data(
+ info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]);
+ param.n_ciphers = nla_len(
+ info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]);
+
+ if (param.n_ciphers > sizeof(hwsim_ciphers))
+ return -EINVAL;
+
+ param.n_ciphers /= sizeof(u32);
+
+ if (hwsim_validate_ciphers(param.ciphers, param.n_ciphers))
+ return -EINVAL;
+ }
+
ret = mac80211_hwsim_new_radio(info, ¶m);
kfree(hwname);
return ret;
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index 3f6b670116d0..a1ef8457fad4 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -133,6 +133,7 @@ enum {
* rates of %HWSIM_ATTR_TX_INFO
* @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
* @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface types bits
+ * @HWSIM_ATTR_CIPHER_SUPPORT: u32 array of supported cipher types
* @__HWSIM_ATTR_MAX: enum limit
*/
@@ -162,6 +163,7 @@ enum {
HWSIM_ATTR_TX_INFO_FLAGS,
HWSIM_ATTR_PERM_ADDR,
HWSIM_ATTR_IFTYPE_SUPPORT,
+ HWSIM_ATTR_CIPHER_SUPPORT,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
--
2.17.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v3 1/2] mac80211_hwsim: allow setting iftype support
[not found] <20181017211624.7338-1-james.prestwood@linux.intel.com>
2018-10-17 21:16 ` [PATCH v3 2/2] mac80211_hwsim: allow configurable cipher types James Prestwood
@ 2018-10-25 17:50 ` James Prestwood
1 sibling, 0 replies; 2+ messages in thread
From: James Prestwood @ 2018-10-25 17:50 UTC (permalink / raw)
To: linux-wireless
Johannes,
Ping
On Wed, 2018-10-17 at 14:16 -0700, James Prestwood wrote:
> The mac80211_hwsim driver hard codes its supported interface types.
> For
> testing purposes it would be valuable to allow changing these
> supported
> types in order to simulate actual drivers that support a limited set
> of
> iftypes. A new attribute was added to allow this:
>
> - HWSIM_ATTR_IFTYPE_SUPPORT
> A u32 bit field of supported NL80211_IFTYPE_* bits
>
> This will only enable/disable iftypes that mac80211_hwsim already
> supports.
>
> In order to accomplish this, the ieee80211_iface_limit structure
> needed
> to be built dynamically to only include limit rules for iftypes that
> the user requested to enable.
>
> Signed-off-by: James Prestwood <james.prestwood@linux.intel.com>
> ---
> drivers/net/wireless/mac80211_hwsim.c | 153 +++++++++++++++---------
> --
> drivers/net/wireless/mac80211_hwsim.h | 2 +
> 2 files changed, 90 insertions(+), 65 deletions(-)
>
> diff --git a/drivers/net/wireless/mac80211_hwsim.c
> b/drivers/net/wireless/mac80211_hwsim.c
> index 18e819d964f1..2799eb247b7e 100644
> --- a/drivers/net/wireless/mac80211_hwsim.c
> +++ b/drivers/net/wireless/mac80211_hwsim.c
> @@ -448,48 +448,6 @@ static const struct nl80211_vendor_cmd_info
> mac80211_hwsim_vendor_events[] = {
> { .vendor_id = OUI_QCA, .subcmd = 1 },
> };
>
> -static const struct ieee80211_iface_limit hwsim_if_limits[] = {
> - { .max = 1, .types = BIT(NL80211_IFTYPE_ADHOC) },
> - { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
> - BIT(NL80211_IFTYPE_P2P_CLIENT) |
> -#ifdef CONFIG_MAC80211_MESH
> - BIT(NL80211_IFTYPE_MESH_POINT) |
> -#endif
> - BIT(NL80211_IFTYPE_AP) |
> - BIT(NL80211_IFTYPE_P2P_GO) },
> - /* must be last, see hwsim_if_comb */
> - { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) }
> -};
> -
> -static const struct ieee80211_iface_combination hwsim_if_comb[] = {
> - {
> - .limits = hwsim_if_limits,
> - /* remove the last entry which is P2P_DEVICE */
> - .n_limits = ARRAY_SIZE(hwsim_if_limits) - 1,
> - .max_interfaces = 2048,
> - .num_different_channels = 1,
> - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT)
> |
> - BIT(NL80211_CHAN_WIDTH_20) |
> - BIT(NL80211_CHAN_WIDTH_40) |
> - BIT(NL80211_CHAN_WIDTH_80) |
> - BIT(NL80211_CHAN_WIDTH_160),
> - },
> -};
> -
> -static const struct ieee80211_iface_combination
> hwsim_if_comb_p2p_dev[] = {
> - {
> - .limits = hwsim_if_limits,
> - .n_limits = ARRAY_SIZE(hwsim_if_limits),
> - .max_interfaces = 2048,
> - .num_different_channels = 1,
> - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT)
> |
> - BIT(NL80211_CHAN_WIDTH_20) |
> - BIT(NL80211_CHAN_WIDTH_40) |
> - BIT(NL80211_CHAN_WIDTH_80) |
> - BIT(NL80211_CHAN_WIDTH_160),
> - },
> -};
> -
> static spinlock_t hwsim_radio_lock;
> static LIST_HEAD(hwsim_radios);
> static struct workqueue_struct *hwsim_wq;
> @@ -513,6 +471,8 @@ struct mac80211_hwsim_data {
> struct ieee80211_channel
> channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)];
> struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)];
> struct ieee80211_iface_combination if_combination;
> + struct ieee80211_iface_limit if_limits[3];
> + int n_if_limits;
>
> struct mac_address addresses[2];
> int channels, idx;
> @@ -641,6 +601,7 @@ static const struct nla_policy
> hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
> [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG },
> [HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
> [HWSIM_ATTR_PERM_ADDR] = { .type = NLA_UNSPEC, .len = ETH_ALEN
> },
> + [HWSIM_ATTR_IFTYPE_SUPPORT] = { .type = NLA_U32 },
> };
>
> static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
> @@ -2413,6 +2374,7 @@ struct hwsim_new_radio_params {
> const char *hwname;
> bool no_vif;
> const u8 *perm_addr;
> + u32 iftypes;
> };
>
> static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
> @@ -2517,6 +2479,29 @@ static void hwsim_mcast_new_radio(int id,
> struct genl_info *info,
> nlmsg_free(mcast_skb);
> }
>
> +#ifdef CONFIG_MAC80211_MESH
> +#define HWSIM_MESH_BIT BIT(NL80211_IFTYPE_MESH_POINT)
> +#else
> +#define HWSIM_MESH_BIT 0
> +#endif
> +
> +#define HWSIM_DEFAULT_IF_LIMIT \
> + ( \
> + BIT(NL80211_IFTYPE_STATION) | \
> + BIT(NL80211_IFTYPE_P2P_CLIENT) | \
> + BIT(NL80211_IFTYPE_AP) | \
> + BIT(NL80211_IFTYPE_P2P_GO) | \
> + HWSIM_MESH_BIT \
> + )
> +
> +#define HWSIM_IFTYPE_SUPPORT_MASK \
> + BIT(NL80211_IFTYPE_STATION) | \
> + BIT(NL80211_IFTYPE_AP) | \
> + BIT(NL80211_IFTYPE_P2P_CLIENT) | \
> + BIT(NL80211_IFTYPE_P2P_GO) | \
> + BIT(NL80211_IFTYPE_ADHOC) | \
> + BIT(NL80211_IFTYPE_MESH_POINT)
> +
> static int mac80211_hwsim_new_radio(struct genl_info *info,
> struct hwsim_new_radio_params
> *param)
> {
> @@ -2528,6 +2513,7 @@ static int mac80211_hwsim_new_radio(struct
> genl_info *info,
> const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
> struct net *net;
> int idx;
> + int n_limits = 0;
>
> if (WARN_ON(param->channels > 1 && !param->use_chanctx))
> return -EINVAL;
> @@ -2603,43 +2589,61 @@ static int mac80211_hwsim_new_radio(struct
> genl_info *info,
> if (info)
> data->portid = info->snd_portid;
>
> + /* setup interface limits, only on interface types we support
> */
> + if (param->iftypes & BIT(NL80211_IFTYPE_ADHOC)) {
> + data->if_limits[n_limits].max = 1;
> + data->if_limits[n_limits].types =
> BIT(NL80211_IFTYPE_ADHOC);
> + n_limits++;
> + }
> +
> + if (param->iftypes & HWSIM_DEFAULT_IF_LIMIT) {
> + data->if_limits[n_limits].max = 2048;
> + /*
> + * For this case, we may only support a subset of
> + * HWSIM_DEFAULT_IF_LIMIT, therefore we only want to
> add the
> + * bits that both param->iftype &
> HWSIM_DEFAULT_IF_LIMIT have.
> + */
> + data->if_limits[n_limits].types =
> + HWSIM_DEFAULT_IF_LIMIT & param-
> >iftypes;
> + n_limits++;
> + }
> +
> + if (param->iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE)) {
> + data->if_limits[n_limits].max = 1;
> + data->if_limits[n_limits].types =
> + BIT(NL80211_IFTYPE_P2P_
> DEVICE);
> + n_limits++;
> + }
> +
> if (data->use_chanctx) {
> hw->wiphy->max_scan_ssids = 255;
> hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
> hw->wiphy->max_remain_on_channel_duration = 1000;
> - hw->wiphy->iface_combinations = &data->if_combination;
> - if (param->p2p_device)
> - data->if_combination =
> hwsim_if_comb_p2p_dev[0];
> - else
> - data->if_combination = hwsim_if_comb[0];
> - hw->wiphy->n_iface_combinations = 1;
> - /* For channels > 1 DFS is not allowed */
> data->if_combination.radar_detect_widths = 0;
> data->if_combination.num_different_channels = data-
> >channels;
> - } else if (param->p2p_device) {
> - hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
> - hw->wiphy->n_iface_combinations =
> - ARRAY_SIZE(hwsim_if_comb_p2p_dev);
> } else {
> - hw->wiphy->iface_combinations = hwsim_if_comb;
> - hw->wiphy->n_iface_combinations =
> ARRAY_SIZE(hwsim_if_comb);
> + data->if_combination.num_different_channels = 1;
> + data->if_combination.radar_detect_widths =
> + BIT(NL80211_CHAN_WIDTH_20_NOHT)
> |
> + BIT(NL80211_CHAN_WIDTH_20) |
> + BIT(NL80211_CHAN_WIDTH_40) |
> + BIT(NL80211_CHAN_WIDTH_80) |
> + BIT(NL80211_CHAN_WIDTH_160);
> }
>
> + data->if_combination.n_limits = n_limits;
> + data->if_combination.max_interfaces = 2048;
> + data->if_combination.limits = data->if_limits;
> +
> + hw->wiphy->iface_combinations = &data->if_combination;
> + hw->wiphy->n_iface_combinations = 1;
> +
> INIT_DELAYED_WORK(&data->roc_start, hw_roc_start);
> INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
> INIT_DELAYED_WORK(&data->hw_scan, hw_scan_work);
>
> hw->queues = 5;
> hw->offchannel_tx_hw_queue = 4;
> - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
> - BIT(NL80211_IFTYPE_AP) |
> - BIT(NL80211_IFTYPE_P2P_CLIENT) |
> - BIT(NL80211_IFTYPE_P2P_GO) |
> - BIT(NL80211_IFTYPE_ADHOC) |
> - BIT(NL80211_IFTYPE_MESH_POINT);
> -
> - if (param->p2p_device)
> - hw->wiphy->interface_modes |=
> BIT(NL80211_IFTYPE_P2P_DEVICE);
>
> ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
> ieee80211_hw_set(hw, CHANCTX_STA_CSA);
> @@ -2665,6 +2669,8 @@ static int mac80211_hwsim_new_radio(struct
> genl_info *info,
> NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
> wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
>
> + hw->wiphy->interface_modes = param->iftypes;
> +
> /* ask mac80211 to reserve space for magic */
> hw->vif_data_size = sizeof(struct hwsim_vif_priv);
> hw->sta_data_size = sizeof(struct hwsim_sta_priv);
> @@ -3240,10 +3246,27 @@ static int hwsim_new_radio_nl(struct sk_buff
> *msg, struct genl_info *info)
> return -EINVAL;
> }
>
> -
> param.perm_addr = nla_data(info-
> >attrs[HWSIM_ATTR_PERM_ADDR]);
> }
>
> + if (info->attrs[HWSIM_ATTR_IFTYPE_SUPPORT]) {
> + param.iftypes = nla_get_u32(
> + info-
> >attrs[HWSIM_ATTR_IFTYPE_SUPPORT]);
> + if (param.iftypes & ~(HWSIM_IFTYPE_SUPPORT_MASK)) {
> + NL_SET_BAD_ATTR(info->extack,
> + info-
> >attrs[HWSIM_ATTR_IFTYPE_SUPPORT]);
> + return -EINVAL;
> + }
> + } else
> + param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
> +
> + /* ensure both flag and iftype support is honored */
> + if (param.p2p_device ||
> + param.iftypes & BIT(NL80211_IFTYPE_P2P_DEVICE))
> {
> + param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
> + param.p2p_device = true;
> + }
> +
> ret = mac80211_hwsim_new_radio(info, ¶m);
> kfree(hwname);
> return ret;
> diff --git a/drivers/net/wireless/mac80211_hwsim.h
> b/drivers/net/wireless/mac80211_hwsim.h
> index 0fe3199f8c72..3f6b670116d0 100644
> --- a/drivers/net/wireless/mac80211_hwsim.h
> +++ b/drivers/net/wireless/mac80211_hwsim.h
> @@ -132,6 +132,7 @@ enum {
> * @HWSIM_ATTR_TX_INFO_FLAGS: additional flags for corresponding
> * rates of %HWSIM_ATTR_TX_INFO
> * @HWSIM_ATTR_PERM_ADDR: permanent mac address of new radio
> + * @HWSIM_ATTR_IFTYPE_SUPPORT: u32 attribute of supported interface
> types bits
> * @__HWSIM_ATTR_MAX: enum limit
> */
>
> @@ -160,6 +161,7 @@ enum {
> HWSIM_ATTR_PAD,
> HWSIM_ATTR_TX_INFO_FLAGS,
> HWSIM_ATTR_PERM_ADDR,
> + HWSIM_ATTR_IFTYPE_SUPPORT,
> __HWSIM_ATTR_MAX,
> };
> #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
^ permalink raw reply [flat|nested] 2+ messages in thread