Search Linux Wireless

Re: [PATCH RFC] wifi: cfg80211: Refactor interface combination input parameter

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

 





On 5/7/2024 3:17 PM, Johannes Berg wrote:
On Sat, 2024-04-27 at 08:45 +0530, Karthikeyan Periyasamy wrote:
Currently, the interface combination input parameter num_different_channels
and iftype_num are directly filled in by the caller under the assumption
that all channels and interfaces belong to a single hardware device. This
assumption is incorrect for multi-device interface combinations because
each device supports a different set of channels and interfaces. As
discussed in [1], need to refactor the input parameters to encode enough
data to handle both single and multiple device interface combinations.
This can be achieved by encoding the frequency and interface type under
the interface entity itself. With this new input parameter structure, the
cfg80211 can classify and construct the device parameters, then verify them
against the device specific interface combinations.

...



- * @num_different_channels: the number of different channels we want
- *	to use for verification
   * @radar_detect: a bitmap where each bit corresponds to a channel
   *	width where radar detection is needed, as in the definition of
   *	&struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the number of interfaces of each interface
- *	type.  The index is the interface type as specified in &enum
- *	nl80211_iftype.
   * @new_beacon_int: set this to the beacon interval of a new interface
   *	that's not operating yet, if such is to be checked as part of
   *	the verification
+ * @ifaces: array with the number of interface parameter use for verification
+ * @num_iface: the length of the @ifaces interface parameter
   */
  struct iface_combination_params {
-	int num_different_channels;
  	u8 radar_detect;
-	int iftype_num[NUM_NL80211_IFTYPES];
  	u32 new_beacon_int;
+	const struct iface_combination_interface *ifaces;
+	u16 num_iface;

The "new_beacon_int" also needs to be for a specific link, witha a
specific freq, so you can check for *that* part of the wiphy? Similarly
for radar_detect?

Make sense, will address this comment in the next version.


+	if (iftype != NL80211_IFTYPE_UNSPECIFIED || chandef) {
+		struct iface_combination_interface *iface;
+
+		iface = &ifaces[params.num_iface];
+		iface->iftype = iftype;
+
+		if (chandef && cfg80211_chandef_valid(chandef)) {
+			iface->links[0].freq = chandef->chan->center_freq;
+			iface->num_link++;
  		}

Not sure I understand this.


Previously both channel and interface creation are validated by independent parameter as below

       if (chandef)
               params.num_different_channels = 1;

       if (iftype != NL80211_IFTYPE_UNSPECIFIED)
               params.iftype_num[iftype] = 1;


But in the new input parameter num_different_channels is replace by link specific freq parameter again this is tied within interface entity. So in either of the above scenario, we have to fill interface entity and the link entity is populate only for valid chandef.




@@ -4009,14 +4029,37 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
  					    wdev_iter->iftype, 0, 1))
  			continue;
- params.iftype_num[wdev_iter->iftype]++;
+		iface = &ifaces[params.num_iface];
+		iface->iftype = wdev_iter->iftype;
+
+		rcu_read_lock();
+		for_each_vif_active_link(&sdata_iter->vif, link_conf, link_id) {
+			struct ieee80211_chanctx_conf *chanctx_conf;
+			struct iface_combination_iface_link *link;
+
+			chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
+			if (chanctx_conf &&
+			    cfg80211_chandef_valid(&chanctx_conf->def)) {

Why the valid check, btw? How could that possibly *not* be valid?


Only added for the precaution before accessing "chanctx_conf->def.chan" pointer.

what do you think ?

+				link = &iface->links[iface->num_link];
+				link->freq = chanctx_conf->def.chan->center_freq;
+				iface->num_link++;
+			}
+		}
+		rcu_read_unlock();

when you also have this?

But maybe separating out actual logic changes in mac80211 to a separate
patch would be good.


Previously the concurrent channel populated from chanctx list as below.

        list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
                        continue;
                params.radar_detect |=
                        ieee80211_chanctx_radar_detect(local, ctx);
               if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
                       params.num_different_channels++;
                       continue;
       }

You want to have the below change of populating concurrent channel populate logic from the active links in a separate patch first ?

+               rcu_read_lock();
+ for_each_vif_active_link(&sdata_iter->vif, link_conf, link_id) {
+                       struct ieee80211_chanctx_conf *chanctx_conf;
+                       struct iface_combination_iface_link *link;
+
+ chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
+                       if (chanctx_conf &&
+                           cfg80211_chandef_valid(&chanctx_conf->def)) {
+                               params.num_different_channels++;
+                       }
+               }
+               rcu_read_unlock();


  	list_for_each_entry_rcu(sdata, &local->interfaces, list)
-		params.iftype_num[sdata->wdev.iftype]++;
+		total_iface++;
+
+	if (!total_iface)
+		goto skip;
+
+	ifaces = kcalloc(total_iface, sizeof(*ifaces), GFP_KERNEL);
+	if (!ifaces)
+		return -ENOMEM;
+
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		struct iface_combination_interface *iface;
+
+		if (params.num_iface >= total_iface)
+			continue;
+
+		iface = &ifaces[params.num_iface];
+		iface->iftype = sdata->wdev.iftype;
+
+		rcu_read_lock();
+		for_each_vif_active_link(&sdata->vif, link_conf, link_id) {
+			struct ieee80211_chanctx_conf *chanctx_conf;
+			struct iface_combination_iface_link *link;
+
+			chanctx_conf = rcu_dereference(link_conf->chanctx_conf);
+			if (chanctx_conf &&
+			    cfg80211_chandef_valid(&chanctx_conf->def)) {
+				link = &iface->links[iface->num_link];
+				link->freq = chanctx_conf->def.chan->center_freq;
+				iface->num_link++;
+			}
+		}
+		rcu_read_unlock();
+
+		params.num_iface++;
+	}

Please don't add the same code twice.

Will make a helper function and reuse in the needed area o avoid redundant code.

Will address this comment in the next version.


--
Karthikeyan Periyasamy
--
கார்த்திகேயன் பெரியசாமி




[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