Search Linux Wireless

Re: [RFC 1/3] cfg80211: Make pre-CAC results valid only for ETSI domain

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

 



On Thursday 26 January 2017 03:04 PM, Johannes Berg wrote:
>
>> +		/* Should we apply the grace period during beaconing
>> interface
>> +		 * shutdown also?
>> +		 */
>> +		cfg80211_sched_dfs_chan_update(rdev);
>
> It might make some sense, say if hostapd crashes and you restart it
> automatically or something?

Sure. Initially it looked tricky to handle this. But I guess we can store
the DFS channel and the time stamp (rdev specific) when the beaconing interface
is brought down. cfg80211_dfs_channels_update_work() can use these information
and apply the grace period before setting the DFS channel state back to 'usable'.

>
>>   	return err;
>> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
>> index 5497d022..090309a 100644
>> --- a/net/wireless/chan.c
>> +++ b/net/wireless/chan.c
>> @@ -456,6 +456,102 @@ bool cfg80211_chandef_dfs_usable(struct wiphy
>> *wiphy,
>>   	return (r1 + r2 > 0);
>>   }
>>
>> +static bool cfg80211_5ghz_sub_chan(struct cfg80211_chan_def
>> *chandef,
>> +				   struct ieee80211_channel *chan)
>
> This could use some explanation, and I don't see anything that's really
> 5 GHz specific in here, so why that in the function name?

Sure.

>
>> +	u32 start_freq_seg0 = 0, end_freq_seg0 = 0;
>> +	u32 start_freq_seg1 = 0, end_freq_seg1 = 0;
>> +
>> +	if (chandef->chan->center_freq == chan->center_freq)
>> +		return true;
>> +
>> +	switch (chandef->width) {
>> +	case NL80211_CHAN_WIDTH_40:
>> +		start_freq_seg0 = chandef->center_freq1 - 20;
>> +		end_freq_seg0 = chandef->center_freq1 + 20;
>> +		break;
>> +	case NL80211_CHAN_WIDTH_80P80:
>> +		start_freq_seg1 = chandef->center_freq2 - 40;
>> +		end_freq_seg1 = chandef->center_freq2 + 40;
>> +		/* fall through */
>> +	case NL80211_CHAN_WIDTH_80:
>> +		start_freq_seg0 = chandef->center_freq1 - 40;
>> +		end_freq_seg0 = chandef->center_freq1 + 40;
>> +		break;
>> +	case NL80211_CHAN_WIDTH_160:
>> +		start_freq_seg0 = chandef->center_freq1 - 80;
>> +		end_freq_seg0 = chandef->center_freq1 + 80;
>> +		break;
>> +	case NL80211_CHAN_WIDTH_20_NOHT:
>> +	case NL80211_CHAN_WIDTH_20:
>> +	case NL80211_CHAN_WIDTH_5:
>> +	case NL80211_CHAN_WIDTH_10:
>> +		break;
>> +	}
>> +
>> +	if (chan->center_freq > start_freq_seg0 &&
>> +	    chan->center_freq < end_freq_seg0)
>> +		return true;
>> +
>> +	return chan->center_freq > start_freq_seg1 &&
>> +		chan->center_freq < end_freq_seg1;
>> +}
>
> It's also written pretty oddly... The 5/10/20 cases could return
> immediately, the start/end could be replaced by width, and the
> initializations wouldn't be needed at all ... I think we can do better
> here.

Sure, I'll improve this function.

>
>> +bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
>> +				       struct ieee80211_channel
>> *chan)
>
> Again, nothing 5 GHz specific.

Ok.

>
>> +	struct wireless_dev *wdev;
>> +
>> +	ASSERT_RTNL();
>> +
>> +	if (!(chan->flags & IEEE80211_CHAN_RADAR))
>> +		return false;
>> +
>> +	list_for_each_entry(wdev, &wiphy->wdev_list, list) {
>> +		if (!cfg80211_beaconing_iface_active(wdev))
>> +			continue;
>> +
>> +		if (cfg80211_5ghz_sub_chan(&wdev->chandef, chan))
>> +			return true;
>> +	}
>> +
>> +	return false;
>> +}
>>
>>   static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy,
>>   					     u32 center_freq,
>> diff --git a/net/wireless/core.h b/net/wireless/core.h
>> index 58ca206..327fe95 100644
>> --- a/net/wireless/core.h
>> +++ b/net/wireless/core.h
>> @@ -459,6 +459,13 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
>>   cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
>>   			      const struct cfg80211_chan_def
>> *chandef);
>>
>> +void cfg80211_sched_dfs_chan_update(struct
>> cfg80211_registered_device *rdev);
>> +
>> +bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
>> +				       struct ieee80211_channel
>> *chan);
>> +
>> +bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev);
>> +
>>   static inline unsigned int elapsed_jiffies_msecs(unsigned long
>> start)
>>   {
>>   	unsigned long end = jiffies;
>> diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
>> index 364f900..10bf040 100644
>> --- a/net/wireless/ibss.c
>> +++ b/net/wireless/ibss.c
>> @@ -190,6 +190,7 @@ static void __cfg80211_clear_ibss(struct
>> net_device *dev, bool nowext)
>>   	if (!nowext)
>>   		wdev->wext.ibss.ssid_len = 0;
>>   #endif
>> +	cfg80211_sched_dfs_chan_update(rdev);
>>   }
>>
>>   void cfg80211_clear_ibss(struct net_device *dev, bool nowext)
>> diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
>> index 2d8518a..ec0b1c2 100644
>> --- a/net/wireless/mesh.c
>> +++ b/net/wireless/mesh.c
>> @@ -262,6 +262,7 @@ int __cfg80211_leave_mesh(struct
>> cfg80211_registered_device *rdev,
>>   		wdev->beacon_interval = 0;
>>   		memset(&wdev->chandef, 0, sizeof(wdev->chandef));
>>   		rdev_set_qos_map(rdev, dev, NULL);
>> +		cfg80211_sched_dfs_chan_update(rdev);
>>   	}
>>
>>   	return err;
>> diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
>> index 22b3d99..3c7e155 100644
>> --- a/net/wireless/mlme.c
>> +++ b/net/wireless/mlme.c
>> @@ -745,6 +745,12 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev,
>> int freq, int sig_mbm,
>>   }
>>   EXPORT_SYMBOL(cfg80211_rx_mgmt);
>>
>> +void cfg80211_sched_dfs_chan_update(struct
>> cfg80211_registered_device *rdev)
>> +{
>> +	cancel_delayed_work(&rdev->dfs_update_channels_wk);
>> +	queue_delayed_work(cfg80211_wq, &rdev-
>>> dfs_update_channels_wk, 0);
>> +}
>
> This uses 0.
>
>> @@ -820,9 +844,7 @@ void cfg80211_radar_event(struct wiphy *wiphy,
>>   	 */
>>   	cfg80211_set_dfs_state(wiphy, chandef,
>> NL80211_DFS_UNAVAILABLE);
>>
>> -	timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
>> -	queue_delayed_work(cfg80211_wq, &rdev-
>>> dfs_update_channels_wk,
>> -			   timeout);
>> +	cfg80211_sched_dfs_chan_update(rdev);
>
> But this didn't - why does that change?

Since cfg80211_dfs_channels_update_work() can be scheduled multiple times to run at
different point of time (2 secs - to expire cac for non-ETSI, 30 * 60 secs - to clear
NOL), cfg80211_sched_dfs_chan_update(rdev) is added to make sure the worker can also
be fired at nearer time stamp when it is already pending to run at after a relatively
later point of time. cfg80211_dfs_channels_update_work() uses the time stamp of channel
DFS state (dfs_state_entered) to set the next DFS state and/or re-schedule the worker
later.

>
>> +unsigned long regulatory_get_pre_cac_timeout(struct wiphy *wiphy)
>> +{
>> +	if (!regulatory_pre_cac_allowed(wiphy))
>> +		return REG_PRE_CAC_EXPIRY_GRACE_MS;
>> +
>> +	/*
>> +	 * Return the maximum pre-CAC timeout when pre-CAC is
>> allowed
>> +	 * in the current dfs domain (ETSI).
>> +	 */
>> +	return -1;
>> +}
>
> Don't ever return -1, that's -EPERM and not really what you want
> anyway.
>

Sure, since the return time is unsigned long I chose to use -1. I'll remove
this function as mentioned in below comment.


> In fact, this doesn't even make sense, since the only caller already
> checks regulatory_pre_cac_allowed() before calling this.

Sure. I originally thought a helper like this would be used multiple places.
But it is not the case now and being used in single place.


Thanks,

Vasanth




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux