diff mbox series

[v2,2/8] wiphy: parse/store frequency info in band object

Message ID 20221216172606.1799396-2-prestwoj@gmail.com (mailing list archive)
State Accepted, archived
Headers show
Series [v2,1/8] band: introduce new method of tracking frequencies | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success
prestwoj/iwd-ci-gitlint success GitLint

Commit Message

James Prestwood Dec. 16, 2022, 5:26 p.m. UTC
As additional frequency info is needed it doesn't make sense to
store a full list of frequencies for every attribute (i.e.
supported, disabled, no-IR, etc).

This changes nl80211_parse_supported_frequencies to take a list
of frequency attributes where each index corresponds to a channel,
and each value can be filled with flag bits to signal any
limitations on that frequency.

wiphy.c then had to be updated to use this rather than the existing
scan_freq_set lists. This, as-is, will break anything using
wiphy_get_disabled_freqs().
---
 src/nl80211util.c | 22 +++++++++++----
 src/nl80211util.h |  6 +++--
 src/wiphy.c       | 68 +++++++++++++++++++++++++++++++++++++++++++----
 src/wiphy.h       |  2 ++
 4 files changed, 86 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/src/nl80211util.c b/src/nl80211util.c
index da36d936..712cdec3 100644
--- a/src/nl80211util.c
+++ b/src/nl80211util.c
@@ -502,19 +502,21 @@  int nl80211_parse_chandef(struct l_genl_msg *msg, struct band_chandef *out)
 
 int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs,
 					struct scan_freq_set *supported_list,
-					struct scan_freq_set *disabled_list)
+					struct band_freq_attrs *list,
+					size_t num_channels)
 {
 	uint16_t type, len;
 	const void *data;
 	struct l_genl_attr attr;
 	struct l_genl_attr nested;
+	uint8_t channel;
 
 	if (!l_genl_attr_recurse(band_freqs, &nested))
 		return -EBADMSG;
 
 	while (l_genl_attr_next(&nested, NULL, NULL, NULL)) {
 		uint32_t freq = 0;
-		bool disabled = false;
+		struct band_freq_attrs freq_attr = { 0 };
 
 		if (!l_genl_attr_recurse(&nested, &attr))
 			continue;
@@ -523,9 +525,13 @@  int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs,
 			switch (type) {
 			case NL80211_FREQUENCY_ATTR_FREQ:
 				freq = *((uint32_t *) data);
+				freq_attr.supported = true;
 				break;
 			case NL80211_FREQUENCY_ATTR_DISABLED:
-				disabled = true;
+				freq_attr.disabled = true;
+				break;
+			case NL80211_FREQUENCY_ATTR_NO_IR:
+				freq_attr.no_ir = true;
 				break;
 			}
 		}
@@ -533,11 +539,17 @@  int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs,
 		if (!freq)
 			continue;
 
+		channel = band_freq_to_channel(freq, NULL);
+		if (!channel)
+			continue;
+
+		if (L_WARN_ON(channel > num_channels))
+			continue;
+
 		if (supported_list)
 			scan_freq_set_add(supported_list, freq);
 
-		if (disabled && disabled_list)
-			scan_freq_set_add(disabled_list, freq);
+		list[channel] = freq_attr;
 	}
 
 	return 0;
diff --git a/src/nl80211util.h b/src/nl80211util.h
index 44555a25..d26d286f 100644
--- a/src/nl80211util.h
+++ b/src/nl80211util.h
@@ -24,6 +24,7 @@ 
 
 struct band_chandef;
 struct scan_freq_set;
+struct band_freq_attrs;
 
 int nl80211_parse_attrs(struct l_genl_msg *msg, int tag, ...);
 
@@ -58,5 +59,6 @@  struct l_genl_msg *nl80211_build_cmd_frame(uint32_t ifindex,
 
 int nl80211_parse_chandef(struct l_genl_msg *msg, struct band_chandef *out);
 int nl80211_parse_supported_frequencies(struct l_genl_attr *band_freqs,
-					struct scan_freq_set *supported,
-					struct scan_freq_set *disabled);
+					struct scan_freq_set *supported_list,
+					struct band_freq_attrs *list,
+					size_t num_channels);
diff --git a/src/wiphy.c b/src/wiphy.c
index 37e0cdb8..6b8f00a1 100644
--- a/src/wiphy.c
+++ b/src/wiphy.c
@@ -745,8 +745,35 @@  void wiphy_generate_address_from_ssid(struct wiphy *wiphy, const char *ssid,
 bool wiphy_constrain_freq_set(const struct wiphy *wiphy,
 						struct scan_freq_set *set)
 {
+	struct band *bands[3] = { wiphy->band_2g,
+					wiphy->band_5g, wiphy->band_6g };
+	unsigned int b;
+	unsigned int i;
+
 	scan_freq_set_constrain(set, wiphy->supported_freqs);
-	scan_freq_set_subtract(set, wiphy->disabled_freqs);
+
+	for (b = 0; b < L_ARRAY_SIZE(bands); b++) {
+		struct band *band = bands[b];
+
+		if (!band)
+			continue;
+
+		for (i = 0; i < band->freqs_len; i++) {
+			uint32_t freq;
+
+			if (!band->freq_attrs[i].supported)
+				continue;
+
+			if (!band->freq_attrs[i].disabled)
+				continue;
+
+			freq = band_channel_to_freq(i, band->freq);
+			if (!freq)
+				continue;
+
+			scan_freq_set_remove(set, freq);
+		}
+	}
 
 	if (!scan_freq_set_get_bands(set))
 		/* The set is empty. */
@@ -1471,19 +1498,23 @@  static void parse_supported_bands(struct wiphy *wiphy,
 		struct band **bandp;
 		struct band *band;
 		enum band_freq freq;
+		size_t num_channels;
 
 		switch (type) {
 		case NL80211_BAND_2GHZ:
 			bandp = &wiphy->band_2g;
 			freq = BAND_FREQ_2_4_GHZ;
+			num_channels = 14;
 			break;
 		case NL80211_BAND_5GHZ:
 			bandp = &wiphy->band_5g;
 			freq = BAND_FREQ_5_GHZ;
+			num_channels = 196;
 			break;
 		case NL80211_BAND_6GHZ:
 			bandp = &wiphy->band_6g;
 			freq = BAND_FREQ_6_GHZ;
+			num_channels = 233;
 			break;
 		default:
 			continue;
@@ -1498,6 +1529,9 @@  static void parse_supported_bands(struct wiphy *wiphy,
 				continue;
 
 			band->freq = freq;
+			band->freq_attrs = l_new(struct band_freq_attrs,
+							num_channels);
+			band->freqs_len = num_channels;
 
 			/* Reset iter to beginning */
 			if (!l_genl_attr_recurse(bands, &attr)) {
@@ -1507,7 +1541,6 @@  static void parse_supported_bands(struct wiphy *wiphy,
 		} else
 			band = *bandp;
 
-
 		while (l_genl_attr_next(&attr, &type, &len, &data)) {
 			struct l_genl_attr nested;
 
@@ -1515,7 +1548,8 @@  static void parse_supported_bands(struct wiphy *wiphy,
 			case NL80211_BAND_ATTR_FREQS:
 				nl80211_parse_supported_frequencies(&attr,
 							wiphy->supported_freqs,
-							wiphy->disabled_freqs);
+							band->freq_attrs,
+							band->freqs_len);
 				break;
 
 			case NL80211_BAND_ATTR_RATES:
@@ -1970,6 +2004,7 @@  static void wiphy_dump_callback(struct l_genl_msg *msg,
 	struct l_genl_attr bands;
 	struct l_genl_attr attr;
 	uint16_t type;
+	struct band *band;
 
 	if (nl80211_parse_attrs(msg, NL80211_ATTR_WIPHY, &id,
 					NL80211_ATTR_WIPHY_BANDS, &bands,
@@ -1980,7 +2015,24 @@  static void wiphy_dump_callback(struct l_genl_msg *msg,
 	if (L_WARN_ON(!wiphy))
 		return;
 
-	while (l_genl_attr_next(&bands, NULL, NULL, NULL)) {
+	while (l_genl_attr_next(&bands, &type, NULL, NULL)) {
+		switch (type) {
+		case NL80211_BAND_2GHZ:
+			band = wiphy->band_2g;
+			break;
+		case NL80211_BAND_5GHZ:
+			band = wiphy->band_5g;
+			break;
+		case NL80211_BAND_6GHZ:
+			band = wiphy->band_6g;
+			break;
+		default:
+			continue;
+		}
+
+		if (L_WARN_ON(!band))
+			continue;
+
 		if (!l_genl_attr_recurse(&bands, &attr))
 			return;
 
@@ -1988,8 +2040,14 @@  static void wiphy_dump_callback(struct l_genl_msg *msg,
 			if (type != NL80211_BAND_ATTR_FREQS)
 				continue;
 
+			/*
+			 * Just write over the old list for each frequency. In
+			 * theory no new frequencies should be added so there
+			 * should never be any stale values.
+			 */
 			nl80211_parse_supported_frequencies(&attr, NULL,
-							wiphy->pending_freqs);
+							band->freq_attrs,
+							band->freqs_len);
 		}
 	}
 }
diff --git a/src/wiphy.h b/src/wiphy.h
index 410105dd..09dc4530 100644
--- a/src/wiphy.h
+++ b/src/wiphy.h
@@ -28,6 +28,7 @@  struct scan_bss;
 struct scan_freq_set;
 struct wiphy_radio_work_item;
 struct ie_rsn_info;
+struct band_freq_attrs;
 enum security;
 enum band_freq;
 
@@ -100,6 +101,7 @@  uint32_t wiphy_get_supported_bands(struct wiphy *wiphy);
 const struct scan_freq_set *wiphy_get_supported_freqs(
 						const struct wiphy *wiphy);
 const struct scan_freq_set *wiphy_get_disabled_freqs(const struct wiphy *wiphy);
+
 bool wiphy_supports_probe_resp_offload(struct wiphy *wiphy);
 bool wiphy_can_transition_disable(struct wiphy *wiphy);
 bool wiphy_can_offload(struct wiphy *wiphy);