This series includes two patches sent previously - allowing more channel
flags to propagate from regdom info and introducing a regulatory enforcement
mechanism for interfaces inhibiting a forbidden channel after a regulatory
update.
Introduce wiphy-specific regulatory management. This allows devices to manage
regdomain changes exclusively for their own wiphy. These devices do not update
the cfg80211 regdomain and are unaffected by hints external to the device/FW.
Introduce a new API to allow these devices to set their own regdomain.
Arik Nemtsov (2):
cfg80211: introduce regulatory flags controlling bw
cfg80211: leave invalid channels on regdomain change
Jonathan Doron (3):
cfg80211: update missing fields in custom regulatory path
cfg80211: allow wiphy specific regdomain management
cfg80211: Allow usermode to query wiphy specific regd info
include/net/cfg80211.h | 14 +++
include/net/regulatory.h | 9 ++
include/uapi/linux/nl80211.h | 23 +++++
net/wireless/core.c | 7 ++
net/wireless/nl80211.c | 132 ++++++++++++++++++++++------
net/wireless/nl80211.h | 1 +
net/wireless/reg.c | 201 ++++++++++++++++++++++++++++++++++++++++++-
net/wireless/reg.h | 1 +
8 files changed, 356 insertions(+), 32 deletions(-)
--
1.9.1
Allow setting bandwidth related regulatory flags. These flags are mapped
to the corresponding channel flags in the specified range.
Make sure the new flags are consulted when calculating the maximum
bandwidth allowed by a regulatory-rule.
Also allow propagating the GO_CONCURRENT modifier from a reg-rule to a
channel.
Signed-off-by: Arik Nemtsov <[email protected]>
---
include/uapi/linux/nl80211.h | 12 ++++++++++++
net/wireless/reg.c | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 46 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index be1d5de..1970d29 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2641,6 +2641,11 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
* base on contiguous rules and wider channels will be allowed to cross
* multiple contiguous/overlapping frequency ranges.
+ * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT
+ * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation
+ * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
+ * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
+ * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2653,11 +2658,18 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_NO_IR = 1<<7,
__NL80211_RRF_NO_IBSS = 1<<8,
NL80211_RRF_AUTO_BW = 1<<11,
+ NL80211_RRF_GO_CONCURRENT = 1<<12,
+ NL80211_RRF_NO_HT40MINUS = 1<<13,
+ NL80211_RRF_NO_HT40PLUS = 1<<14,
+ NL80211_RRF_NO_80MHZ = 1<<15,
+ NL80211_RRF_NO_160MHZ = 1<<16,
};
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR
+#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\
+ NL80211_RRF_NO_HT40PLUS)
/* For backport compatibility with older userspace */
#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index b725a31..7449a8c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -573,8 +573,9 @@ static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
return get_cfg80211_regdom();
}
-unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
- const struct ieee80211_reg_rule *rule)
+static unsigned int
+reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
+ const struct ieee80211_reg_rule *rule)
{
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
const struct ieee80211_freq_range *freq_range_tmp;
@@ -622,6 +623,27 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
return end_freq - start_freq;
}
+unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+ const struct ieee80211_reg_rule *rule)
+{
+ unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule);
+
+ if (rule->flags & NL80211_RRF_NO_160MHZ)
+ bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80));
+ if (rule->flags & NL80211_RRF_NO_80MHZ)
+ bw = min_t(unsigned int, bw, MHZ_TO_KHZ(40));
+
+ /*
+ * HT40+/HT40- limits are handled per-channel. Only limit BW if both
+ * are not allowed.
+ */
+ if (rule->flags & NL80211_RRF_NO_HT40MINUS &&
+ rule->flags & NL80211_RRF_NO_HT40PLUS)
+ bw = min_t(unsigned int, bw, MHZ_TO_KHZ(20));
+
+ return bw;
+}
+
/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
@@ -946,6 +968,16 @@ static u32 map_regdom_flags(u32 rd_flags)
channel_flags |= IEEE80211_CHAN_NO_OFDM;
if (rd_flags & NL80211_RRF_NO_OUTDOOR)
channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
+ if (rd_flags & NL80211_RRF_GO_CONCURRENT)
+ channel_flags |= IEEE80211_CHAN_GO_CONCURRENT;
+ if (rd_flags & NL80211_RRF_NO_HT40MINUS)
+ channel_flags |= IEEE80211_CHAN_NO_HT40MINUS;
+ if (rd_flags & NL80211_RRF_NO_HT40PLUS)
+ channel_flags |= IEEE80211_CHAN_NO_HT40PLUS;
+ if (rd_flags & NL80211_RRF_NO_80MHZ)
+ channel_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (rd_flags & NL80211_RRF_NO_160MHZ)
+ channel_flags |= IEEE80211_CHAN_NO_160MHZ;
return channel_flags;
}
--
1.9.1
From: Jonathan Doron <[email protected]>
Some channels fields were not being updated in the custom regulatory
path. Update them according to the code in handle_channel().
Signed-off-by: Jonathan Doron <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
net/wireless/reg.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index efbdff0..9575aea 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1691,10 +1691,23 @@ static void handle_channel_custom(struct wiphy *wiphy,
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
+ chan->dfs_state = NL80211_DFS_USABLE;
+ chan->dfs_state_entered = jiffies;
+
+ chan->beacon_found = false;
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
chan->max_reg_power = chan->max_power =
(int) MBM_TO_DBM(power_rule->max_eirp);
+
+ if (chan->flags & IEEE80211_CHAN_RADAR) {
+ if (reg_rule->dfs_cac_ms)
+ chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
+ else
+ chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+ }
+
+ chan->max_power = chan->max_reg_power;
}
static void handle_band_custom(struct wiphy *wiphy,
--
1.9.1
When the regulatory settings change, some channels might become invalid.
Disconnect interfaces acting on these channels, after giving userspace
code a grace period to leave them.
Signed-off-by: Arik Nemtsov <[email protected]>
---
include/net/regulatory.h | 6 +++
net/wireless/reg.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 104 insertions(+), 1 deletion(-)
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index dad7ab2..701177c 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -136,6 +136,11 @@ struct regulatory_request {
* otherwise initiating radiation is not allowed. This will enable the
* relaxations enabled under the CFG80211_REG_RELAX_NO_IR configuration
* option
+ * @REGULATORY_ENFORCE_CHANNELS: the regulatory core will make sure all
+ * interfaces on this wiphy reside on allowed channels. Upon a regdomain
+ * change, the interfaces are given a grace period to disconnect or move
+ * to an allowed channels. Interfaces on forbidden channels are forcibly
+ * disconnected.
*/
enum ieee80211_regulatory_flags {
REGULATORY_CUSTOM_REG = BIT(0),
@@ -144,6 +149,7 @@ enum ieee80211_regulatory_flags {
REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3),
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
REGULATORY_ENABLE_RELAX_NO_IR = BIT(5),
+ REGULATORY_ENFORCE_CHANNELS = BIT(6),
};
struct ieee80211_freq_range {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7449a8c..efbdff0 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -56,6 +56,7 @@
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
+#include "rdev-ops.h"
#include "regdb.h"
#include "nl80211.h"
@@ -66,6 +67,12 @@
#define REG_DBG_PRINT(args...)
#endif
+/*
+ * Grace period we give before making sure all current interfaces reside on
+ * channels allowed by the current regulatory domain.
+ */
+#define REG_ENFORCE_GRACE_MS 60000
+
/**
* enum reg_request_treatment - regulatory request treatment
*
@@ -210,6 +217,9 @@ struct reg_beacon {
struct ieee80211_channel chan;
};
+static void reg_check_chans_work(struct work_struct *work);
+static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);
+
static void reg_todo(struct work_struct *work);
static DECLARE_WORK(reg_work, reg_todo);
@@ -1518,6 +1528,88 @@ static void reg_call_notifier(struct wiphy *wiphy,
wiphy->reg_notifier(wiphy, request);
}
+static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+ struct ieee80211_channel *ch;
+ struct cfg80211_chan_def chandef;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ bool ret = true;
+
+ wdev_lock(wdev);
+
+ if (!wdev->netdev || !netif_running(wdev->netdev))
+ goto out;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ if (!wdev->beacon_interval)
+ goto out;
+
+ ret = cfg80211_reg_can_beacon(wiphy,
+ &wdev->chandef, wdev->iftype);
+ break;
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_P2P_CLIENT:
+ if (!wdev->current_bss ||
+ !wdev->current_bss->pub.channel)
+ goto out;
+
+ ch = wdev->current_bss->pub.channel;
+ if (rdev->ops->get_channel &&
+ !rdev_get_channel(rdev, wdev, &chandef))
+ ret = cfg80211_chandef_usable(wiphy, &chandef,
+ IEEE80211_CHAN_DISABLED);
+ else
+ ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
+ break;
+ default:
+ /* others not implemented for now */
+ break;
+ }
+
+out:
+ wdev_unlock(wdev);
+ return ret;
+}
+
+static void reg_leave_invalid_chans(struct wiphy *wiphy)
+{
+ struct wireless_dev *wdev;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+
+ ASSERT_RTNL();
+
+ list_for_each_entry(wdev, &rdev->wdev_list, list)
+ if (!reg_wdev_chan_valid(wiphy, wdev))
+ cfg80211_leave(rdev, wdev);
+}
+
+static void reg_check_chans_work(struct work_struct *work)
+{
+ struct cfg80211_registered_device *rdev;
+
+ REG_DBG_PRINT("Verifying active interfaces after reg change\n");
+ rtnl_lock();
+
+ list_for_each_entry(rdev, &cfg80211_rdev_list, list)
+ if (rdev->wiphy.regulatory_flags & REGULATORY_ENFORCE_CHANNELS)
+ reg_leave_invalid_chans(&rdev->wiphy);
+
+ rtnl_unlock();
+}
+
+static void reg_check_channels(void)
+{
+ /*
+ * Give usermode a chance to do something nicer (move to another
+ * channel, orderly disconnection), before forcing a disconnection.
+ */
+ mod_delayed_work(system_power_efficient_wq,
+ ®_check_chans,
+ msecs_to_jiffies(REG_ENFORCE_GRACE_MS));
+}
+
static void wiphy_update_regulatory(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
@@ -1557,6 +1649,8 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
wiphy = &rdev->wiphy;
wiphy_update_regulatory(wiphy, initiator);
}
+
+ reg_check_channels();
}
static void handle_channel_custom(struct wiphy *wiphy,
@@ -1963,8 +2057,10 @@ static void reg_process_hint(struct regulatory_request *reg_request)
/* This is required so that the orig_* parameters are saved */
if (treatment == REG_REQ_ALREADY_SET && wiphy &&
- wiphy->regulatory_flags & REGULATORY_STRICT_REG)
+ wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
wiphy_update_regulatory(wiphy, reg_request->initiator);
+ reg_check_channels();
+ }
return;
@@ -2845,6 +2941,7 @@ void regulatory_exit(void)
cancel_work_sync(®_work);
cancel_delayed_work_sync(®_timeout);
+ cancel_delayed_work_sync(®_check_chans);
/* Lock to suppress warnings */
rtnl_lock();
--
1.9.1
From: Jonathan Doron <[email protected]>
Add a new regulatory flag that allows a driver to manage regdomain
changes/updates for its own wiphy.
In this case the regdomain is local to the driver, and it does not use
the shared cfg80211 regdomain. It also implies that the driver does not
wish to get regulatory updates generated by other wiphys or by usermode.
A new API lets the driver send a complete regdomain, to be applied on
its wiphy only.
After a wiphy-specific regdomain change takes place, usermode will get
a new type of change notification. The regulatory core also takes care
enforce regulatory restrictions, in case some interfaces are on
forbidden channels.
Signed-off-by: Jonathan Doron <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
include/net/cfg80211.h | 14 ++++++++
include/net/regulatory.h | 9 +++++
include/uapi/linux/nl80211.h | 5 +++
net/wireless/core.c | 7 ++++
net/wireless/nl80211.c | 80 ++++++++++++++++++++++++++++++++++----------
net/wireless/nl80211.h | 1 +
net/wireless/reg.c | 59 ++++++++++++++++++++++++++++++++
7 files changed, 157 insertions(+), 18 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 77aa805..7f2c595 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3685,6 +3685,20 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
/**
+ * regulatory_set_wiphy_regd_rtnl - set regdom info for self managed drivers
+ * @wiphy: the wireless device we want to process the regulatory domain on
+ * @rd: the regulatory domain informatoin to use for this wiphy
+ *
+ * Set the regulatory domain information for self managed drivers, only they
+ * can use this function.
+ * This function requires the caller to hold the rtnl_lock.
+ *
+ * Return: 0 on success. -EINVAL, -EPERM
+ */
+int regulatory_set_wiphy_regd_rtnl(struct wiphy *wiphy,
+ struct ieee80211_regdomain *rd);
+
+/**
* wiphy_apply_custom_regulatory - apply a custom driver regulatory domain
* @wiphy: the wireless device we want to process the regulatory domain on
* @regd: the custom regulatory domain to use for this wiphy
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 701177c..42345f4 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -141,6 +141,14 @@ struct regulatory_request {
* change, the interfaces are given a grace period to disconnect or move
* to an allowed channels. Interfaces on forbidden channels are forcibly
* disconnected.
+ * @REGULATORY_WIPHY_SELF_MANAGED: for devices that employ wiphy-specific
+ * regdom management. These devices will ignore all regdom changes not
+ * originating from their own wiphy. This flag is incompatible with the
+ * flags: %REGULATORY_CUSTOM_REG, %REGULATORY_STRICT_REG,
+ * %REGULATORY_COUNTRY_IE_FOLLOW_POWER, %REGULATORY_COUNTRY_IE_IGNORE and
+ * %REGULATORY_DISABLE_BEACON_HINTS. Mixing any of the above flags with
+ * this flag will result in a failure to register the wiphy. This flag
+ * implies %REGULATORY_DISABLE_BEACON_HINTS.
*/
enum ieee80211_regulatory_flags {
REGULATORY_CUSTOM_REG = BIT(0),
@@ -150,6 +158,7 @@ enum ieee80211_regulatory_flags {
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
REGULATORY_ENABLE_RELAX_NO_IR = BIT(5),
REGULATORY_ENFORCE_CHANNELS = BIT(6),
+ REGULATORY_WIPHY_SELF_MANAGED = BIT(7),
};
struct ieee80211_freq_range {
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1970d29..4c8be9e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -746,6 +746,9 @@
* destination %NL80211_ATTR_MAC on the interface identified by
* %NL80211_ATTR_IFINDEX.
*
+ * @NL80211_CMD_WIPHY_REG_CHANGE: Similar to %NL80211_CMD_REG_CHANGE, but used
+ * for indicating changes for devices with wiphy-specific regdom management
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -922,6 +925,8 @@ enum nl80211_commands {
NL80211_CMD_GET_MPP,
+ NL80211_CMD_WIPHY_REG_CHANGE,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f52a4cd..22f4b08 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -503,6 +503,13 @@ int wiphy_register(struct wiphy *wiphy)
!wiphy->wowlan->tcp))
return -EINVAL;
#endif
+ if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
+ (wiphy->regulatory_flags &
+ (REGULATORY_CUSTOM_REG | REGULATORY_STRICT_REG |
+ REGULATORY_COUNTRY_IE_FOLLOW_POWER |
+ REGULATORY_COUNTRY_IE_IGNORE |
+ REGULATORY_DISABLE_BEACON_HINTS))))
+ return -EINVAL;
if (WARN_ON(wiphy->coalesce &&
(!wiphy->coalesce->n_rules ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d98d4ea..44c95e3 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10617,25 +10617,9 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
NL80211_MCGRP_SCAN, GFP_KERNEL);
}
-/*
- * This can happen on global regulatory changes or device specific settings
- * based on custom world regulatory domains.
- */
-void nl80211_send_reg_change_event(struct regulatory_request *request)
+static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
+ struct regulatory_request *request)
{
- struct sk_buff *msg;
- void *hdr;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return;
-
- hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
- if (!hdr) {
- nlmsg_free(msg);
- return;
- }
-
/* Userspace can always count this one always being set */
if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
goto nla_put_failure;
@@ -10665,6 +10649,66 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
goto nla_put_failure;
+ return true;
+
+nla_put_failure:
+ return false;
+}
+
+/*
+ * This can happen on global regulatory changes or device specific settings
+ * based on custom world regulatory domains.
+ */
+void nl80211_send_reg_change_event(struct regulatory_request *request)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nl80211_reg_change_event_fill(msg, request) == false)
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+
+ rcu_read_lock();
+ genlmsg_multicast_allns(&nl80211_fam, msg, 0,
+ NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
+ rcu_read_unlock();
+
+ return;
+
+nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+
+void nl80211_send_wiphy_reg_change_event(struct regulatory_request *request)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_WIPHY_REG_CHANGE);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nl80211_reg_change_event_fill(msg, request) == false)
+ goto nla_put_failure;
+
genlmsg_end(msg, hdr);
rcu_read_lock();
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 7ad70d6..b91b9c5 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -18,6 +18,7 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
struct net_device *netdev);
void nl80211_send_reg_change_event(struct regulatory_request *request);
+void nl80211_send_wiphy_reg_change_event(struct regulatory_request *request);
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
const u8 *buf, size_t len, gfp_t gfp);
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 9575aea..50e8ffc 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1307,6 +1307,9 @@ static bool ignore_reg_update(struct wiphy *wiphy,
{
struct regulatory_request *lr = get_last_request();
+ if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
+ return true;
+
if (!lr) {
REG_DBG_PRINT("Ignoring regulatory request set by %s "
"since last_request is not set\n",
@@ -1370,6 +1373,9 @@ static void handle_reg_beacon(struct wiphy *wiphy, unsigned int chan_idx,
sband = wiphy->bands[reg_beacon->chan.band];
chan = &sband->channels[chan_idx];
+ if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
+ return;
+
if (likely(chan->center_freq != reg_beacon->chan.center_freq))
return;
@@ -2424,6 +2430,9 @@ static void restore_regulatory_settings(bool reset_user)
world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
+ if (rdev->wiphy.regulatory_flags &
+ REGULATORY_WIPHY_SELF_MANAGED)
+ continue;
if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
restore_custom_reg_settings(&rdev->wiphy);
}
@@ -2827,6 +2836,56 @@ int set_regdom(const struct ieee80211_regdomain *rd)
return 0;
}
+int regulatory_set_wiphy_regd_rtnl(struct wiphy *wiphy,
+ struct ieee80211_regdomain *rd)
+{
+ const struct ieee80211_regdomain *regd;
+ const struct ieee80211_regdomain *tmp;
+ enum ieee80211_band band;
+ struct regulatory_request request = {};
+
+ if (WARN_ON(!wiphy || !rd))
+ return -EINVAL;
+
+ if (WARN(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED,
+ "wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n"))
+ return -EPERM;
+
+ WARN_ON_ONCE(!lockdep_rtnl_is_held());
+
+ if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) {
+ print_regdomain_info(rd);
+ return -EINVAL;
+ }
+
+ regd = reg_copy_regd(rd);
+ if (IS_ERR(regd))
+ return PTR_ERR(regd);
+
+ tmp = get_wiphy_regdom(wiphy);
+ rcu_assign_pointer(wiphy->regd, regd);
+ rcu_free_regdom(tmp);
+
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+ handle_band_custom(wiphy,
+ wiphy->bands[band],
+ regd);
+ }
+
+ reg_process_ht_flags(wiphy);
+
+ request.wiphy_idx = get_wiphy_idx(wiphy);
+ request.alpha2[0] = rd->alpha2[0];
+ request.alpha2[1] = rd->alpha2[1];
+ request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
+
+ nl80211_send_wiphy_reg_change_event(&request);
+
+ reg_check_channels();
+ return 0;
+}
+EXPORT_SYMBOL(regulatory_set_wiphy_regd_rtnl);
+
void wiphy_regulatory_register(struct wiphy *wiphy)
{
struct regulatory_request *lr;
--
1.9.1
From: Jonathan Doron <[email protected]>
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 <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
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(-)
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
--
1.9.1
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
> From: Jonathan Doron <[email protected]>
>
> Some channels fields were not being updated in the custom regulatory
> path. Update them according to the code in handle_channel().
>
> Signed-off-by: Jonathan Doron <[email protected]>
> Signed-off-by: Arik Nemtsov <[email protected]>
Reviewed-by: Luis R. Rodriguez <[email protected]>
Luis
On Wed, Nov 5, 2014 at 5:16 AM, Luis R. Rodriguez
<[email protected]> wrote:
> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>> +static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
>> +{
>> + struct ieee80211_channel *ch;
>> + struct cfg80211_chan_def chandef;
>> + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
>> + bool ret = true;
>> +
>> + wdev_lock(wdev);
>> +
>> + if (!wdev->netdev || !netif_running(wdev->netdev))
>> + goto out;
>> +
>> + switch (wdev->iftype) {
>> + case NL80211_IFTYPE_AP:
>> + case NL80211_IFTYPE_P2P_GO:
>> + if (!wdev->beacon_interval)
>> + goto out;
>> +
>> + ret = cfg80211_reg_can_beacon(wiphy,
>> + &wdev->chandef, wdev->iftype);
>> + break;
>> + case NL80211_IFTYPE_STATION:
>> + case NL80211_IFTYPE_P2P_CLIENT:
>> + if (!wdev->current_bss ||
>> + !wdev->current_bss->pub.channel)
>> + goto out;
>> +
>> + ch = wdev->current_bss->pub.channel;
>> + if (rdev->ops->get_channel &&
>> + !rdev_get_channel(rdev, wdev, &chandef))
>> + ret = cfg80211_chandef_usable(wiphy, &chandef,
>> + IEEE80211_CHAN_DISABLED);
>> + else
>> + ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
>> + break;
>> + default:
>> + /* others not implemented for now */
>
> Looks good to me except this of course, since its a flag that will
> enable this per wiphy might as well WARN() if you really do not want
> to think about this. That means that once someone does enable this on
> a wiphy with the other type of interfaces they'll have to think about
> this, likewise one could warn if a wiphy interface is registered with
> the flag to follow this but supports a mode not handled here yet.
But I do want to support a wiphy that has other modes
(NL80211_IFTYPE_ADHOC), but I don't want people to get warnings every
time they use IBSS.
Maybe I'll rename the flag to REGULATORY_ENFORCE_AP_STA_CHANNELS?
Arik
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
> Allow setting bandwidth related regulatory flags. These flags are mapped
> to the corresponding channel flags in the specified range.
> Make sure the new flags are consulted when calculating the maximum
> bandwidth allowed by a regulatory-rule.
>
> Also allow propagating the GO_CONCURRENT modifier from a reg-rule to a
> channel.
>
> Signed-off-by: Arik Nemtsov <[email protected]>
Reviewed-by: Luis R. Rodriguez <[email protected]>
Luis
On Thu, Nov 13, 2014 at 12:53 AM, Luis R. Rodriguez
<[email protected]> wrote:
> On Wed, Nov 5, 2014 at 1:18 AM, Arik Nemtsov <[email protected]> wrote:
>> On Wed, Nov 5, 2014 at 5:16 AM, Luis R. Rodriguez
>> <[email protected]> wrote:
>>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>>>> +static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
>>>> +{
>>>> + struct ieee80211_channel *ch;
>>>> + struct cfg80211_chan_def chandef;
>>>> + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
>>>> + bool ret = true;
>>>> +
>>>> + wdev_lock(wdev);
>>>> +
>>>> + if (!wdev->netdev || !netif_running(wdev->netdev))
>>>> + goto out;
>>>> +
>>>> + switch (wdev->iftype) {
>>>> + case NL80211_IFTYPE_AP:
>>>> + case NL80211_IFTYPE_P2P_GO:
>>>> + if (!wdev->beacon_interval)
>>>> + goto out;
>>>> +
>>>> + ret = cfg80211_reg_can_beacon(wiphy,
>>>> + &wdev->chandef, wdev->iftype);
>>>> + break;
>>>> + case NL80211_IFTYPE_STATION:
>>>> + case NL80211_IFTYPE_P2P_CLIENT:
>>>> + if (!wdev->current_bss ||
>>>> + !wdev->current_bss->pub.channel)
>>>> + goto out;
>>>> +
>>>> + ch = wdev->current_bss->pub.channel;
>>>> + if (rdev->ops->get_channel &&
>>>> + !rdev_get_channel(rdev, wdev, &chandef))
>>>> + ret = cfg80211_chandef_usable(wiphy, &chandef,
>>>> + IEEE80211_CHAN_DISABLED);
>>>> + else
>>>> + ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
>>>> + break;
>>>> + default:
>>>> + /* others not implemented for now */
>>>
>>> Looks good to me except this of course, since its a flag that will
>>> enable this per wiphy might as well WARN() if you really do not want
>>> to think about this. That means that once someone does enable this on
>>> a wiphy with the other type of interfaces they'll have to think about
>>> this, likewise one could warn if a wiphy interface is registered with
>>> the flag to follow this but supports a mode not handled here yet.
>>
>> But I do want to support a wiphy that has other modes
>> (NL80211_IFTYPE_ADHOC), but I don't want people to get warnings every
>> time they use IBSS.
>> Maybe I'll rename the flag to REGULATORY_ENFORCE_AP_STA_CHANNELS?
>
> Then it depends on how important this feature is for your regulatory
> requirements. If its important then I'd wait until its properly
> implemented, if its not required for the other modes then a simple
> information message would suffice.
Let's settle for the pr_info then.
Arik
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
> +static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
> +{
> + struct ieee80211_channel *ch;
> + struct cfg80211_chan_def chandef;
> + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
> + bool ret = true;
> +
> + wdev_lock(wdev);
> +
> + if (!wdev->netdev || !netif_running(wdev->netdev))
> + goto out;
> +
> + switch (wdev->iftype) {
> + case NL80211_IFTYPE_AP:
> + case NL80211_IFTYPE_P2P_GO:
> + if (!wdev->beacon_interval)
> + goto out;
> +
> + ret = cfg80211_reg_can_beacon(wiphy,
> + &wdev->chandef, wdev->iftype);
> + break;
> + case NL80211_IFTYPE_STATION:
> + case NL80211_IFTYPE_P2P_CLIENT:
> + if (!wdev->current_bss ||
> + !wdev->current_bss->pub.channel)
> + goto out;
> +
> + ch = wdev->current_bss->pub.channel;
> + if (rdev->ops->get_channel &&
> + !rdev_get_channel(rdev, wdev, &chandef))
> + ret = cfg80211_chandef_usable(wiphy, &chandef,
> + IEEE80211_CHAN_DISABLED);
> + else
> + ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
> + break;
> + default:
> + /* others not implemented for now */
Looks good to me except this of course, since its a flag that will
enable this per wiphy might as well WARN() if you really do not want
to think about this. That means that once someone does enable this on
a wiphy with the other type of interfaces they'll have to think about
this, likewise one could warn if a wiphy interface is registered with
the flag to follow this but supports a mode not handled here yet.
Luis
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
> cfg80211: allow wiphy specific regdomain management
This guy never made it to my inbox.
Luis
On Wed, Nov 5, 2014 at 5:21 AM, Luis R. Rodriguez
<[email protected]> wrote:
> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>> cfg80211: allow wiphy specific regdomain management
>
> This guy never made it to my inbox.
Here it is:
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/129448
Arik
>
>> 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
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
On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> 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
On Wed, Nov 5, 2014 at 1:12 AM, Arik Nemtsov <[email protected]> wrote:
> On Wed, Nov 5, 2014 at 5:23 AM, Luis R. Rodriguez
> <[email protected]> wrote:
>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> 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
On Wed, Nov 5, 2014 at 5:23 AM, Luis R. Rodriguez
<[email protected]> wrote:
> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> 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
On Thu, Nov 13, 2014 at 9:05 PM, Luis R. Rodriguez <[email protected]> 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
On Wed, Nov 5, 2014 at 1:18 AM, Arik Nemtsov <[email protected]> wrote:
> On Wed, Nov 5, 2014 at 5:16 AM, Luis R. Rodriguez
> <[email protected]> wrote:
>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>>> +static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
>>> +{
>>> + struct ieee80211_channel *ch;
>>> + struct cfg80211_chan_def chandef;
>>> + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
>>> + bool ret = true;
>>> +
>>> + wdev_lock(wdev);
>>> +
>>> + if (!wdev->netdev || !netif_running(wdev->netdev))
>>> + goto out;
>>> +
>>> + switch (wdev->iftype) {
>>> + case NL80211_IFTYPE_AP:
>>> + case NL80211_IFTYPE_P2P_GO:
>>> + if (!wdev->beacon_interval)
>>> + goto out;
>>> +
>>> + ret = cfg80211_reg_can_beacon(wiphy,
>>> + &wdev->chandef, wdev->iftype);
>>> + break;
>>> + case NL80211_IFTYPE_STATION:
>>> + case NL80211_IFTYPE_P2P_CLIENT:
>>> + if (!wdev->current_bss ||
>>> + !wdev->current_bss->pub.channel)
>>> + goto out;
>>> +
>>> + ch = wdev->current_bss->pub.channel;
>>> + if (rdev->ops->get_channel &&
>>> + !rdev_get_channel(rdev, wdev, &chandef))
>>> + ret = cfg80211_chandef_usable(wiphy, &chandef,
>>> + IEEE80211_CHAN_DISABLED);
>>> + else
>>> + ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
>>> + break;
>>> + default:
>>> + /* others not implemented for now */
>>
>> Looks good to me except this of course, since its a flag that will
>> enable this per wiphy might as well WARN() if you really do not want
>> to think about this. That means that once someone does enable this on
>> a wiphy with the other type of interfaces they'll have to think about
>> this, likewise one could warn if a wiphy interface is registered with
>> the flag to follow this but supports a mode not handled here yet.
>
> But I do want to support a wiphy that has other modes
> (NL80211_IFTYPE_ADHOC), but I don't want people to get warnings every
> time they use IBSS.
> Maybe I'll rename the flag to REGULATORY_ENFORCE_AP_STA_CHANNELS?
Then it depends on how important this feature is for your regulatory
requirements. If its important then I'd wait until its properly
implemented, if its not required for the other modes then a simple
information message would suffice.
Luis
On Thu, Nov 13, 2014 at 1:07 AM, Luis R. Rodriguez
<[email protected]> wrote:
> On Wed, Nov 5, 2014 at 12:41 AM, Arik Nemtsov <[email protected]> wrote:
>> On Wed, Nov 5, 2014 at 5:21 AM, Luis R. Rodriguez
>> <[email protected]> wrote:
>>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>>>> cfg80211: allow wiphy specific regdomain management
>>>
>>> This guy never made it to my inbox.
>>
>> Here it is:
>> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/129448
>
> Look OK but I can't comment on code so please also Cc this address on
> future patches: [email protected]. Look forward to next iteration.
I'll resubmit the v2 with the pr_info change, so you'll be able to
comment on the missing patch.
Arik
On Thu, 2014-10-23 at 09:37 +0300, Arik Nemtsov wrote:
> Allow setting bandwidth related regulatory flags. These flags are mapped
> to the corresponding channel flags in the specified range.
> Make sure the new flags are consulted when calculating the maximum
> bandwidth allowed by a regulatory-rule.
>
> Also allow propagating the GO_CONCURRENT modifier from a reg-rule to a
> channel.
Applied.
johannes
On Wed, Nov 5, 2014 at 12:41 AM, Arik Nemtsov <[email protected]> wrote:
> On Wed, Nov 5, 2014 at 5:21 AM, Luis R. Rodriguez
> <[email protected]> wrote:
>> On Wed, Oct 22, 2014 at 11:37 PM, Arik Nemtsov <[email protected]> wrote:
>>> cfg80211: allow wiphy specific regdomain management
>>
>> This guy never made it to my inbox.
>
> Here it is:
> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/129448
Look OK but I can't comment on code so please also Cc this address on
future patches: [email protected]. Look forward to next iteration.
Luis