Search Linux Wireless

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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 <james.prestwood@xxxxxxxxxxxxxxx>
> ---
>  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)



[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux