[PATCH RFC 2/3] scan: add scan_freq_map

Alexander Ganslandt <[email protected]> Tue, 15 Apr 2025 10:21:13 +0200
Newsgroups dev.linux.lists.iwd
Message-ID <[email protected]>
This is a hashmap where the keys are freqs and the values are
timestamps. When a freq has been scanned, the timestamp for that freq is
updated to "now". The function scan_get_freq_age can be used for getting
the age of a freq, which is how long time ago it was last scanned.

This is useful for deciding if a certain freq should be scanned, or if
it's better to spend that time on scanning another freq.
---
 src/scan.c | 36 ++++++++++++++++++++++++++++++++++++
 src/scan.h |  2 ++
 2 files changed, 38 insertions(+)

diff --git a/src/scan.c b/src/scan.c
index aeab6516..f4c2e548 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -62,6 +62,7 @@ static uint32_t SCAN_MAX_INTERVAL;
 static uint32_t SCAN_INIT_INTERVAL;
 
 static struct l_queue *scan_contexts;
+static struct l_hashmap *scan_freq_map;
 
 static struct l_genl_family *nl80211;
 
@@ -2316,6 +2317,37 @@ static void scan_retry_pending(uint32_t wiphy_id)
 	}
 }
 
+static void scan_update_freq_map_entry(uint32_t freq, void *user_data)
+{
+	void *existing = l_hashmap_lookup(scan_freq_map, L_UINT_TO_PTR(freq));
+	uint64_t now = l_time_now();
+
+	if (existing) {
+		l_hashmap_remove(scan_freq_map, L_UINT_TO_PTR(freq));
+	}
+
+	l_hashmap_insert(scan_freq_map, L_UINT_TO_PTR(freq), L_UINT_TO_PTR(now));
+}
+
+static void scan_update_freq_map(struct scan_freq_set *freqs)
+{
+	scan_freq_set_foreach(freqs, scan_update_freq_map_entry, NULL);
+}
+
+uint64_t scan_get_freq_age(uint32_t freq)
+{
+	void *entry = l_hashmap_lookup(scan_freq_map, L_UINT_TO_PTR(freq));
+
+	if (entry) {
+		uint64_t timestamp = (uintptr_t) entry;
+		uint64_t now = l_time_now();
+
+		return (now - timestamp) / 1000000;
+	}
+
+	return UINT64_MAX;
+}
+
 static void scan_notify(struct l_genl_msg *msg, void *user_data)
 {
 	struct l_genl_attr attr;
@@ -2461,6 +2493,8 @@ static void scan_notify(struct l_genl_msg *msg, void *user_data)
 
 		scan_get_results(sc, sr, freqs);
 
+		scan_update_freq_map(freqs);
+
 		break;
 	}
 
@@ -2645,6 +2679,7 @@ static int scan_init(void)
 	const struct l_settings *config = iwd_get_config();
 
 	scan_contexts = l_queue_new();
+	scan_freq_map = l_hashmap_new();
 
 	RANK_2G_FACTOR = scan_get_band_rank_modifier(BAND_FREQ_2_4_GHZ);
 	RANK_5G_FACTOR = scan_get_band_rank_modifier(BAND_FREQ_5_GHZ);
@@ -2688,6 +2723,7 @@ static void scan_exit(void)
 	scan_contexts = NULL;
 	l_genl_family_free(nl80211);
 	nl80211 = NULL;
+	l_hashmap_destroy(scan_freq_map, NULL);
 }
 
 IWD_MODULE(scan, scan_init, scan_exit)
diff --git a/src/scan.h b/src/scan.h
index 4c1ebc21..135ffa5e 100644
--- a/src/scan.h
+++ b/src/scan.h
@@ -182,3 +182,5 @@ double scan_get_band_rank_modifier(enum band_freq band);
 
 bool scan_wdev_add(uint64_t wdev_id);
 bool scan_wdev_remove(uint64_t wdev_id);
+
+uint64_t scan_get_freq_age(uint32_t freq);

-- 
2.39.5