Search Linux Wireless

Re: [RFC 3/3] cfg80211: Share Channel DFS state across wiphys of same DFS domain

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

 



On Wed, 2017-01-25 at 17:01 +0530, Vasanthakumar Thiagarajan wrote:
> Sharing DFS channel state across multiple wiphys (radios) could
> be useful with multiple radios on the system. When one radio
> completes CAC and marks the channel available another radio
> can use this information and start beaconing without really doing
> CAC.
> 
> Whenever there is a state change in DFS channel associated to
> a particular wiphy the the same state change is propagated to
> other wiphys having the same DFS reg domain configuration.
> Also when a new wiphy is created the DFS channel state of
> other existing wiphys of same DFS domain is copied.
> 
> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@xxxxxxxxxxxxxxxx>
> ---
>  net/wireless/chan.c |  24 +++++++++--
>  net/wireless/core.c |  37 +++++++++++++++++
>  net/wireless/core.h |   6 +++
>  net/wireless/mlme.c |  11 +++++-
>  net/wireless/reg.c  | 112
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  net/wireless/reg.h  |  22 +++++++++++
>  6 files changed, 207 insertions(+), 5 deletions(-)
> 
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index 090309a..40f1097 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -532,21 +532,37 @@ bool cfg80211_beaconing_iface_active(struct
> wireless_dev *wdev)
>  	return active;
>  }
>  
> +static bool cfg80211_5ghz_is_wiphy_oper_chan(struct wiphy *wiphy,
> +					     struct
> ieee80211_channel *chan)

again, nothing really 5 GHz specific here, afaict?

> +	struct wireless_dev *wdev;
> +
> +	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;
> +}
> +
>  bool cfg80211_5ghz_any_wiphy_oper_chan(struct wiphy *wiphy,
>  				       struct ieee80211_channel
> *chan)
>  {
> -	struct wireless_dev *wdev;
> +	struct cfg80211_registered_device *rdev;
>  
>  	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))
> +	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
> +		if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
>  			continue;
>  
> -		if (cfg80211_5ghz_sub_chan(&wdev->chandef, chan))
> +		if (cfg80211_5ghz_is_wiphy_oper_chan(&rdev->wiphy,
> chan))
>  			return true;
>  	}
>  
> diff --git a/net/wireless/core.c b/net/wireless/core.c
> index 903fc419..c3fe44b 100644
> --- a/net/wireless/core.c
> +++ b/net/wireless/core.c
> @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct
> work_struct *work)
>  	rtnl_unlock();
>  }
>  
> +static void cfg80211_propagate_radar_detect_wk(struct work_struct
> *work)
> +{
> +	struct cfg80211_registered_device *rdev;
> +
> +	rdev = container_of(work, struct cfg80211_registered_device,
> +			    porpagate_radar_detect_wk);
> +
> +	rtnl_lock();
> +
> +	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev-
> >radar_chandef,
> +				       NL80211_DFS_UNAVAILABLE,
> +				       NL80211_RADAR_DETECTED);
> +
> +	rtnl_unlock();
> +}
> +
> +static void cfg80211_propagate_cac_done_wk(struct work_struct *work)
> +{
> +	struct cfg80211_registered_device *rdev;
> +
> +	rdev = container_of(work, struct cfg80211_registered_device,
> +			    propagate_cac_done_wk);
> +
> +	rtnl_lock();
> +
> +	regulatory_propagate_dfs_state(&rdev->wiphy, &rdev-
> >cac_done_chandef,
> +				       NL80211_DFS_AVAILABLE,
> +				       NL80211_RADAR_CAC_FINISHED);
> +
> +	rtnl_unlock();
> +}
> +
>  /* exported functions */
>  
>  struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int
> sizeof_priv,
> @@ -456,6 +488,9 @@ struct wiphy *wiphy_new_nm(const struct
> cfg80211_ops *ops, int sizeof_priv,
>  	spin_lock_init(&rdev->destroy_list_lock);
>  	INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
>  	INIT_WORK(&rdev->sched_scan_stop_wk,
> cfg80211_sched_scan_stop_wk);
> +	INIT_WORK(&rdev->porpagate_radar_detect_wk,
> +		  cfg80211_propagate_radar_detect_wk);
> +	INIT_WORK(&rdev->propagate_cac_done_wk,
> cfg80211_propagate_cac_done_wk);
>  
>  #ifdef CONFIG_CFG80211_DEFAULT_PS
>  	rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
> @@ -914,6 +949,8 @@ void wiphy_unregister(struct wiphy *wiphy)
>  	flush_work(&rdev->destroy_work);
>  	flush_work(&rdev->sched_scan_stop_wk);
>  	flush_work(&rdev->mlme_unreg_wk);
> +	flush_work(&rdev->porpagate_radar_detect_wk);

typo: propagate.

> +	flush_work(&rdev->propagate_cac_done_wk);

You got it right here :)
 
>  #ifdef CONFIG_PM
>  	if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
> diff --git a/net/wireless/core.h b/net/wireless/core.h
> index 327fe95..607c8be 100644
> --- a/net/wireless/core.h
> +++ b/net/wireless/core.h
> @@ -97,6 +97,12 @@ struct cfg80211_registered_device {
>  
>  	struct work_struct sched_scan_stop_wk;
>  
> +	struct cfg80211_chan_def radar_chandef;
> +	struct work_struct porpagate_radar_detect_wk;

Since it compiled, the typo exists everywhere this is referenced.

> +++ b/net/wireless/mlme.c
> @@ -18,7 +18,6 @@
>  #include "nl80211.h"
>  #include "rdev-ops.h"
>  
> -
>  void cfg80211_rx_assoc_resp(struct net_device *dev, struct
> cfg80211_bss *bss,

please don't make unrelated "cleanups".

> +bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2)
> +{
> +	const struct ieee80211_regdomain *wiphy1_regd = NULL;
> +	const struct ieee80211_regdomain *wiphy2_regd = NULL;
> +	const struct ieee80211_regdomain *cfg80211_regd = NULL;
> +	bool dfs_domain_same = false;

You can remove that initializer,

> +	rcu_read_lock();
> +
> +	cfg80211_regd = rcu_dereference(cfg80211_regdomain);
> +	wiphy1_regd = rcu_dereference(wiphy1->regd);
> +	if (!wiphy1_regd)
> +		wiphy1_regd = cfg80211_regd;
> +
> +	wiphy2_regd = rcu_dereference(wiphy2->regd);
> +	if (!wiphy2_regd)
> +		wiphy2_regd = cfg80211_regd;
> +
> +	if (wiphy1_regd->dfs_region == wiphy2_regd->dfs_region)
> +		dfs_domain_same = true;

and just assign
	dfs_domain_same = wiphy1... == wiphy2...;

> +static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy,
> +				       struct wiphy *src_wiphy)
> +{
> +	struct ieee80211_supported_band *src_sband, *dst_sband;
> +	int i, j;
> +
> +	dst_sband = dst_wiphy->bands[NL80211_BAND_5GHZ];
> +	src_sband = src_wiphy->bands[NL80211_BAND_5GHZ];
> +	if (!dst_sband || !src_sband)
> +		return;

Why make this 5 GHz specific? Perhaps some kind of radar stuff will
exist in future bands too. It shouldn't really cost much to iterate all
the bands, I think?

johannes



[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