From 6ca866bc799b3880df833c9ee5e89eb15065afbf Mon Sep 17 00:00:00 2001
From: Filip Matusiak <filip.matusiak@iopsys.eu>
Date: Thu, 10 Nov 2022 11:57:00 +0100
Subject: [PATCH] Pause BTM of sticky clients for couple of minutes

Signed-off-by: Filip Matusiak <filip.matusiak@iopsys.eu>
---
 src/cntlr.c                   | 21 ++++++++++++++++-----
 src/cntlr.h                   |  2 +-
 src/cntlr_map.c               |  2 +-
 src/cntlr_ubus.c              |  4 ++--
 src/plugins/steer/rcpi/rcpi.c | 11 +++++++----
 src/steer_module.h            |  3 ++-
 6 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/src/cntlr.c b/src/cntlr.c
index 59a1007f..eb4b840e 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -392,9 +392,12 @@ void cntlr_update_sta_steer_counters(struct controller *c,
 		break;
 	case STEER_MODE_BTM_REQ:
 		a->method = STEER_METHOD_BTM_REQ;
+		/* Update SteeringSummaryStats - per STA & per Network */
+		s->stats.btm_attempt_cnt++;
 		break;
 	case STEER_MODE_OPPORTUNITY:
 		a->method = STEER_METHOD_ASYNC_BTM;
+		/*TODO: add counter for opportunity (incl blacklis count) */
 		break;
 	default:
 		a->method = STEER_METHOD_UNKNOWN;
@@ -408,7 +411,7 @@ void cntlr_update_sta_steer_counters(struct controller *c,
 	/*TODO: split counter for opportunity & mandate */
 	s->stats.btm_attempt_cnt++;
 	/* Record tsp for most recent steer attempt */
-	timestamp_update(&s->stats.last_steer_time);
+	timestamp_update(&s->stats.last_attempt_tsp);
 	s->num_steer_attempts += 1;
 }
 
@@ -521,9 +524,9 @@ static void cntlr_try_steer_sta(struct controller *c, struct sta *s)
 
 	switch (candidate.verdict) {
 	case STEER_VERDICT_OK:
-		if (!timestamp_expired(&s->stats.last_steer_time, STEER_ATTEMPT_MIN_INTV)) {
+		if (!timestamp_expired(&s->stats.last_attempt_tsp, STEER_ATTEMPT_MIN_ITV)) {
 			dbg("%s: last steer attempt < %us ago; skip steering\n",
-			    __func__, STEER_ATTEMPT_MIN_INTV / 1000);
+			    __func__, STEER_ATTEMPT_MIN_ITV / 1000);
 			return;
 		}
 		cntlr_steer_sta(c, s, candidate.best, candidate.mode, candidate.reason);
@@ -534,7 +537,15 @@ static void cntlr_try_steer_sta(struct controller *c, struct sta *s)
 		/* TODO: check next steer-control ? */
 		break;
 	case STEER_VERDICT_EXCLUDE:
-		/* TODO: exclude this STA from subsequent steer attempts */
+		/* STA excluded from subsequent steer attempts */
+		dbg("%s: sticky STA excluded from steering, elapsed %us of %us\n", __func__,
+			    timestamp_elapsed_sec(&s->stats.last_attempt_tsp),
+			    STEER_ATTEMPT_STICKY_ITV / 1000);
+		if (timestamp_expired(&s->stats.last_attempt_tsp, STEER_ATTEMPT_STICKY_ITV))
+			/* time up, allow steering again */
+			s->failed_steer_attempts = 0;
+
+		/* TODO: consider update of BTM steering disallowed STA list in agent */
 		break;
 	default:
 		break;
@@ -603,7 +614,7 @@ static void cntlr_init_sta_steer_counters(struct sta *s)
 	//s->stats.btm_success_cnt = 0;
 	//s->stats.btm_failure_cnt = 0;
 	//s->stats.btm_query_resp_cnt = 0;
-	//s->stats.last_steer_time = 0;
+	//s->stats.last_attempt_tsp = 0;
 }
 
 struct sta *cntlr_add_sta(struct controller *c, uint8_t *macaddr)
diff --git a/src/cntlr.h b/src/cntlr.h
index c4186bb7..b82db4fb 100644
--- a/src/cntlr.h
+++ b/src/cntlr.h
@@ -148,7 +148,7 @@ struct steer_stats {
 	/* Reperesents time this Associated Device was last attempted
 	 * to be steered. Calculate delta from now (secs) for reporting
 	 */
-	struct timespec last_steer_time;
+	struct timespec last_attempt_tsp;
 };
 
 struct sta {
diff --git a/src/cntlr_map.c b/src/cntlr_map.c
index d2119674..4f26d27b 100644
--- a/src/cntlr_map.c
+++ b/src/cntlr_map.c
@@ -318,7 +318,7 @@ int handle_topology_response(void *cntlr, struct cmdu_buff *cmdu)
 					s->type = IEEE1905;
 					s->agent = bsta->agent;
 					//s->failed_steer_attempts = 0;
-					//timestamp_reset(s->stats.last_steer_time);
+					//timestamp_reset(s->stats.last_attempt_tsp);
 				}
 			}
 		}
diff --git a/src/cntlr_ubus.c b/src/cntlr_ubus.c
index efebf7bd..8ee2b8f6 100644
--- a/src/cntlr_ubus.c
+++ b/src/cntlr_ubus.c
@@ -596,7 +596,7 @@ static int cntlr_status(struct ubus_context *ctx, struct ubus_object *obj,
 		blobmsg_add_u32(&bb, "ul_thput", s->ul_thput);
 		blobmsg_add_u32(&bb, "dl_thput", s->dl_thput);
 		blobmsg_add_u32(&bb, "ul_rcpi", s->ul_rcpi);
-		//blobmsg_add_u32(&bb, "last_steer_time", s->stats.last_steer_time);
+		//blobmsg_add_u32(&bb, "last_attempt_tsp", s->stats.last_attempt_tsp);
 		blobmsg_add_u32(&bb, "failed_steer_attempts", s->failed_steer_attempts);
 		//blobmsg_add_u16(&bb, "num_bcn_metrics", s->num_bcn_metrics);
 
@@ -818,7 +818,7 @@ static int cntlr_steer_summary(struct ubus_context *ctx, struct ubus_object *obj
 
 			if (!hwaddr_is_zero(macaddr))
 				blobmsg_add_u32(&bb, "time_since_steer",
-						timestamp_elapsed_sec(&s->stats.last_steer_time));
+						timestamp_elapsed_sec(&s->stats.last_attempt_tsp));
 		}
 
 	} else {
diff --git a/src/plugins/steer/rcpi/rcpi.c b/src/plugins/steer/rcpi/rcpi.c
index 2b032739..29ba215a 100644
--- a/src/plugins/steer/rcpi/rcpi.c
+++ b/src/plugins/steer/rcpi/rcpi.c
@@ -50,6 +50,12 @@ int rcpi_steer(void *priv, struct steer_sta *s)
 		return 0;
 	}
 
+	if (s->s->failed_steer_attempts > sctrl->max_btm_attempt) {
+		/* skip further checks for sticky candidates */
+		s->verdict = STEER_VERDICT_EXCLUDE;
+		return 0;
+	}
+
 	if (list_empty(s->bcnlist)) {
 		dbg("%s: report list is empty\n", __func__);
 		s->verdict = STEER_VERDICT_NOK;
@@ -118,14 +124,11 @@ int rcpi_steer(void *priv, struct steer_sta *s)
 
 	s->reason = STEER_REASON_LOW_RCPI;
 	s->verdict = STEER_VERDICT_OK;
-
 	if (s->s->failed_steer_attempts < sctrl->max_btm_attempt)
 		s->mode = STEER_MODE_BTM_REQ;
-	else
+	else if (s->s->failed_steer_attempts == sctrl->max_btm_attempt)
 		s->mode = STEER_MODE_ASSOC_CTL;
 
-	/* TODO: return STEER_VERDICT_EXCLUDE for more than X assoc cntlrs */
-
 	return 0;
 }
 
diff --git a/src/steer_module.h b/src/steer_module.h
index f91ae995..20e69024 100644
--- a/src/steer_module.h
+++ b/src/steer_module.h
@@ -21,7 +21,8 @@ extern "C" {
 
 #include "steer.h"
 
-#define STEER_ATTEMPT_MIN_INTV		30000 /* ms */
+#define STEER_ATTEMPT_MIN_ITV		(30 * 1000) 		/* 30 secs */
+#define STEER_ATTEMPT_STICKY_ITV	(10 * 60 * 1000)	/* 10 minutes */
 
 struct steer_control *cntlr_get_steer_control(struct controller *c);
 void cntlr_assign_steer_module_default(struct controller *c);
-- 
GitLab