Message ID | 20181017193307.1780-2-james.prestwood@linux.intel.com (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Johannes Berg |
Headers | show |
Series | Configuring iftype/cipher support | expand |
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@linux.intel.com> > --- > 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, ¶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)
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
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
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 >
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 >
> 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
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 >
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, ¶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)
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@linux.intel.com> --- drivers/net/wireless/mac80211_hwsim.c | 154 +++++++++++++++----------- drivers/net/wireless/mac80211_hwsim.h | 2 + 2 files changed, 90 insertions(+), 66 deletions(-)