From a3cd0bdad386a4fc18d004c57aca4dea002fea15 Mon Sep 17 00:00:00 2001
From: Filip Matusiak <filip.matusiak@iopsys.eu>
Date: Mon, 9 Dec 2024 15:51:16 +0100
Subject: [PATCH] Allow immediate handling of lost BH

---
 src/agent.c    |  8 ++++----
 src/agent.h    |  2 +-
 src/backhaul.c | 43 +++++++++++++++++++++++++++++--------------
 src/backhaul.h |  2 +-
 4 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/agent.c b/src/agent.c
index fdd34ec19..e8b1d7aa2 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -4690,14 +4690,14 @@ static void wifi_bsta_event_scan_failed(struct agent *a, struct netif_bk *bk)
 	return;
 }
 
-void agent_handle_bh_lost(struct agent *a, struct netif_bk *bk)
+void agent_handle_bh_lost(struct agent *a, struct netif_bk *bk, bool immediate)
 {
 	char ul_ifname[16] = {0};
 
 	if (!bk->cfg->enabled)
 		return;
 
-	dynbh_handle_bh_lost(a, bk);
+	dynbh_handle_bh_lost(a, bk, immediate);
 
 	if (agent_get_backhaul_ifname(a, ul_ifname)) {
 		if (!strncmp(ul_ifname, bk->ifname, IFNAMSIZ)) {
@@ -4858,7 +4858,7 @@ static void wifi_bsta_event_handler(void *agent, struct blob_attr *msg)
 
 		bk->connected = false;
 		/* Handle link loss if this was supposed to be an active bsta */
-		agent_handle_bh_lost(a, bk);
+		agent_handle_bh_lost(a, bk, false);
 
 		wifi_mod_bridge(a, bk, false);
 		a->connected = agent_is_bsta_connected(a);
@@ -5927,7 +5927,7 @@ static void bk_toggle(struct agent *a, struct netif_bk *bk,
 		/* check if part of the bridge */
 		if (if_isbridge_interface(bk->ifname)) {
 			wifi_mod_bridge(a, bk, false);
-			agent_handle_bh_lost(a, bk);
+			agent_handle_bh_lost(a, bk, false);
 		}
 	}
 }
diff --git a/src/agent.h b/src/agent.h
index e225e7c01..f97a8a6df 100644
--- a/src/agent.h
+++ b/src/agent.h
@@ -1148,7 +1148,7 @@ void agent_set_post_scan_action_pref(struct agent *agent, struct wifi_radio_elem
 bool is_channel_supported_by_radio(struct wifi_radio_element *r,
 				   uint8_t opclass,
 				   uint8_t channel);
-void agent_handle_bh_lost(struct agent *a, struct netif_bk *bk);
+void agent_handle_bh_lost(struct agent *a, struct netif_bk *bk, bool immediate);
 int agent_send_ch_scan_response(struct agent *a, struct wifi_radio_element *ndev,
 		struct wifi_scan_request_radio *req);
 bool agent_ch_scan_succesful(struct agent *a);
diff --git a/src/backhaul.c b/src/backhaul.c
index ba28f8c81..3044dcc08 100644
--- a/src/backhaul.c
+++ b/src/backhaul.c
@@ -378,28 +378,27 @@ void dynbh_bh_reconf_cb(atimer_t *t)
 	agent_config_reload(a);
 }
 
-void dynbh_bh_lost_cb(atimer_t *t)
+static int dynbh_bh_lost(struct agent *a)
 {
 	trace("%s: --->\n", __func__);
 
-	struct agent *a = container_of(t, struct agent, bh_lost_timer);
 	struct agent_config *cfg;
 	struct dyn_bh_cfg *c;
 
 	if (!a)
-		return;
+		return -1;
 
 	cfg = &a->cfg;
 	if (!cfg) {
 		err("%s:%d - missing configuration!\n", __func__, __LINE__);
-		return;
+		return -1;
 	}
 
 	c = &cfg->dbhcfg;
 	if (!c) {
 		err("%s:%d - missing dynamic backhaul configuration!\n",
 		    __func__, __LINE__);
-		return;
+		return -1;
 	}
 
 	dbg("|%s:%d| backhaul link loss timeout: %d sec\n",
@@ -408,7 +407,7 @@ void dynbh_bh_lost_cb(atimer_t *t)
 	if (agent_is_backhaul_type_eth() && c->bh_miss_tmo) {
 		/* additional time */
 		timer_set(&a->bh_lost_timer, c->bh_miss_tmo * 1000);
-		return;
+		return -1;
 	}
 
 #ifdef AGENT_ISLAND_PREVENTION
@@ -431,9 +430,23 @@ void dynbh_bh_lost_cb(atimer_t *t)
 	if (timer_remaining_ms(&a->bh_reconf_timer) == -1)
 		timer_set(&a->bh_reconf_timer,
 				  (c->bh_reconf_tmo - c->bh_miss_tmo) * 1000);
+
+	return 0;
 }
 
-int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk)
+void dynbh_bh_lost_cb(atimer_t *t)
+{
+	trace("%s: --->\n", __func__);
+
+	struct agent *a = container_of(t, struct agent, bh_lost_timer);
+
+	if (!a)
+		return;
+
+	dynbh_bh_lost(a);
+}
+
+int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk, bool immediate)
 {
 	trace("|%s:%d| detected backhaul link loss bk:%s!\n",
 		  __func__, __LINE__, bk->ifname);
@@ -444,7 +457,6 @@ int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk)
 	if (!a)
 		return -1;
 
-
 	if (!agent_is_backhaul_type_eth() && !agent_bsta_steer_is_active_all(a)) {
 		char fmt[128] = {0};
 
@@ -452,10 +464,10 @@ int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk)
 		agent_exec_platform_scripts(fmt);
 	}
 
-
 	cfg = &a->cfg;
 	if (!cfg) {
-		err("%s:%d - missing configuration!\n", __func__, __LINE__);
+		err("%s:%d - missing configuration!\n",
+		    __func__, __LINE__);
 		return -1;
 	}
 
@@ -467,13 +479,16 @@ int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk)
 	}
 
 	dbg("|%s:%d| backhaul link loss timeout: %d sec\n",
-		  __func__, __LINE__, c->bh_miss_tmo);
+	    __func__, __LINE__, c->bh_miss_tmo);
 
-	if (c->bh_miss_tmo && timer_remaining_ms(&a->bh_lost_timer) == -1)
-		/* Trigger bh link loss timer */
+	/* Trigger bh link loss timer */
+	if (immediate)
+		dynbh_bh_lost(a);
+	else if (c->bh_miss_tmo && timer_remaining_ms(&a->bh_lost_timer) == -1)
 		timer_set(&a->bh_lost_timer, c->bh_miss_tmo * 1000);
 
 	timestamp_update(&a->disconnect_t);
+
 	return 0;
 }
 
@@ -620,7 +635,7 @@ void agent_manage_bsta(struct agent *a, struct netif_bk *bk)
 		if (if_isbridge_interface(ifname)) {
 			wifi_mod_bridge(a, bk, false);
 			/* Handle bk link loss if this is an active bsta */
-			agent_handle_bh_lost(a, bk);
+			agent_handle_bh_lost(a, bk, false);
 		}
 	}
 }
diff --git a/src/backhaul.h b/src/backhaul.h
index 453f6dbae..20cc22931 100644
--- a/src/backhaul.h
+++ b/src/backhaul.h
@@ -27,7 +27,7 @@ void dynbh_upgrade_backhaul_cb(atimer_t *t);
 void dynbh_bh_reconf_cb(atimer_t *t);
 void dynbh_bh_lost_cb(atimer_t *t);
 void dynbh_disable_unconnected_bsta_cb(atimer_t *t);
-int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk);
+int dynbh_handle_bh_lost(struct agent *a, struct netif_bk *bk, bool immediate);
 
 void agent_check_bsta_connections(struct agent *a);
 void agent_manage_bsta(struct agent *a, struct netif_bk *bk);
-- 
GitLab