From 05c1de699d9a127e6b32caa7d8a97ea05ee66852 Mon Sep 17 00:00:00 2001
From: Filip Matusiak <filip.matusiak@iopsys.eu>
Date: Fri, 9 Sep 2022 17:31:35 +0200
Subject: [PATCH] Add flag to allow steering STA to a BSSID on another band

Signed-off-by: Filip Matusiak <filip.matusiak@iopsys.eu>
---
 src/cntlr.c                   |  7 ++++---
 src/cntlr.h                   | 15 ++++++++-------
 src/config.c                  |  8 ++++++++
 src/config.h                  |  1 +
 src/plugins/steer/rcpi/rcpi.c | 25 +++++++++++++++++++------
 src/steer.h                   |  1 +
 src/wifi_dataelements.h       |  1 +
 7 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/src/cntlr.c b/src/cntlr.c
index dea752c2..97a3cb63 100644
--- a/src/cntlr.c
+++ b/src/cntlr.c
@@ -650,6 +650,7 @@ struct netif_iface *cntlr_radio_add_interface(struct controller *c,
 		return NULL;
 	}
 
+	n->band = get_band_from_opclass(r->radio_el->cur_opclass.entry[0].id);
 	n->bss->is_fbss = true;
 	n->bss->is_bbss = false;
 	n->bss->enabled = true;
@@ -733,8 +734,7 @@ static int get_bw_from_opclass(int op_class)
 	}
 }
 
-#if 0
-static enum wifi_freqband get_band_from_opclass(int opclass)
+enum wifi_freqband get_band_from_opclass(int opclass)
 {
 	/* TODO move to libwifi */
 
@@ -767,7 +767,6 @@ static enum wifi_freqband get_band_from_opclass(int opclass)
 		return BAND_UNKNOWN;
 	}
 }
-#endif
 
 uint8_t cntlr_get_classid_ht20(struct wifi_radio_element *radio, uint8_t channel)
 {
@@ -1882,6 +1881,8 @@ void run_controller(void)
 		scfg.rcpi_threshold = 100; /* TODO */
 		scfg.rcpi_hysteresis = 5; /* TODO */
 		scfg.rcpi_diffsnr = 10;
+		scfg.bandsteer = c->cfg.bandsteer;
+
 		cntlr_configure_steer_module(c, &scfg);
 	}
 
diff --git a/src/cntlr.h b/src/cntlr.h
index aca1a988..95a588ea 100644
--- a/src/cntlr.h
+++ b/src/cntlr.h
@@ -136,13 +136,13 @@ enum media_type {
 struct netif_iface {
 	char ifname[16];
 
-	int band;					/* TODO unused: deprecate */
-	enum media_type med_type;	/* TODO unused: deprecate */
-	uint32_t bssid_info;		/* TODO unused: deprecate */
-	uint8_t reg;				/* TODO unused: deprecate */
-	uint8_t phy;				/* TODO unused: deprecate */
-	int channel;				/* TODO unused: deprecate */
-	int capacity;				/* TODO unused: deprecate */
+	enum wifi_freqband band;
+	enum media_type med_type;	/* TODO unused */
+	uint32_t bssid_info;		/* TODO unused */
+	uint8_t reg;				/* TODO unused */
+	uint8_t phy;				/* TODO unused */
+	int channel;				/* TODO unused */
+	int capacity;				/* TODO unused */
 
 	struct node *agent;
 	uint8_t upstream_bssid[6]; /* in the case of the interface is a bsta interface */
@@ -374,6 +374,7 @@ int cntlr_radio_clean_scanlist_el(struct wifi_scanres_element *el);
 void free_bcn_metrics(struct controller *c, struct sta *s);
 void free_usta_metrics(struct controller *c, struct sta *s);
 
+enum wifi_freqband get_band_from_opclass(int opclass);
 uint8_t cntlr_get_classid_ht20(struct wifi_radio_element *radio, uint8_t channel);
 int cntlr_radio_opclass_add(struct wifi_radio_element *radio, uint8_t opclass,
 			    uint8_t channel, uint8_t preference);
diff --git a/src/config.c b/src/config.c
index cd89a29d..8319b59d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -562,6 +562,7 @@ static int cntlr_config_get_base(struct controller_config *c,
 		CNTLR_USE_USTA_METRICS,
 		CNTLR_INITIAL_CHANNEL_SCAN,
 		CNTLR_STEER_MODULE,
+		CNTLR_BANDSTEER,
 		CNTLR_CHANNEL_PLAN_TIMEOUT,
 		CNTLR_BGDFS_TIMEOUT,
 		CNTLR_PRIMARY_VID,
@@ -580,6 +581,7 @@ static int cntlr_config_get_base(struct controller_config *c,
 		{ .name = "use_usta_metrics", .type = UCI_TYPE_STRING },
 		{ .name = "initial_channel_scan", .type = UCI_TYPE_STRING },
 		{ .name = "steer_module", .type = UCI_TYPE_LIST },
+		{ .name = "bandsteer", .type = UCI_TYPE_STRING },
 		{ .name = "channel_plan", .type = UCI_TYPE_STRING },
 		{ .name = "allow_bgdfs", .type = UCI_TYPE_STRING },
 		{ .name = "primary_vid", .type = UCI_TYPE_STRING },
@@ -665,6 +667,12 @@ static int cntlr_config_get_base(struct controller_config *c,
 		dbg("\n");
 	}
 
+	if (tb[CNTLR_BANDSTEER]) {
+		const char *val = tb[CNTLR_BANDSTEER]->v.string;
+
+		c->bandsteer = atoi(val) == 1 ? true : false;
+	}
+
 	if (tb[CNTLR_CHANNEL_PLAN_TIMEOUT]) {
 		const char *val = tb[CNTLR_CHANNEL_PLAN_TIMEOUT]->v.string;
 
diff --git a/src/config.h b/src/config.h
index 2ee7ea0a..f4023d9e 100644
--- a/src/config.h
+++ b/src/config.h
@@ -131,6 +131,7 @@ struct controller_config {
 	bool use_bcn_metrics;
 	bool use_usta_metrics;
 	bool initial_channel_scan;
+	bool bandsteer;
 	int num_bss;
 	int num_apolicy;
 	int acs_timeout;
diff --git a/src/plugins/steer/rcpi/rcpi.c b/src/plugins/steer/rcpi/rcpi.c
index 0e47f8c1..5941aafc 100644
--- a/src/plugins/steer/rcpi/rcpi.c
+++ b/src/plugins/steer/rcpi/rcpi.c
@@ -23,6 +23,7 @@ struct rcpi_steer_control {
 	uint8_t low;
 	uint8_t hysteresis;
 	uint8_t rcpi_threshold;
+	bool bandsteer;
 	void *self;
 };
 
@@ -30,13 +31,22 @@ static int rcpi_steer_init(void **priv);
 static int rcpi_steer_config(void *priv, struct steer_config *cfg);
 static int rcpi_steer_exit(void *priv);
 
+static bool is_bandsteer_allowed(void *priv)
+{
+	struct rcpi_steer_control *sctrl = (struct rcpi_steer_control *)priv;
+
+	if (sctrl->bandsteer)
+		return true;
+
+	return false;
+}
+
 int rcpi_steer(void *priv, struct steer_sta *s)
 {
-	struct rcpi_steer_control *p = (struct rcpi_steer_control *)priv;
+	struct rcpi_steer_control *sctrl = (struct rcpi_steer_control *)priv;
 	struct wifi_sta_meas_report *b;
 
 	trace("%s: --------->\n", __func__);
-	UNUSED(p);	//TODO
 
 	s->verdict = STEER_VERDICT_UNDECIDED;
 	s->reason = STEER_REASON_UNDEFINED;
@@ -48,10 +58,14 @@ int rcpi_steer(void *priv, struct steer_sta *s)
 
 	s->best = list_first_entry(s->meas_reportlist, struct wifi_sta_meas_report, list);
 	list_for_each_entry(b, s->meas_reportlist, list) {
-		if ((b->rcpi - s->best->rcpi) > p->diffsnr) {
+		if ((b->rcpi - s->best->rcpi) > sctrl->diffsnr) {
 			dbg("%s: new best bcn from "MACFMT" with rcpi %d\n",
 			    __func__, MAC2STR(b->bssid), b->rcpi);
-			s->best = b;
+
+			if(!is_bandsteer_allowed(priv)
+				/* consider tBSS only from STA's current band */
+				&& get_band_from_opclass(b->opclass) != s->s->fh->band)
+					continue;
 		}
 	}
 
@@ -107,8 +121,7 @@ static int rcpi_steer_config(void *priv, struct steer_config *cfg)
 	p->rcpi_threshold = cfg->rcpi_threshold;
 	p->hysteresis = cfg->rcpi_hysteresis;
 	p->diffsnr = cfg->rcpi_diffsnr;
-
-	//TODO
+	p->bandsteer = cfg->bandsteer;
 
 	dbg("%s: <========================\n", __func__);
 
diff --git a/src/steer.h b/src/steer.h
index 0c013b7b..99def320 100644
--- a/src/steer.h
+++ b/src/steer.h
@@ -45,6 +45,7 @@ struct steer_config {
 	uint8_t rcpi_hysteresis;
 	uint8_t rcpi_diffsnr;
 	uint8_t ch_utilization;
+	bool bandsteer;
 };
 
 struct steer_sta {
diff --git a/src/wifi_dataelements.h b/src/wifi_dataelements.h
index 71d38106..e9acb676 100644
--- a/src/wifi_dataelements.h
+++ b/src/wifi_dataelements.h
@@ -24,6 +24,7 @@ enum wifi_freqband {
 	BAND_60      = 1 << 2,        /**< 0x4 for 60Ghz */
 	BAND_6       = 1 << 3,        /**< 0x8 for 6Ghz */
 	BAND_UNKNOWN = 1 << 4,        /**< 0x10 (and above) for unknown band */
+	__WIFI_FREQBAND_MAX
 };
 
 /** enum wifi_bw - bandwidth */
-- 
GitLab