diff mbox series

nl80211: Add support to configure allowed frequency list for AP operation

Message ID 20230328093105.3640436-1-quic_vjakkam@quicinc.com
State New
Headers show
Series nl80211: Add support to configure allowed frequency list for AP operation | expand

Commit Message

Veerendranath Jakkam March 28, 2023, 9:31 a.m. UTC
Add support to configure the list of allowed 20 MHz channels for AP
operation using an array of channel center frequencies in MHz, this
configuration is valid until the AP is stopped. Driver shall filter out
channels on top of this list of channels based on regulatory or other
constraints during channel switch etc. Driver shall stop the AP
operation if all the channels are filtered out during such operation.

This configuration can be used to specify user's choice of frequencies,
allowed list of channels with static puncturing feature etc.

Signed-off-by: Veerendranath Jakkam <quic_vjakkam@quicinc.com>
---
 include/net/cfg80211.h       | 14 +++++++++++
 include/uapi/linux/nl80211.h | 28 ++++++++++++++++++++++
 net/wireless/nl80211.c       | 45 ++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+)

Comments

Johannes Berg March 28, 2023, 9:42 a.m. UTC | #1
On Tue, 2023-03-28 at 15:01 +0530, Veerendranath Jakkam wrote:
> Add support to configure the list of allowed 20 MHz channels for AP
> operation using an array of channel center frequencies in MHz, this
> configuration is valid until the AP is stopped. Driver shall filter out
> channels on top of this list of channels based on regulatory or other
> constraints during channel switch etc. Driver shall stop the AP
> operation if all the channels are filtered out during such operation.
> 

Normally hostapd is doing anything related to the channel picking, so
you need to explain why this is needed.

Really that's true for _any_ patch, please.

johannes
Jouni Malinen March 30, 2023, 4:30 p.m. UTC | #2
On Tue, Mar 28, 2023 at 11:42:17AM +0200, Johannes Berg wrote:
> On Tue, 2023-03-28 at 15:01 +0530, Veerendranath Jakkam wrote:
> > Add support to configure the list of allowed 20 MHz channels for AP
> > operation using an array of channel center frequencies in MHz, this
> > configuration is valid until the AP is stopped. Driver shall filter out
> > channels on top of this list of channels based on regulatory or other
> > constraints during channel switch etc. Driver shall stop the AP
> > operation if all the channels are filtered out during such operation.
> 
> Normally hostapd is doing anything related to the channel picking, so
> you need to explain why this is needed.

hostapd does this for many cases, but there are drivers, including a
couple of the upstream drivers, that select a channel internally for
channel switch cases. Those would be able to use this information. Is
that of sufficient generic interest or do you prefer vendor commands to
be used for such functionality?
Johannes Berg March 31, 2023, 9:14 a.m. UTC | #3
On Thu, 2023-03-30 at 19:30 +0300, Jouni Malinen wrote:
> On Tue, Mar 28, 2023 at 11:42:17AM +0200, Johannes Berg wrote:
> > On Tue, 2023-03-28 at 15:01 +0530, Veerendranath Jakkam wrote:
> > > Add support to configure the list of allowed 20 MHz channels for AP
> > > operation using an array of channel center frequencies in MHz, this
> > > configuration is valid until the AP is stopped. Driver shall filter out
> > > channels on top of this list of channels based on regulatory or other
> > > constraints during channel switch etc. Driver shall stop the AP
> > > operation if all the channels are filtered out during such operation.
> > 
> > Normally hostapd is doing anything related to the channel picking, so
> > you need to explain why this is needed.
> 
> hostapd does this for many cases, but there are drivers, including a
> couple of the upstream drivers, that select a channel internally for
> channel switch cases. Those would be able to use this information. Is
> that of sufficient generic interest or do you prefer vendor commands to
> be used for such functionality?

Oh, no, I'm entirely happy with this happening in nl80211, it's just the
age-old question again of whether those upstream drivers will ever even
get support for it, or if we end up with more code that effectively
looks dead as far as upstream is concerned :-)

If this actually came with a driver patch using it, the question
wouldn't even arise, since then it's clear why it's needed and what
for...

johannes
Jouni Malinen March 31, 2023, 9:34 a.m. UTC | #4
On Fri, Mar 31, 2023 at 11:14:14AM +0200, Johannes Berg wrote:
> On Thu, 2023-03-30 at 19:30 +0300, Jouni Malinen wrote:
> Oh, no, I'm entirely happy with this happening in nl80211, it's just the
> age-old question again of whether those upstream drivers will ever even
> get support for it, or if we end up with more code that effectively
> looks dead as far as upstream is concerned :-)
> 
> If this actually came with a driver patch using it, the question
> wouldn't even arise, since then it's clear why it's needed and what
> for...

This is one of those cases where the changes seem to be of general
interest, but there is no immediate plans to work on any upstream driver
to use that. As far as the current potentially applicable upstream
drivers are concerned, I would not expect ath6kl to be extended to use
this. I do not really know whether anyone maintaining the drivers for
other vendors would be interested.

This is a balance on what would be the cleanest design (i.e., the most
appropriate nl80211 command for this type of configuration) and
potential help for others vs. what could be done with a somewhat ugly
vendor specific command before the start AP command. Since this specific
case can be handled with a vendor command, I'm not planning on pushing
strongly for this to get accepted into upstream nl80211, but it did seem
to make sense to propose this to see if there would be sufficient
interest for other drivers.
diff mbox series

Patch

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e04f69712b1..062d75709f4f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1359,6 +1359,18 @@  struct cfg80211_unsol_bcast_probe_resp {
  * @punct_bitmap: Preamble puncturing bitmap. Each bit represents
  *	a 20 MHz channel, lowest bit corresponding to the lowest channel.
  *	Bit set to 1 indicates that the channel is punctured.
+ * @allowed_freqs: List of allowed 20 MHz channel center frequencies in MHz for
+ *	the AP operation. The configuration is valid until the AP is stopped.
+ *	Whenever performing a channel selection, the driver shall generate a new
+ *	list based on this provided list by filtering out the channels that
+ *	cannot be used at that time due to regulatory or other constraints. The
+ *	resulting list is used as the list of all allowed channels, i.e.,
+ *	operation on any channel that is not included is not allowed, whenever
+ *	performing operations like ACS and DFS. If all the channels are filtered
+ *	out during such operation driver shall stop the AP operation. Driver
+ *	shall advertise %NL80211_EXT_FEATURE_AP_ALLOWED_FREQ_LIST when it
+ *	supports this configuration.
+ * @num_allowed_freqs: Number of frequencies specified in %allowed_freqs
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -1394,6 +1406,8 @@  struct cfg80211_ap_settings {
 	struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
 	struct cfg80211_mbssid_config mbssid_config;
 	u16 punct_bitmap;
+	u32 *allowed_freqs;
+	int num_allowed_freqs;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index cf4fb981e131..9c9152a6f935 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2805,6 +2805,18 @@  enum nl80211_commands {
  *	index. If the userspace includes more RNR elements than number of
  *	MBSSID elements then these will be added in every EMA beacon.
  *
+ * @NL80211_ATTR_AP_ALLOWED_FREQ_LIST: Nested attribute with frequencies in u32
+ *	attributes. A list of allowed 20 MHz channel center frequencies in MHz
+ *	for AP operation. Used with %NL80211_CMD_START_AP. The configuration is
+ *	valid until the AP is stopped. The drivers shall filter out channels on
+ *	top of this list of channels based on regulatory or other constraints
+ *	during channel switch etc. If all the channels are filtered out during
+ *	such operation, the driver shall stop the AP operation.
+ *	This can be used to specify userspace choice of frequencies, allowed
+ *	list of channels with static puncturing feature etc. This configuration
+ *	allowed only when driver indicates
+ *	%NL80211_EXT_FEATURE_AP_ALLOWED_FREQ_LIST.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3341,6 +3353,8 @@  enum nl80211_attrs {
 
 	NL80211_ATTR_EMA_RNR_ELEMS,
 
+	NL80211_ATTR_AP_ALLOWED_FREQ_LIST,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -6365,6 +6379,19 @@  enum nl80211_feature_flags {
  *	in authentication and deauthentication frames sent to unassociated peer
  *	using @NL80211_CMD_FRAME.
  *
+ * @NL80211_EXT_FEATURE_AP_ALLOWED_FREQ_LIST: Driver supports configuring
+ *	allowed frequency list for AP operation in %NL80211_CMD_START_AP with
+ *	%NL80211_ATTR_AP_ALLOWED_FREQ_LIST from userspace. When driver indicates
+ *	this and userspace sends %NL80211_ATTR_AP_ALLOWED_FREQ_LIST in
+ *	%NL80211_CMD_START_AP, driver shall generate a new list based on the
+ *	provided list in %NL80211_ATTR_AP_ALLOWED_FREQ_LIST by filtering out the
+ *	channels that can't be used at that time due to regulatory or other
+ *	constraints. The resulting list is used as the list of all allowed
+ *	channels, i.e., operation on any channel that is not included is not
+ *	allowed, whenever performing operations like ACS and DFS. If all the
+ *	channels are filtered out during such operation driver shall stop the AP
+ *	operation.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -6436,6 +6463,7 @@  enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_PUNCT,
 	NL80211_EXT_FEATURE_SECURE_NAN,
 	NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA,
+	NL80211_EXT_FEATURE_AP_ALLOWED_FREQ_LIST,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f1cd3d9130dd..65576d8ccb82 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -810,6 +810,7 @@  static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS] = { .type = NLA_U16 },
 	[NL80211_ATTR_HW_TIMESTAMP_ENABLED] = { .type = NLA_FLAG },
 	[NL80211_ATTR_EMA_RNR_ELEMS] = { .type = NLA_NESTED },
+	[NL80211_ATTR_AP_ALLOWED_FREQ_LIST] = { .type = NLA_NESTED },
 };
 
 /* policy for the key attributes */
@@ -5886,6 +5887,35 @@  static void nl80211_send_ap_started(struct wireless_dev *wdev,
 	nlmsg_free(msg);
 }
 
+static int parse_ap_allowed_freq_list(struct nlattr *freq_list,
+				      struct cfg80211_ap_settings *params)
+{
+	struct nlattr *attr;
+	int tmp;
+	int n_freqs = 0;
+
+	nla_for_each_nested(attr, freq_list, tmp) {
+		if (nla_len(attr) != sizeof(u32))
+			return -EINVAL;
+
+		n_freqs++;
+	}
+
+	if (!n_freqs)
+		return -EINVAL;
+
+	params->allowed_freqs = kcalloc(n_freqs, sizeof(*params->allowed_freqs),
+					GFP_KERNEL);
+	if (!params->allowed_freqs)
+		return -ENOMEM;
+
+	nla_for_each_nested(attr, freq_list, tmp)
+		params->allowed_freqs[params->num_allowed_freqs++] =
+				nla_get_u32(attr);
+
+	return 0;
+}
+
 static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 {
 	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -6049,6 +6079,20 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		goto out;
 	}
 
+	if (info->attrs[NL80211_ATTR_AP_ALLOWED_FREQ_LIST]) {
+		if (!wiphy_ext_feature_isset(&rdev->wiphy,
+				NL80211_EXT_FEATURE_AP_ALLOWED_FREQ_LIST)) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
+
+		err = parse_ap_allowed_freq_list(
+				info->attrs[NL80211_ATTR_AP_ALLOWED_FREQ_LIST],
+				params);
+		if (err)
+			goto out;
+	}
+
 	wdev_lock(wdev);
 
 	if (info->attrs[NL80211_ATTR_TX_RATES]) {
@@ -6187,6 +6231,7 @@  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 	wdev_unlock(wdev);
 out:
 	kfree(params->acl);
+	kfree(params->allowed_freqs);
 	kfree(params->beacon.mbssid_ies);
 	if (params->mbssid_config.tx_wdev &&
 	    params->mbssid_config.tx_wdev->netdev &&