diff mbox

[5/5] cfg80211: Allow usermode to query wiphy specific regd info

Message ID 1414046257-22184-6-git-send-email-arik@wizery.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Arik Nemtsov Oct. 23, 2014, 6:37 a.m. UTC
From: Jonathan Doron <jond@wizery.com>

Allow usermode to query wiphy-specific regd info, for drivers that use
wiphy-specific regulatory management.

Use the existing API for sending regdomain info to usermode, but return
the wiphy-specific regd in case wiphy index is provided and the driver
employs wiphy-specific management. This implies user and kernel-mode
support for the feature and is backward compatible.

Signed-off-by: Jonathan Doron <jonathanx.doron@intel.com>
Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
---
 include/uapi/linux/nl80211.h |  6 +++++
 net/wireless/nl80211.c       | 54 +++++++++++++++++++++++++++++++++++---------
 net/wireless/reg.c           |  2 +-
 net/wireless/reg.h           |  1 +
 4 files changed, 51 insertions(+), 12 deletions(-)

Comments

Luis R. Rodriguez Nov. 5, 2014, 3:23 a.m. UTC | #1
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <arik@wizery.com> wrote:
> + * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating the
> + *     regulatory information came from the driver and not from the global
> + *     cfg80211 regulatory domain information.

Awesome, can you also add another entry for those drivers that use
regulatory_hint() API given that the wiphy->regd will be set and then
that is a custom regdomain which I do think would be great to query as
well.

 Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arik Nemtsov Nov. 5, 2014, 9:12 a.m. UTC | #2
On Wed, Nov 5, 2014 at 5:23 AM, Luis R. Rodriguez
<mcgrof@do-not-panic.com> wrote:
> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <arik@wizery.com> wrote:
>> + * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating the
>> + *     regulatory information came from the driver and not from the global
>> + *     cfg80211 regulatory domain information.
>
> Awesome, can you also add another entry for those drivers that use
> regulatory_hint() API given that the wiphy->regd will be set and then
> that is a custom regdomain which I do think would be great to query as
> well.

Just to be sure we're on the same page.
1. You're asking for an attribute to be automatically sent to
userspace whenever someone registers with REGULATORY_CUSTOM_REG.
2. And then if userspace sends a wiphy idx to the NL80211_CMD_GET_REG,
we'll return wiphy->regd for that case as well?

Arik
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Luis R. Rodriguez Nov. 12, 2014, 10:51 p.m. UTC | #3
On Wed, Nov 5, 2014 at 1:12 AM, Arik Nemtsov <arik@wizery.com> wrote:
> On Wed, Nov 5, 2014 at 5:23 AM, Luis R. Rodriguez
> <mcgrof@do-not-panic.com> wrote:
>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <arik@wizery.com> wrote:
>>> + * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating the
>>> + *     regulatory information came from the driver and not from the global
>>> + *     cfg80211 regulatory domain information.
>>
>> Awesome, can you also add another entry for those drivers that use
>> regulatory_hint() API given that the wiphy->regd will be set and then
>> that is a custom regdomain which I do think would be great to query as
>> well.
>
> Just to be sure we're on the same page.
> 1. You're asking for an attribute to be automatically sent to
> userspace whenever someone registers with REGULATORY_CUSTOM_REG.

Right now if REGULATORY_CUSTOM_REG is set you are expected to use
wiphy_apply_custom_regulatory() and the regd is not cached, instead we
rely on the orgi parameters to ensure that data is used as that
maximum set. These data structures are already part of the kernel so I
don't think its necessary to send them to userspace right now but
specially since it'd mean adding a new data structure and caching it
completely. That's possible but I was more looking for users of
regulatory_hint(), when that is used the wiphy->regd is set and so its
available and cached already.

> 2. And then if userspace sends a wiphy idx to the NL80211_CMD_GET_REG,
> we'll return wiphy->regd for that case as well?

That's right, for now we'd be able to send the regd when either
NL80211_ATTR_WIPHY_SELF_MANAGED_REG is set or when
NL80211_ATTR_WIPHY_SELF_MANAGED_REG is not set but regulatory_hint()
was used. Note that some users may have REGULATORY_CUSTOM_REG. and
then later use regulatory_hint(), this is done to for example set a
more restrictive custom world regdomain and then later use the CRDA
data for a specific alpha2.

 Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arik Nemtsov Nov. 13, 2014, 3:55 p.m. UTC | #4
>
>> 2. And then if userspace sends a wiphy idx to the NL80211_CMD_GET_REG,
>> we'll return wiphy->regd for that case as well?
>
> That's right, for now we'd be able to send the regd when either
> NL80211_ATTR_WIPHY_SELF_MANAGED_REG is set or when
> NL80211_ATTR_WIPHY_SELF_MANAGED_REG is not set but regulatory_hint()
> was used. Note that some users may have REGULATORY_CUSTOM_REG. and
> then later use regulatory_hint(), this is done to for example set a
> more restrictive custom world regdomain and then later use the CRDA
> data for a specific alpha2.

Well always sending wiphy->regd whenever it is set is easy, but it
might be problematic I guess:

We intend to add a patch to wpa_s to always add the wiphy_idx to
NL80211_CMD_GET_REG. With the current approach only drivers with
SELF_MANAGED_REG will get wiphy->regd back. This is ok since these are
new drivers, which are familiar with this API.

But if we use your suggestion and always return wiphy->regd, then some
driver like ath9k that uses regulatory_hint() will now get it's
private regd returned to the wpa_s that manages it. I'm not saying
it's necessarily bad, but it's different than what was returned
before. The cfg80211 regdomain is intersected with wiphy->regd, so now
ath9k will start getting more permissive channels in usermode.

So we thought it's best to enable the new behavior only if the driver
explicitly wants it, using a new regulatory flag.

Arik
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Luis Chamberlain Nov. 13, 2014, 7:05 p.m. UTC | #5
On Thu, Nov 13, 2014 at 05:55:13PM +0200, Arik Nemtsov wrote:
> >
> >> 2. And then if userspace sends a wiphy idx to the NL80211_CMD_GET_REG,
> >> we'll return wiphy->regd for that case as well?
> >
> > That's right, for now we'd be able to send the regd when either
> > NL80211_ATTR_WIPHY_SELF_MANAGED_REG is set or when
> > NL80211_ATTR_WIPHY_SELF_MANAGED_REG is not set but regulatory_hint()
> > was used. Note that some users may have REGULATORY_CUSTOM_REG. and
> > then later use regulatory_hint(), this is done to for example set a
> > more restrictive custom world regdomain and then later use the CRDA
> > data for a specific alpha2.
> 
> Well always sending wiphy->regd whenever it is set is easy, but it
> might be problematic I guess:
> 
> We intend to add a patch to wpa_s to always add the wiphy_idx to
> NL80211_CMD_GET_REG. With the current approach only drivers with
> SELF_MANAGED_REG will get wiphy->regd back. This is ok since these are
> new drivers, which are familiar with this API.
> 
> But if we use your suggestion and always return wiphy->regd, then some
> driver like ath9k that uses regulatory_hint() will now get it's
> private regd returned to the wpa_s that manages it. I'm not saying
> it's necessarily bad, but it's different than what was returned
> before. The cfg80211 regdomain is intersected with wiphy->regd, so now
> ath9k will start getting more permissive channels in usermode.
> 
> So we thought it's best to enable the new behavior only if the driver
> explicitly wants it, using a new regulatory flag.

There's two userspace APIs:

iw reg get


That should return the cfg80211 regdomain and then traverse through all
the wiphy and if they have a wiphy->regd it should return that and also
a qualifier that specifies how that wiphy->regd got there.

iw rege get dev wlan0

That will only get the wiphy->regd for wlan0 and the qualifier that
identifies how it was set.

With the qualifier userspace should be able to do different things
and that should address letting you do something different per
different wiphy->regd on userspace, no?

  Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Arik Nemtsov Nov. 16, 2014, 11:09 a.m. UTC | #6
On Thu, Nov 13, 2014 at 9:05 PM, Luis R. Rodriguez <mcgrof@suse.com> wrote:
> On Thu, Nov 13, 2014 at 05:55:13PM +0200, Arik Nemtsov wrote:
>> >
>> >> 2. And then if userspace sends a wiphy idx to the NL80211_CMD_GET_REG,
>> >> we'll return wiphy->regd for that case as well?
>> >
>> > That's right, for now we'd be able to send the regd when either
>> > NL80211_ATTR_WIPHY_SELF_MANAGED_REG is set or when
>> > NL80211_ATTR_WIPHY_SELF_MANAGED_REG is not set but regulatory_hint()
>> > was used. Note that some users may have REGULATORY_CUSTOM_REG. and
>> > then later use regulatory_hint(), this is done to for example set a
>> > more restrictive custom world regdomain and then later use the CRDA
>> > data for a specific alpha2.
>>
>> Well always sending wiphy->regd whenever it is set is easy, but it
>> might be problematic I guess:
>>
>> We intend to add a patch to wpa_s to always add the wiphy_idx to
>> NL80211_CMD_GET_REG. With the current approach only drivers with
>> SELF_MANAGED_REG will get wiphy->regd back. This is ok since these are
>> new drivers, which are familiar with this API.
>>
>> But if we use your suggestion and always return wiphy->regd, then some
>> driver like ath9k that uses regulatory_hint() will now get it's
>> private regd returned to the wpa_s that manages it. I'm not saying
>> it's necessarily bad, but it's different than what was returned
>> before. The cfg80211 regdomain is intersected with wiphy->regd, so now
>> ath9k will start getting more permissive channels in usermode.
>>
>> So we thought it's best to enable the new behavior only if the driver
>> explicitly wants it, using a new regulatory flag.
>
> There's two userspace APIs:
>
> iw reg get
>
>
> That should return the cfg80211 regdomain and then traverse through all
> the wiphy and if they have a wiphy->regd it should return that and also
> a qualifier that specifies how that wiphy->regd got there.

This we didn't do, we didn't want to change the current syntax. Guess
we can add some --all here or something.

>
> iw rege get dev wlan0
>
> That will only get the wiphy->regd for wlan0 and the qualifier that
> identifies how it was set.

This patch we already have internally. We thought we'll send it once
the cfg80211 changes are in.
It's a small patch :)

>
> With the qualifier userspace should be able to do different things
> and that should address letting you do something different per
> different wiphy->regd on userspace, no?

See my reply to your other question here.

Arik
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 4c8be9e..af7febf 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1653,6 +1653,10 @@  enum nl80211_commands {
  * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
  *	&enum nl80211_smps_mode.
  *
+ * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating the
+ *	regulatory information came from the driver and not from the global
+ *	cfg80211 regulatory domain information.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -2005,6 +2009,8 @@  enum nl80211_attrs {
 
 	NL80211_ATTR_SMPS_MODE,
 
+	NL80211_ATTR_WIPHY_SELF_MANAGED_REG,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 44c95e3..e9b5f1c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -395,6 +395,7 @@  static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
 	[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
 	[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
+	[NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -5280,14 +5281,24 @@  static int nl80211_update_mesh_config(struct sk_buff *skb,
 
 static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 {
-	const struct ieee80211_regdomain *regdom;
+	const struct ieee80211_regdomain *regdom = NULL;
+	struct cfg80211_registered_device *rdev;
 	struct sk_buff *msg;
 	void *hdr = NULL;
 	struct nlattr *nl_reg_rules;
 	unsigned int i;
 
-	if (!cfg80211_regdomain)
-		return -EINVAL;
+	if (info->attrs[NL80211_ATTR_WIPHY] != NULL) {
+		struct wiphy *wiphy;
+
+		rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
+		if (IS_ERR(rdev))
+			return PTR_ERR(rdev);
+
+		wiphy = &rdev->wiphy;
+		if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
+			regdom = get_wiphy_regdom(wiphy);
+	}
 
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 	if (!msg)
@@ -5298,13 +5309,27 @@  static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 	if (!hdr)
 		goto put_failure;
 
-	if (reg_last_request_cell_base() &&
-	    nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
-			NL80211_USER_REG_HINT_CELL_BASE))
-		goto nla_put_failure;
+	if (!regdom) {
+		if (!cfg80211_regdomain) {
+			nlmsg_free(msg);
+			return -EINVAL;
+		}
+
+		if (reg_last_request_cell_base() &&
+		    nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
+				NL80211_USER_REG_HINT_CELL_BASE))
+			goto nla_put_failure;
+	} else {
+		if (nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
+			goto nla_put_failure;
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx))
+			goto nla_put_failure;
+	}
 
 	rcu_read_lock();
-	regdom = rcu_dereference(cfg80211_regdomain);
+
+	if (regdom == NULL)
+		regdom = rcu_dereference(cfg80211_regdomain);
 
 	if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
 	    (regdom->dfs_region &&
@@ -10645,9 +10670,16 @@  static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
 			goto nla_put_failure;
 	}
 
-	if (request->wiphy_idx != WIPHY_IDX_INVALID &&
-	    nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
-		goto nla_put_failure;
+	if (request->wiphy_idx != WIPHY_IDX_INVALID) {
+		struct wiphy *wiphy;
+
+		wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
+		if ((wiphy != NULL) &&
+		    nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx) &&
+		    (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
+		    (nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG)))
+			goto nla_put_failure;
+	}
 
 	return true;
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 50e8ffc..82bafa2 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -142,7 +142,7 @@  static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
 	return rtnl_dereference(cfg80211_regdomain);
 }
 
-static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
+const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
 {
 	return rtnl_dereference(wiphy->regd);
 }
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 5e48031..4b45d6e 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -38,6 +38,7 @@  unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
 				   const struct ieee80211_reg_rule *rule);
 
 bool reg_last_request_cell_base(void);
+const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy);
 
 /**
  * regulatory_hint_found_beacon - hints a beacon was found on a channel