From 730da44db25a687e910544f4b2fe4313deb6479c Mon Sep 17 00:00:00 2001
From: Janusz Dziedzic <janusz.dziedzic@iopsys.eu>
Date: Wed, 20 Sep 2023 11:08:02 +0200
Subject: [PATCH] Add CAC action support

---
 src/agent_map.c | 17 ++++++++++++++++-
 src/wifi.c      |  4 ++--
 src/wifi.h      |  2 +-
 src/wifi_ubus.c |  8 +++++---
 src/wifi_ubus.h |  3 ++-
 src/wifidefs.h  |  6 ++++++
 6 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/agent_map.c b/src/agent_map.c
index 825a09dc4..d06cf997a 100644
--- a/src/agent_map.c
+++ b/src/agent_map.c
@@ -5724,9 +5724,11 @@ int handle_cac_request(void *agent, struct cmdu_buff *cmdu, struct node *n)
 
 	for (i = 0; i < cac_request->num_radio; i++) {
 		enum wifi_cac_method method;
+		enum wifi_cac_completion_action action;
 		enum wifi_bw bw;
 		uint32_t cac_time;
 		int cac_method;
+		int cac_action;
 		int opclass;
 		int channel;
 
@@ -5738,6 +5740,7 @@ int handle_cac_request(void *agent, struct cmdu_buff *cmdu, struct node *n)
 		bw = get_op_class_wifi_bw(cac_request->radio[i].opclass);
 		opclass = cac_request->radio[i].opclass;
 		cac_method = (cac_request->radio[i].mode & CAC_REQUEST_METHOD) >> 5;
+		cac_action = (cac_request->radio[i].mode & CAC_REQUEST_COMPLETE_ACTION) >> 3;
 		switch (cac_method) {
 		case 0:
 			method = WIFI_CAC_CONTINUOUS;
@@ -5753,6 +5756,18 @@ int handle_cac_request(void *agent, struct cmdu_buff *cmdu, struct node *n)
 			break;
 		}
 
+		switch (cac_action) {
+		case 0:
+			action = WIFI_CAC_REMAIN_ON_CHANNEL_AND_MONITOR;
+			break;
+		case 1:
+			action = WIFI_CAC_RETURN_TO_RECENT_CHANNEL;
+			break;
+		default:
+			action = WIFI_CAC_RETURN_TO_RECENT_CHANNEL;
+			break;
+		}
+
 		/* Check if CAC ongoing */
 		if (re->cac_request.channel) {
 			/* Already ongoing */
@@ -5802,7 +5817,7 @@ int handle_cac_request(void *agent, struct cmdu_buff *cmdu, struct node *n)
 		}
 
 		/* Finally run CAC */
-		ret = wifi_start_cac(re->name, channel, bw, method);
+		ret = wifi_start_cac(re->name, channel, bw, method, action);
 		if (ret) {
 			re->cac_request.report_failed = true;
 			re->cac_request.report_failed_channel = channel;
diff --git a/src/wifi.c b/src/wifi.c
index ad82a0aea..90adc7143 100644
--- a/src/wifi.c
+++ b/src/wifi.c
@@ -45,12 +45,12 @@ int wifi_del_neighbor(const char *ifname, unsigned char *bssid)
 }
 
 int wifi_start_cac(const char *name, int channel, enum wifi_bw bw,
-		   enum wifi_cac_method method)
+		   enum wifi_cac_method method, enum wifi_cac_completion_action action)
 {
 	struct ubus_context *ctx = ubus_connect(NULL);
 	int ret;
 
-	ret = wifi_ubus_start_cac(ctx, name, channel, bw, method);
+	ret = wifi_ubus_start_cac(ctx, name, channel, bw, method, action);
 
 	ubus_free(ctx);
 	return ret;
diff --git a/src/wifi.h b/src/wifi.h
index 58fad1fa8..77e94cb9e 100644
--- a/src/wifi.h
+++ b/src/wifi.h
@@ -118,7 +118,7 @@ int wifi_scan(const char *name, struct scan_param_ex *p,
 	      int num_channel, uint8_t *channel);
 int wifi_get_scan_results(const char *name, struct wifi_bss *bsss, int *num);
 int wifi_start_cac(const char *name, int channel, enum wifi_bw bw,
-		   enum wifi_cac_method method);
+		   enum wifi_cac_method method, enum wifi_cac_completion_action action);
 int wifi_stop_cac(const char *name);
 int wifi_opclass_preferences(const char *radio,
 			     struct wifi_radio_opclass *opclass);
diff --git a/src/wifi_ubus.c b/src/wifi_ubus.c
index 782e917e8..8ad53130d 100644
--- a/src/wifi_ubus.c
+++ b/src/wifi_ubus.c
@@ -121,7 +121,8 @@ out:
 }
 
 int wifi_ubus_start_cac(struct ubus_context *ubus_ctx, const char *radio, int channel,
-			enum wifi_bw bw, enum wifi_cac_method method)
+			enum wifi_bw bw, enum wifi_cac_method method,
+			enum wifi_cac_completion_action action)
 {
 	struct blob_buf bb = {};
 	int bandwidth;
@@ -129,8 +130,8 @@ int wifi_ubus_start_cac(struct ubus_context *ubus_ctx, const char *radio, int ch
 	uint32_t id;
 	int ret;
 
-	trace("[%s] %s %d/%d method %d\n", radio, __func__,
-	      channel, bw, method);
+	trace("[%s] %s %d/%d method %d action %d\n", radio, __func__,
+	      channel, bw, method, action);
 
 	switch (bw) {
 	case BW20:
@@ -161,6 +162,7 @@ int wifi_ubus_start_cac(struct ubus_context *ubus_ctx, const char *radio, int ch
 	blobmsg_add_u32(&bb, "channel", channel);
 	blobmsg_add_u32(&bb, "bandwidth", bandwidth);
 	blobmsg_add_u32(&bb, "method", method);
+	blobmsg_add_u32(&bb, "action", action);
 
 	ret = ubus_invoke(ubus_ctx, id, "start_cac", bb.head, NULL, NULL, 3 * 1000);
 	blob_buf_free(&bb);
diff --git a/src/wifi_ubus.h b/src/wifi_ubus.h
index 66614ffa2..193269e0d 100644
--- a/src/wifi_ubus.h
+++ b/src/wifi_ubus.h
@@ -17,7 +17,8 @@ int wifi_ubus_scan(struct ubus_context *ubus_ctx, const char *radio,
 int wifi_ubus_ap_set_state(struct ubus_context *ubus_ctx, const char *name, bool up);
 
 int wifi_ubus_start_cac(struct ubus_context *ubus_ctx, const char *radio,
-			int channel, enum wifi_bw bw, enum wifi_cac_method method);
+			int channel, enum wifi_bw bw, enum wifi_cac_method method,
+			enum wifi_cac_completion_action action);
 int wifi_ubus_stop_cac(struct ubus_context *ubus_ctx, const char *radio);
 int wifi_ubus_del_neighbor(struct ubus_context *ubus_ctx, const char *ifname, uint8_t *bssid);
 int wifi_ubus_add_neighbor(struct ubus_context *ubus_ctx, const char *ifname, struct nbr *nbr);
diff --git a/src/wifidefs.h b/src/wifidefs.h
index b068c93aa..7483dd177 100644
--- a/src/wifidefs.h
+++ b/src/wifidefs.h
@@ -237,6 +237,12 @@ enum wifi_cac_method {
 	WIFI_CAC_TIME_SLICED,
 };
 
+/** enum wifi_cac_completion_action - for successful CAC */
+enum wifi_cac_completion_action {
+	WIFI_CAC_REMAIN_ON_CHANNEL_AND_MONITOR,
+	WIFI_CAC_RETURN_TO_RECENT_CHANNEL,
+};
+
 /** @struct mimo_rate - used for phyrate calculation */
 struct mimo_rate {
 	uint8_t mcs;        /**< MCS value */
-- 
GitLab