2019-10-02 14:01:05

by Aaron Komisar

[permalink] [raw]
Subject: [PATCH v3] mac80211: fix scan blocked on DFS channels in ETSI domains

In non-ETSI reg domains scan is blocked when operating channel is a DFS ch.
For ETSI domains, however, once DFS channel is marked as available afer
the CAC, this channel will remain available even after leaving this channel.
Therefore a new CAC will not be required when scan is done.

In cfg80211 scan is not blocked for ETSI reg domains.
This patch enables scan in mac80211 as well when operating channel is a radar
channel for ETSI reg domains (unless CAC is in progress).

Signed-off-by: Aaron Komisar <[email protected]>
---

Changes in v2:
- Added verification that CAC is not in progress
- Updated commit message
Changes in v3:
- Updated commit message

include/net/cfg80211.h | 8 ++++++++
net/mac80211/scan.c | 30 ++++++++++++++++++++++++++++--
net/wireless/reg.c | 1 +
net/wireless/reg.h | 8 --------
4 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5253e7f667bd..5349898ed3e6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5546,6 +5546,14 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
const char *reg_initiator_name(enum nl80211_reg_initiator initiator);

/**
+ * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain
+ * @wiphy: wiphy for which pre-CAC capability is checked.
+
+ * Pre-CAC is allowed only in ETSI domain.
+ */
+bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
+
+/**
* DOC: Internal regulatory db functions
*
*/
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index adf94ba1ed77..4d31d9688dc2 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -520,10 +520,33 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
return 0;
}

+static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_sub_if_data *sdata_iter;
+
+ if (!ieee80211_is_radar_required(local))
+ return true;
+
+ if (!regulatory_pre_cac_allowed(local->hw.wiphy))
+ return false;
+
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata_iter, &local->interfaces, list) {
+ if (sdata_iter->wdev.cac_started) {
+ mutex_unlock(&local->iflist_mtx);
+ return false;
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ return true;
+}
+
static bool ieee80211_can_scan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
- if (ieee80211_is_radar_required(local))
+ if (!__ieee80211_can_leave_ch(sdata))
return false;

if (!list_empty(&local->roc_list))
@@ -630,7 +653,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,

lockdep_assert_held(&local->mtx);

- if (local->scan_req || ieee80211_is_radar_required(local))
+ if (local->scan_req)
+ return -EBUSY;
+
+ if (!__ieee80211_can_leave_ch(sdata))
return -EBUSY;

if (!ieee80211_can_scan(local, sdata)) {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5311d0ae2454..50d3242c4985 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -3883,6 +3883,7 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)

return pre_cac_allowed;
}
+EXPORT_SYMBOL(regulatory_pre_cac_allowed);

void regulatory_propagate_dfs_state(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef,
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 504133d76de4..dc8f689bd469 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -156,14 +156,6 @@ bool regulatory_indoor_allowed(void);
#define REG_PRE_CAC_EXPIRY_GRACE_MS 2000

/**
- * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain
- * @wiphy: wiphy for which pre-CAC capability is checked.
-
- * Pre-CAC is allowed only in ETSI domain.
- */
-bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
-
-/**
* regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys
* @wiphy - wiphy on which radar is detected and the event will be propagated
* to other available wiphys having the same DFS domain
--
2.11.0


2019-10-02 17:51:14

by Peter Oh

[permalink] [raw]
Subject: Re: [PATCH v3] mac80211: fix scan blocked on DFS channels in ETSI domains


On 10/2/19 6:59 AM, Aaron Komisar wrote:
> In non-ETSI reg domains scan is blocked when operating channel is a DFS ch.
> For ETSI domains, however, once DFS channel is marked as available afer
> the CAC, this channel will remain available even after leaving this channel.
> Therefore a new CAC will not be required when scan is done.
>
> In cfg80211 scan is not blocked for ETSI reg domains.
> This patch enables scan in mac80211 as well when operating channel is a radar
> channel for ETSI reg domains (unless CAC is in progress).
>
This is not the right approach to solve the problem.

The real reason of scan failure is because mac80211 checks if it's DFS
channel, but it doesn't check if CAC is done or not.

So to solve the issue, the right approach should be "check if DFS
channels and check if CAC is done".

You may refer how "cfg80211_reg_can_beacon()" is doing for that.


Thanks,

Peter

2019-10-03 08:14:28

by Aaron Komisar

[permalink] [raw]
Subject: [PATCH v3] mac80211: fix scan blocked on DFS channels in ETSI domains

On 10/2/19 5:46 PM, Peter Oh wrote:
>On 10/2/19 6:59 AM, Aaron Komisar wrote:
>> In non-ETSI reg domains scan is blocked when operating channel is a DFS ch.
>> For ETSI domains, however, once DFS channel is marked as available afer
>> the CAC, this channel will remain available even after leaving this channel.
>> Therefore a new CAC will not be required when scan is done.
>>
>> In cfg80211 scan is not blocked for ETSI reg domains.
>> This patch enables scan in mac80211 as well when operating channel is a radar
>> channel for ETSI reg domains (unless CAC is in progress).
>>
>This is not the right approach to solve the problem.
>
>The real reason of scan failure is because mac80211 checks if it's DFS
>channel, but it doesn't check if CAC is done or not.

The problem is that scan request is blocked in ETSI reg domains. In non-ETSI
reg domains the behavior is fine.

cfg80211 blocks scan in non-ETSI reg domains and allows leaving the channel
in ETSI reg domains. I think that if we add a function in mac80211, which
checks if we can leave the operating channel this function should also take
into account the reg domain for completeness.
>
>So to solve the issue, the right approach should be "check if DFS
>channels and check if CAC is done".

We can't scan while CAC is in progress but why must we verify that CAC was done
in order to perform a scan operation?
>
>You may refer how "cfg80211_reg_can_beacon()" is doing for that.
>
>
>Thanks,
>
>Peter

Thanks,
Aaron

2019-10-04 12:18:51

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v3] mac80211: fix scan blocked on DFS channels in ETSI domains

On Thu, 2019-10-03 at 08:13 +0000, Aaron Komisar wrote:

> > The real reason of scan failure is because mac80211 checks if it's DFS
> > channel, but it doesn't check if CAC is done or not.
>
> The problem is that scan request is blocked in ETSI reg domains. In non-ETSI
> reg domains the behavior is fine.
>
> cfg80211 blocks scan in non-ETSI reg domains and allows leaving the channel
> in ETSI reg domains. I think that if we add a function in mac80211, which
> checks if we can leave the operating channel this function should also take
> into account the reg domain for completeness.
> > So to solve the issue, the right approach should be "check if DFS
> > channels and check if CAC is done".
>
> We can't scan while CAC is in progress but why must we verify that CAC was done
> in order to perform a scan operation?

I agree that'd be weird - if CAC wasn't done we shouldn't be operating
on that channel to start with?

Peter, can you clarify your objection? Just to be sure - we're talking
here about the channel we're currently operating on, not any channel
that we might want to scan on.

I also note that regulatory_pre_cac_allowed() is named a bit confusingly
in this context, but I understand it - maybe a comment would be
worthwhile where this function is used, saying e.g.
/*
* If pre-CAC is allowed, we can also briefly leave the channel
* for scanning purposes.
*/

or something like that.

I do wonder if we should pull up the check for "cac_started" into
cfg80211? But then if we do that, we could maybe even pull *all* of the
checks up? But maybe not because of the tracking which channels we're on
etc. But at least the "cac_started" seems feasible?

Thanks,
johannes

2019-10-04 17:44:57

by Peter Oh

[permalink] [raw]
Subject: Re: [PATCH v3] mac80211: fix scan blocked on DFS channels in ETSI domains


On 10/4/19 5:15 AM, Johannes Berg wrote:
> On Thu, 2019-10-03 at 08:13 +0000, Aaron Komisar wrote:
>
>>> The real reason of scan failure is because mac80211 checks if it's DFS
>>> channel, but it doesn't check if CAC is done or not.
>> The problem is that scan request is blocked in ETSI reg domains. In non-ETSI
>> reg domains the behavior is fine.
>>
>> cfg80211 blocks scan in non-ETSI reg domains and allows leaving the channel
>> in ETSI reg domains. I think that if we add a function in mac80211, which
>> checks if we can leave the operating channel this function should also take
>> into account the reg domain for completeness.
>>> So to solve the issue, the right approach should be "check if DFS
>>> channels and check if CAC is done".
>> We can't scan while CAC is in progress but why must we verify that CAC was done
>> in order to perform a scan operation?
> I agree that'd be weird - if CAC wasn't done we shouldn't be operating
> on that channel to start with?

Sorry to make you guys confused. I was thinking about something else.

So ignore my comment in previous email.


Thanks,

Peter