Search Linux Wireless

[RFC wireless-next 2/3] wifi: cfg80211: set and report chandef CAC ongoing

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

 



In case of background Channel Availability Check we
can start it from any application or via iw. This patch
allow to track and check CAC state from user mode by
simple check phy channels eg. using iw phy1 channels
command.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@xxxxxxxxx>
---
 include/net/cfg80211.h       |  5 +++++
 include/uapi/linux/nl80211.h |  6 ++++++
 net/wireless/chan.c          | 25 +++++++++++++++++++++++++
 net/wireless/core.h          |  4 ++++
 net/wireless/mlme.c          |  5 +++++
 net/wireless/nl80211.c       |  8 ++++++++
 6 files changed, 53 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4072a67c9cc9..ae1052c2db4a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -191,6 +191,9 @@ enum ieee80211_channel_flags {
  *	on this channel.
  * @dfs_state_entered: timestamp (jiffies) when the dfs state was entered.
  * @dfs_cac_ms: DFS CAC time in milliseconds, this is valid for DFS channels.
+ * @cac_ongoing: true if CAC is currently in progress on this channel
+ * @cac_ongoing_time: timestamp (jiffies) when CAC was started on this channel.
+ *	Only valid when @cac_ongoing is true.
  * @psd: power spectral density (in dBm)
  */
 struct ieee80211_channel {
@@ -208,6 +211,8 @@ struct ieee80211_channel {
 	enum nl80211_dfs_state dfs_state;
 	unsigned long dfs_state_entered;
 	unsigned int dfs_cac_ms;
+	bool cac_ongoing;
+	unsigned long cac_ongoing_time;
 	s8 psd;
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index aed0b4c5d5e8..56e748afea4e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4396,6 +4396,10 @@ enum nl80211_wmm_rule {
  *	very low power (VLP) AP, despite being NO_IR.
  * @NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY: This channel can be active in
  *	20 MHz bandwidth, despite being NO_IR.
+ * @NL80211_FREQUENCY_ATTR_CAC_ONGOING: Channel Availability Check (CAC) is
+ *	currently in progress on this channel.
+ * @NL80211_FREQUENCY_ATTR_CAC_ONGOING_TIME: CAC ongoing time in milliseconds
+ *	since CAC started. Only present when CAC is ongoing.
  * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
  *	currently defined
  * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
@@ -4441,6 +4445,8 @@ enum nl80211_frequency_attr {
 	NL80211_FREQUENCY_ATTR_CAN_MONITOR,
 	NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP,
 	NL80211_FREQUENCY_ATTR_ALLOW_20MHZ_ACTIVITY,
+	NL80211_FREQUENCY_ATTR_CAC_ONGOING,
+	NL80211_FREQUENCY_ATTR_CAC_ONGOING_TIME,
 
 	/* keep last */
 	__NL80211_FREQUENCY_ATTR_AFTER_LAST,
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 193734b7f9dc..1833bafa2b03 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -646,6 +646,31 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
 	}
 }
 
+void cfg80211_set_cac_state(struct wiphy *wiphy,
+			     const struct cfg80211_chan_def *chandef,
+			     bool cac_ongoing)
+{
+	struct ieee80211_channel *c;
+	int width;
+
+	if (WARN_ON(!cfg80211_chandef_valid(chandef)))
+		return;
+
+	width = cfg80211_chandef_get_width(chandef);
+	if (width < 0)
+		return;
+
+	for_each_subchan(chandef, freq, cf) {
+		c = ieee80211_get_channel_khz(wiphy, freq);
+		if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
+			continue;
+
+		c->cac_ongoing = cac_ongoing;
+		if (cac_ongoing)
+			c->cac_ongoing_time = jiffies;
+	}
+}
+
 static bool
 cfg80211_dfs_permissive_check_wdev(struct cfg80211_registered_device *rdev,
 				   enum nl80211_iftype iftype,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index b6bd7f4d6385..c6da96e50fc4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -480,6 +480,10 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
 			    const struct cfg80211_chan_def *chandef,
 			    enum nl80211_dfs_state dfs_state);
 
+void cfg80211_set_cac_state(struct wiphy *wiphy,
+			     const struct cfg80211_chan_def *chandef,
+			     bool cac_ongoing);
+
 void cfg80211_dfs_channels_update_work(struct work_struct *work);
 
 void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 9afda72aea38..538f95d02b6a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1160,9 +1160,11 @@ void cfg80211_cac_event(struct net_device *netdev,
 		fallthrough;
 	case NL80211_RADAR_CAC_ABORTED:
 		wdev->links[link_id].cac_started = false;
+		cfg80211_set_cac_state(wiphy, chandef, false);
 		break;
 	case NL80211_RADAR_CAC_STARTED:
 		wdev->links[link_id].cac_started = true;
+		cfg80211_set_cac_state(wiphy, chandef, true);
 		break;
 	default:
 		WARN_ON(1);
@@ -1193,6 +1195,7 @@ __cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
 	switch (event) {
 	case NL80211_RADAR_CAC_FINISHED:
 		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE);
+		cfg80211_set_cac_state(wiphy, chandef, false);
 		memcpy(&rdev->cac_done_chandef, chandef, sizeof(*chandef));
 		queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk);
 		cfg80211_sched_dfs_chan_update(rdev);
@@ -1201,9 +1204,11 @@ __cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
 	case NL80211_RADAR_CAC_ABORTED:
 		if (!cancel_delayed_work(&rdev->background_cac_done_wk))
 			return;
+		cfg80211_set_cac_state(wiphy, chandef, false);
 		wdev = rdev->background_radar_wdev;
 		break;
 	case NL80211_RADAR_CAC_STARTED:
+		cfg80211_set_cac_state(wiphy, chandef, true);
 		break;
 	default:
 		return;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b7bc7e5e81dd..8235415e72cf 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1197,6 +1197,13 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
 					NL80211_FREQUENCY_ATTR_DFS_CAC_TIME,
 					chan->dfs_cac_ms))
 				goto nla_put_failure;
+			if (chan->cac_ongoing) {
+				if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_CAC_ONGOING))
+					goto nla_put_failure;
+				if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_CAC_ONGOING_TIME,
+						elapsed_jiffies_msecs(chan->cac_ongoing_time)))
+					goto nla_put_failure;
+			}
 		}
 	}
 
@@ -11142,6 +11149,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
 	wdev->links[link_id].cac_started = true;
 	wdev->links[link_id].cac_start_time = jiffies;
 	wdev->links[link_id].cac_time_ms = cac_time_ms;
+	cfg80211_set_cac_state(wiphy, &chandef, true);
 
 	return 0;
 }
-- 
2.43.0





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

  Powered by Linux