wifi: mac80211_hwsim: add support for multi-radio wiphy
authorFelix Fietkau <nbd@nbd.name>
Tue, 9 Jul 2024 08:38:38 +0000 (10:38 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 9 Jul 2024 09:36:12 +0000 (11:36 +0200)
This registers one wiphy radio per supported band. Number of different
channels is set per radio.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/3a16838bb7a7d1a072bd7c9d586d17f70fcd8a60.1720514221.git-series.nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/virtual/mac80211_hwsim.c
drivers/net/wireless/virtual/mac80211_hwsim.h

index d60c780d4e8a472593e748931e4382570229d294..714e1f04b0cb39990b503a057520ca5354a6b069 100644 (file)
@@ -69,6 +69,10 @@ static bool mlo;
 module_param(mlo, bool, 0444);
 MODULE_PARM_DESC(mlo, "Support MLO");
 
+static bool multi_radio;
+module_param(multi_radio, bool, 0444);
+MODULE_PARM_DESC(mlo, "Support Multiple Radios per wiphy");
+
 /**
  * enum hwsim_regtest - the type of regulatory tests we offer
  *
@@ -669,6 +673,10 @@ struct mac80211_hwsim_data {
        struct ieee80211_iface_limit if_limits[3];
        int n_if_limits;
 
+       struct ieee80211_iface_combination if_combination_radio;
+       struct wiphy_radio_freq_range radio_range[NUM_NL80211_BANDS];
+       struct wiphy_radio radio[NUM_NL80211_BANDS];
+
        u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
 
        struct mac_address addresses[2];
@@ -917,6 +925,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
        [HWSIM_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
        [HWSIM_ATTR_PMSR_SUPPORT] = NLA_POLICY_NESTED(hwsim_pmsr_capa_policy),
        [HWSIM_ATTR_PMSR_RESULT] = NLA_POLICY_NESTED(hwsim_pmsr_peers_result_policy),
+       [HWSIM_ATTR_MULTI_RADIO] = { .type = NLA_FLAG },
 };
 
 #if IS_REACHABLE(CONFIG_VIRTIO)
@@ -4018,6 +4027,7 @@ struct hwsim_new_radio_params {
        bool reg_strict;
        bool p2p_device;
        bool use_chanctx;
+       bool multi_radio;
        bool destroy_on_close;
        const char *hwname;
        bool no_vif;
@@ -4094,6 +4104,12 @@ static int append_radio_msg(struct sk_buff *skb, int id,
                        return ret;
        }
 
+       if (param->multi_radio) {
+               ret = nla_put_flag(skb, HWSIM_ATTR_MULTI_RADIO);
+               if (ret < 0)
+                       return ret;
+       }
+
        if (param->hwname) {
                ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME,
                              strlen(param->hwname), param->hwname);
@@ -5114,6 +5130,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
        struct net *net;
        int idx, i;
        int n_limits = 0;
+       int n_bands = 0;
 
        if (WARN_ON(param->channels > 1 && !param->use_chanctx))
                return -EINVAL;
@@ -5217,22 +5234,22 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                n_limits++;
        }
 
+       data->if_combination.radar_detect_widths =
+                               BIT(NL80211_CHAN_WIDTH_5) |
+                               BIT(NL80211_CHAN_WIDTH_10) |
+                               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);
+
        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;
-               data->if_combination.radar_detect_widths = 0;
                data->if_combination.num_different_channels = data->channels;
        } else {
                data->if_combination.num_different_channels = 1;
-               data->if_combination.radar_detect_widths =
-                                       BIT(NL80211_CHAN_WIDTH_5) |
-                                       BIT(NL80211_CHAN_WIDTH_10) |
-                                       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);
        }
 
        if (!n_limits) {
@@ -5350,6 +5367,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];
+               struct wiphy_radio_freq_range *radio_range;
+               const struct ieee80211_channel *c;
+               struct wiphy_radio *radio;
 
                sband->band = band;
 
@@ -5423,8 +5443,36 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                mac80211_hwsim_sband_capab(sband);
 
                hw->wiphy->bands[band] = sband;
+
+               if (!param->multi_radio)
+                       continue;
+
+               c = sband->channels;
+               radio_range = &data->radio_range[n_bands];
+               radio_range->start_freq = ieee80211_channel_to_khz(c) - 10000;
+
+               c += sband->n_channels - 1;
+               radio_range->end_freq = ieee80211_channel_to_khz(c) + 10000;
+
+               radio = &data->radio[n_bands++];
+               radio->freq_range = radio_range;
+               radio->n_freq_range = 1;
+               radio->iface_combinations = &data->if_combination_radio;
+               radio->n_iface_combinations = 1;
        }
 
+       if (param->multi_radio) {
+               hw->wiphy->radio = data->radio;
+               hw->wiphy->n_radio = n_bands;
+
+               memcpy(&data->if_combination_radio, &data->if_combination,
+                      sizeof(data->if_combination));
+               data->if_combination.num_different_channels *= n_bands;
+       }
+
+       if (data->use_chanctx)
+               data->if_combination.radar_detect_widths = 0;
+
        /* By default all radios belong to the first group */
        data->group = 1;
        mutex_init(&data->mutex);
@@ -6042,6 +6090,9 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
        else
                param.use_chanctx = (param.channels > 1);
 
+       if (info->attrs[HWSIM_ATTR_MULTI_RADIO])
+               param.multi_radio = true;
+
        if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2])
                param.reg_alpha2 =
                        nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
@@ -6122,7 +6173,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
 
        param.mlo = info->attrs[HWSIM_ATTR_MLO_SUPPORT];
 
-       if (param.mlo)
+       if (param.mlo || param.multi_radio)
                param.use_chanctx = true;
 
        if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
@@ -6815,7 +6866,8 @@ static int __init init_mac80211_hwsim(void)
 
                param.p2p_device = support_p2p_device;
                param.mlo = mlo;
-               param.use_chanctx = channels > 1 || mlo;
+               param.multi_radio = multi_radio;
+               param.use_chanctx = channels > 1 || mlo || multi_radio;
                param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
                if (param.p2p_device)
                        param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
index 28c1db482e793114855f00a285611e8cb46bc1c7..f32fc3a492b068f31d49a8efc16ef68ebdb7a888 100644 (file)
@@ -157,6 +157,9 @@ enum hwsim_commands {
  *     to provide details about peer measurement request (nl80211_peer_measurement_attrs)
  * @HWSIM_ATTR_PMSR_RESULT: nested attributed used with %HWSIM_CMD_REPORT_PMSR
  *     to provide peer measurement result (nl80211_peer_measurement_attrs)
+ * @HWSIM_ATTR_MULTI_RADIO: Register multiple wiphy radios (flag).
+ *     Adds one radio for each band. Number of supported channels will be set for
+ *     each radio instead of for the wiphy.
  * @__HWSIM_ATTR_MAX: enum limit
  */
 enum hwsim_attrs {
@@ -189,6 +192,7 @@ enum hwsim_attrs {
        HWSIM_ATTR_PMSR_SUPPORT,
        HWSIM_ATTR_PMSR_REQUEST,
        HWSIM_ATTR_PMSR_RESULT,
+       HWSIM_ATTR_MULTI_RADIO,
        __HWSIM_ATTR_MAX,
 };
 #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)