2018-10-17 19:29:31

by James Prestwood

[permalink] [raw]
Subject: [PATCH v2 0/2] Configuring iftype/cipher support

This is V2 of my original patch, but a lot has changed:

- (extended) feature support has been completely removed due to
(extended) features being set in core driver code. There was
no way to set all (extended) features in JUST mac80211_hwsim.

- Iftype support was changed to a bit mask, and checks were added
to ensure only iftypes that mac80211_hwsim already supported
were allowed to be enabled/disabled. The interface limit rules
are now built dynamically rather than being static structures.
This was done because limit verification code complains if you
have a limit rule for an iftype that you do not support.

- A new patch was added to allow supported ciphers to be configured.


James Prestwood (2):
mac80211_hwsim: allow setting iftype support
mac80211_hwsim: allow configurable cipher types

drivers/net/wireless/mac80211_hwsim.c | 218 ++++++++++++++++++--------
drivers/net/wireless/mac80211_hwsim.h | 4 +
2 files changed, 156 insertions(+), 66 deletions(-)

--
2.17.1



2018-10-17 19:29:33

by James Prestwood

[permalink] [raw]
Subject: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

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 than 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 <[email protected]>
---
drivers/net/wireless/mac80211_hwsim.c | 154 +++++++++++++++-----------
drivers/net/wireless/mac80211_hwsim.h | 2 +
2 files changed, 90 insertions(+), 66 deletions(-)

diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 18e819d964f1..2e4dac2de187 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,60 @@ 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.n_limits = n_limits;
+ data->if_combination.max_interfaces = 2048;
+ 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.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 +2668,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 +3245,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, &param);
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)
--
2.17.1


2018-10-17 19:29:33

by James Prestwood

[permalink] [raw]
Subject: [PATCH v2 2/2] mac80211_hwsim: allow configurable cipher types

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 <[email protected]>
---
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 2e4dac2de187..b6b832a41286 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,
@@ -2637,6 +2656,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);
@@ -3184,6 +3210,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 };
@@ -3266,6 +3315,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, &param);
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


2018-10-17 19:39:24

by James Prestwood

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 12:33 -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 than 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 <[email protected]>
> ---
> drivers/net/wireless/mac80211_hwsim.c | 154 +++++++++++++++---------
> --
> drivers/net/wireless/mac80211_hwsim.h | 2 +
> 2 files changed, 90 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/net/wireless/mac80211_hwsim.c
> b/drivers/net/wireless/mac80211_hwsim.c
> index 18e819d964f1..2e4dac2de187 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,60 @@ 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_P
> 2P_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.n_limits = n_limits;
> + data->if_combination.max_interfaces = 2048;
> + data->if_combination.num_different_channels = 1;
> + data->if_combination.radar_detect_widths =
> + BIT(NL80211_CHAN_WIDTH_20_NO
> HT) |
> + BIT(NL80211_CHAN_WIDTH_20) |
> + BIT(NL80211_CHAN_WIDTH_40) |
> + BIT(NL80211_CHAN_WIDTH_80) |
> + BIT(NL80211_CHAN_WIDTH_160);
I just realized this changes how the old code worked. In the
use_chanctx case we want radar_detect_widths to be set to zero and
num_different_channels set to data->channels. These two lines needs to
be surrounded in an if (!data->use_chanctx) block.
> + 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 +2668,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 +3245,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, &param);
> 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)

2018-10-17 19:53:18

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 12:33 -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 than support a limited set of

typo: than -> that

> 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.

That makes me wonder if you'd also want to support limiting the # of
interfaces/channels to mimic another device?

johannes


2018-10-17 20:56:44

by James Prestwood

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 21:53 +0200, Johannes Berg wrote:
> On Wed, 2018-10-17 at 12:33 -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 than support a limited
> > set of
>
> typo: than -> that
>
> > 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.
>
> That makes me wonder if you'd also want to support limiting the # of
> interfaces/channels to mimic another device?

Yeah it seems like it would be pretty easy to add that on top of this
change, although I don't really see us actually using it. I can add it,
but my only concern is I would not test it up to the same level I
tested iftype/ciphers. Maybe this is also because I am not entirely
sure what num_different_channels is doing. Is this only relevant when
multiple interfaces exist on a radio? Like setting how many channels
can be use simultaneously?

>
> johannes
>

2018-10-17 20:59:13

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 14:00 -0700, James Prestwood wrote:
>
> > That makes me wonder if you'd also want to support limiting the # of
> > interfaces/channels to mimic another device?
>
> Yeah it seems like it would be pretty easy to add that on top of this
> change, although I don't really see us actually using it.

Sure, fair enough.

> I can add it,
> but my only concern is I would not test it up to the same level I
> tested iftype/ciphers.

If you don't really want to use it, then I don't think you need to add
it. I was just wondering if it made a difference.

> Maybe this is also because I am not entirely
> sure what num_different_channels is doing. Is this only relevant when
> multiple interfaces exist on a radio? Like setting how many channels
> can be use simultaneously?

Correct. "Simultaneously" is a bit of an overstatement, typically today
it's implemented by TDM - if you have two interfaces with a connection
to an AP each, but on different channels, each interface would just tell
its AP that it's going to sleep, but instead hop to the other channel
and tell that AP that it woke up... etc.

johannes


2018-10-17 21:01:50

by James Prestwood

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 22:58 +0200, Johannes Berg wrote:
> On Wed, 2018-10-17 at 14:00 -0700, James Prestwood wrote:
> >
> > > That makes me wonder if you'd also want to support limiting the #
> > > of
> > > interfaces/channels to mimic another device?
> >
> > Yeah it seems like it would be pretty easy to add that on top of
> > this
> > change, although I don't really see us actually using it.
>
> Sure, fair enough.
>
> > I can add it,
> > but my only concern is I would not test it up to the same level I
> > tested iftype/ciphers.
>
> If you don't really want to use it, then I don't think you need to
> add
> it. I was just wondering if it made a difference.
>
> > Maybe this is also because I am not entirely
> > sure what num_different_channels is doing. Is this only relevant
> > when
> > multiple interfaces exist on a radio? Like setting how many
> > channels
> > can be use simultaneously?
>
> Correct. "Simultaneously" is a bit of an overstatement, typically
> today
> it's implemented by TDM - if you have two interfaces with a
> connection
> to an AP each, but on different channels, each interface would just
> tell
> its AP that it's going to sleep, but instead hop to the other channel
> and tell that AP that it woke up... etc.

Ah ok, that makes sense. Ok, well I can fixup that typo, as well as
reordering the use_chanctx stuff I mentioned. Unless there was anything
else? If not I can submit v3.

>
> johannes
>

2018-10-17 21:08:44

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support


> Ah ok, that makes sense. Ok, well I can fixup that typo, as well as
> reordering the use_chanctx stuff I mentioned. Unless there was anything
> else? If not I can submit v3.

I haven't really looked at it much yet, it's 11pm here and I'm tired :-)

Feel free to resubmit, but I'm not going to promise I won't make you
submit v4 if you do ;-)

johannes


2018-10-17 21:11:47

by James Prestwood

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] mac80211_hwsim: allow setting iftype support

On Wed, 2018-10-17 at 23:08 +0200, Johannes Berg wrote:
> > Ah ok, that makes sense. Ok, well I can fixup that typo, as well as
> > reordering the use_chanctx stuff I mentioned. Unless there was
> > anything
> > else? If not I can submit v3.
>
> I haven't really looked at it much yet, it's 11pm here and I'm tired
> :-)
>
> Feel free to resubmit, but I'm not going to promise I won't make you
> submit v4 if you do ;-)

Ha, ok no problem. Ill submit v3 now.

Thanks,
james

>
> johannes
>