From cb701a8dbe98a70d8cf2017ab7ad9d1a1c4cfaf6 Mon Sep 17 00:00:00 2001
From: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
Date: Thu, 9 Dec 2021 15:52:41 +0100
Subject: [PATCH] check opclass preference age

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
---
 src/cntlr.c      | 26 ++++++++++++++++++++++++++
 src/cntlr.h      |  1 +
 src/cntlr_cmdu.c | 13 +++++++++++++
 src/cntlr_cmdu.h |  1 +
 src/cntlr_map.c  |  6 ++++++
 5 files changed, 47 insertions(+)

diff --git a/src/cntlr.c b/src/cntlr.c
index 49de0b06..1124d5ab 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -1252,6 +1252,32 @@ void cntlr_radio_cur_opclass_dump(struct netif_radio *radio)
 	_cntlr_radio_opclass_dump(&radio->cur_opclass);
 }
 
+static bool cntlr_radio_opclass_expired(struct netif_radio *radio)
+{
+	time_t age;
+
+	if (!radio->opclass.opclass_entry_num)
+		return true;
+
+	age = time(NULL) - radio->opclass.opclass_entry_time;
+	if (((unsigned int) age) > 120)
+		return true;
+
+	return false;
+}
+
+bool cntlr_node_opclass_expired(struct node *node)
+{
+	struct netif_radio *radio;
+	bool expired = false;
+
+	list_for_each_entry(radio, &node->radiolist, list) {
+		expired |= cntlr_radio_opclass_expired(radio);
+	}
+
+	return expired;
+}
+
 static enum wifi_freqband cntlr_radio_opclass_get_band(struct opclass *opclass)
 {
 	enum wifi_freqband band;
diff --git a/src/cntlr.h b/src/cntlr.h
index 59b4c0e5..196e9cd4 100644
--- a/src/cntlr.h
+++ b/src/cntlr.h
@@ -438,5 +438,6 @@ int cntlr_radio_cur_opclass_add(struct netif_radio *radio, uint8_t opclass,
 void cntlr_radio_cur_opclass_reset(struct netif_radio *radio);
 void cntlr_radio_cur_opclass_dump(struct netif_radio *radio);
 void cntlr_radio_update_band(struct netif_radio *radio);
+bool cntlr_node_opclass_expired(struct node *node);
 
 #endif /* CNTLR_H */
diff --git a/src/cntlr_cmdu.c b/src/cntlr_cmdu.c
index 7e9adb05..49ae43bd 100644
--- a/src/cntlr_cmdu.c
+++ b/src/cntlr_cmdu.c
@@ -707,6 +707,19 @@ struct cmdu_buff *cntlr_gen_channel_preference_query(
 	return req;
 }
 
+int cntrl_send_channel_preference_query(struct controller *c, uint8_t *agent)
+{
+	struct cmdu_buff *cmdu;
+
+	cmdu = cntlr_gen_channel_preference_query(c, agent);
+	if (!cmdu)
+		return -1;
+	send_cmdu(c, cmdu);
+	cmdu_free(cmdu);
+
+	return 0;
+}
+
 struct cmdu_buff* cntlr_gen_cac_req(struct controller *c, uint8_t *agent,
 		int num_data, void *data)
 {
diff --git a/src/cntlr_cmdu.h b/src/cntlr_cmdu.h
index d96723e3..277c6b91 100644
--- a/src/cntlr_cmdu.h
+++ b/src/cntlr_cmdu.h
@@ -72,4 +72,5 @@ struct cmdu_buff *cntlr_gen_client_steer_request(struct controller *c,
 		uint8_t target_bssid[][6], uint32_t request_mode);
 struct cmdu_buff *cntlr_gen_comb_infra_metrics_query(struct controller *c,
 		uint8_t *origin, uint8_t *bssid_mac);
+int cntrl_send_channel_preference_query(struct controller *c, uint8_t *agent);
 #endif
diff --git a/src/cntlr_map.c b/src/cntlr_map.c
index aa738c2d..4e0b6dca 100644
--- a/src/cntlr_map.c
+++ b/src/cntlr_map.c
@@ -243,6 +243,12 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu)
 		}
 	}
 
+	/* Check opclass preferency age */
+	if (cntlr_node_opclass_expired(n)) {
+		trace("node " MACFMT " opclass expired\n", MAC2STR(n->alid));
+		cntrl_send_channel_preference_query(c, n->alid);
+	}
+
 	return 0;
 }
 
-- 
GitLab