From 2dea6c3ec98ffbb41acf5406dd22cd30d471ecb4 Mon Sep 17 00:00:00 2001
From: Filip Matusiak <filip.matusiak@iopsys.eu>
Date: Thu, 18 May 2023 15:34:44 +0200
Subject: [PATCH] Adjust time to wait for beacon metrics dynamically

Signed-off-by: Filip Matusiak <filip.matusiak@iopsys.eu>
---
 src/cntlr.c     | 24 ++++++++++-------
 src/cntlr.h     |  4 ++-
 src/cntlr_map.c | 70 +++++++++++++++++++++++++++++++++++--------------
 3 files changed, 68 insertions(+), 30 deletions(-)

diff --git a/src/cntlr.c b/src/cntlr.c
index 68369b9c..badc8a9c 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -808,6 +808,7 @@ static void cntlr_bcn_metrics_parse(atimer_t *t)
 	struct netif_iface *bss = NULL;
 	struct wifi_sta_meas_report *b = NULL, *tmp;
 	struct steer_control_config *scc;
+	bool stale = true;
 
 	dbg("%s: STA " MACFMT" connected to " MACFMT " in Node " MACFMT"\n",
 	    __func__, MAC2STR(s->de_sta->macaddr), MAC2STR(s->bssid), MAC2STR(n->alid));
@@ -822,9 +823,22 @@ static void cntlr_bcn_metrics_parse(atimer_t *t)
 			free(b);
 			s->de_sta->num_meas_reports--;
 			dbg("Delete alien entry "MACFMT"\n", MAC2STR(b->bssid));
+			continue;
 		}
+
+		if (stale && !b->stale)
+			/* at least one fresh metric found */
+			stale = false;
+	}
+
+	if (stale) {
+		/* only stale metrics, reschedule parse of the results */
+		timer_set(&s->bcn_metrics_timer,
+				s->bcn_report_wait_time * 1000);
+		return;
 	}
 
+	/* Steer */
 	scc = get_steer_control_config(c);
 	if (!scc)
 		return;
@@ -1284,16 +1298,6 @@ void free_bcn_metrics(struct controller *c, struct sta *s)
 	}
 }
 
-void cntlr_mark_old_bcn_metrics(struct controller *c, struct sta *s)
-{
-	struct wifi_sta_meas_report *b = NULL, *tmp;
-
-	list_for_each_entry_safe(b, tmp, &s->de_sta->meas_reportlist, list) {
-		/* TODO: only most recent measurement marked as fresh */
-		b->stale = true;
-	}
-}
-
 void free_usta_metrics(struct controller *c, struct sta *s)
 {
 	struct una_sta_metrics *u = NULL, *tmp;
diff --git a/src/cntlr.h b/src/cntlr.h
index da80e94b..e7510ba4 100644
--- a/src/cntlr.h
+++ b/src/cntlr.h
@@ -136,6 +136,9 @@ struct sta {
 	struct node *agent; /* the agent representing an IEEE1905 device, only applicable for backhaul stations */
 	atimer_t bcn_metrics_timer;
 	struct timespec last_bcn_metrics_query;
+#define BCN_REPORT_WAIT_MAX 60
+#define BCN_REPORT_STALE_TIME 20
+	int bcn_report_wait_time; /* maximum time to wait for bcn response in seconds */
 	int latest_assoc_cntrl_mid;
 
 #define BTM_RESP_EXP_TIMEOUT 5
@@ -400,7 +403,6 @@ bool cntlr_resync_config(struct controller *c, bool reload);
 
 int cntlr_radio_clean_scanlist_el(struct wifi_scanres_element *el);
 void free_bcn_metrics(struct controller *c, struct sta *s);
-void cntlr_mark_old_bcn_metrics(struct controller *c, struct sta *s);
 void free_usta_metrics(struct controller *c, struct sta *s);
 
 int cntlr_radio_pref_opclass_add(struct wifi_radio_element *radio, uint8_t opclass,
diff --git a/src/cntlr_map.c b/src/cntlr_map.c
index 040c5745..dd9e56a4 100644
--- a/src/cntlr_map.c
+++ b/src/cntlr_map.c
@@ -2128,6 +2128,54 @@ int handle_link_metrics_response(struct controller *c, struct cmdu_buff *cmdu,
 	return 0;
 }
 
+void cntlr_mark_bcnlist_stale(struct controller *c, struct sta *s)
+{
+	struct wifi_sta_meas_report *b = NULL, *tmp;
+
+	list_for_each_entry_safe(b, tmp, &s->de_sta->meas_reportlist, list) {
+		b->stale = true;
+	}
+}
+
+static void cntlr_get_bcn_metrics(struct controller *c, struct sta *s)
+{
+	int num_req = 0;
+	int wt = BCN_REPORT_STALE_TIME;
+
+	if (s->bcn_report_wait_time > BCN_REPORT_STALE_TIME)
+		wt = s->bcn_report_wait_time;
+
+	if (!timestamp_expired(&s->last_bcn_metrics_query, wt * 1000)) {
+		/* Avoid too frequent beacon requests */
+		dbg("|%s:%d| skipping new bcn metrics req - to early\n",
+		    __func__, __LINE__);
+		return;
+	}
+
+	/* Mark all old metrics stale */
+	cntlr_mark_bcnlist_stale(c, s);
+
+	/* Get fresh metrics */
+	dbg("|%s:%d| requesting beacon metrics from " MACFMT "\n",
+	    __func__, __LINE__, MAC2STR(s->de_sta->macaddr));
+	num_req = cntlr_request_bcn_metrics_sta(c, s);
+	if (WARN_ON(num_req <= 0))
+		return;
+
+	timestamp_update(&s->last_bcn_metrics_query);
+
+	if (num_req * 3 <= BCN_REPORT_WAIT_MAX)
+		/* agent needs 3 secs for each channel */
+		s->bcn_report_wait_time = num_req * 3;
+	else
+		s->bcn_report_wait_time = BCN_REPORT_WAIT_MAX;
+
+	/* Schedule parse of the results */
+	dbg("|%s:%d| (re)scheduling response parse in %d seconds\n",
+	    __func__, __LINE__, s->bcn_report_wait_time);
+	timer_set(&s->bcn_metrics_timer, s->bcn_report_wait_time * 1000);
+}
+
 int handle_sta_link_metrics_response(void *cntlr, struct cmdu_buff *cmdu,
 				     struct node *n)
 {
@@ -2205,7 +2253,7 @@ int handle_sta_link_metrics_response(void *cntlr, struct cmdu_buff *cmdu,
 			if (scc->use_bcn_metrics) {
 				dbg("|%s:%d| request bcn metrics from bsta\n",
 				    __func__, __LINE__);
-				cntlr_mark_old_bcn_metrics(c, s);
+				cntlr_mark_bcnlist_stale(c, s);
 				cntlr_request_bcn_metrics_bsta(c, s);
 				/* TODO: set timeout here (?) */
 			}
@@ -2221,24 +2269,8 @@ int handle_sta_link_metrics_response(void *cntlr, struct cmdu_buff *cmdu,
 			}
 
 			/* Get bcn metrics */
-			if (scc->use_bcn_metrics) {
-				int num_req = 0;
-
-				/* FIXME: consider dynamic timer value */
-				if (timestamp_expired(&s->last_bcn_metrics_query, 20 * 1000)) {
-					dbg("|%s:%d| requesting bcn metrics from sta\n",
-					    __func__, __LINE__);
-					cntlr_mark_old_bcn_metrics(c, s);
-					num_req = cntlr_request_bcn_metrics_sta(c, s);
-					if (num_req > 0) {
-						timestamp_update(&s->last_bcn_metrics_query);
-						timer_set(&s->bcn_metrics_timer, num_req * 3 * 1000);
-					}
-				} else {
-					dbg("|%s:%d| skip requesting bcn metrics - up to date\n",
-					    __func__, __LINE__);
-				}
-			}
+			if (scc->use_bcn_metrics)
+				cntlr_get_bcn_metrics(c,s);
 
 			/* Get usta metrics for each agent in mesh */
 			if (scc->use_usta_metrics) {
-- 
GitLab