diff mbox series

[usteer,v3,9/9] New aggr. levels combined with STA specific configuration

Message ID 20241107112313.507-10-n.rottgardt@gmail.com
State New
Headers show
Series Better handling of unfriendly STAs / IEEE enhancements / MBO | expand

Commit Message

Nils Hendrik Rottgardt Nov. 7, 2024, 11:23 a.m. UTC
- band_steering: changed config option
- band_steering: handle aggressivness levels in bss transition requests
- local_node: avoid kick reset on bss tm respone if aggressivness is 3
- local_node: changed config option
- main: changed config option
- policy: changed config option
- policy: handle aggressivness levels in bss transition requests
- policy: SM stay in ROAM_TRIGGER_SCAN_DONE until disassoc_timer is over
- policy: roaming skipped if there was a positiv BSS-TM-RESP with code = 0
- policy: load mac list from options to set specific aggressivness per sta
- ubus: correct log message (typo)
- ubus: reassoc_delay is send with diasaccociation imminent = true only
- ubus: changed config option

Signed-off-by: Nils Hendrik Rottgardt <n.rottgardt@gmail.com>
---
 band_steering.c                        |  7 ++++--
 local_node.c                           | 18 +++++++--------
 main.c                                 |  2 +-
 openwrt/usteer/files/etc/config/usteer | 15 +++++++-----
 openwrt/usteer/files/etc/init.d/usteer |  4 ++--
 policy.c                               | 32 ++++++++++++++++++++++----
 sta.c                                  | 30 +++++++++++++-----------
 ubus.c                                 | 10 ++++----
 usteer.h                               | 11 +++++----
 9 files changed, 81 insertions(+), 48 deletions(-)
diff mbox series

Patch

diff --git a/band_steering.c b/band_steering.c
index 17eca32..a3dfd62 100644
--- a/band_steering.c
+++ b/band_steering.c
@@ -100,10 +100,13 @@  void usteer_band_steering_perform_steer(struct usteer_local_node *ln)
 		if (si->bss_transition) {
 			si->roam_transition_request_validity_end = current_time + 10000;
 			validity_period = 10000 / usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */
-			if (si->sta->aggressive) {
+			if (si->sta->aggressiveness >= 2) {
 				if (!si->kick_time)
 					si->kick_time = current_time + config.roam_kick_delay;
-				disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln);
+				if (si->sta->aggressiveness >= 3)
+					disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln);
+				else
+					disassoc_timer = 0;
 				usteer_ubus_band_steering_request(si, 0, true, disassoc_timer, true, validity_period);
 			} else
 				usteer_ubus_band_steering_request(si, 0, false, 0, true, validity_period);
diff --git a/local_node.c b/local_node.c
index 89490d7..b38f96f 100644
--- a/local_node.c
+++ b/local_node.c
@@ -180,10 +180,10 @@  usteer_handle_bss_tm_response(struct usteer_local_node *ln, struct blob_attr *ms
 	si->bss_transition_response.status_code = blobmsg_get_u8(tb[BSS_TM_RESPONSE_STATUS_CODE]);
 	si->bss_transition_response.timestamp = current_time;
 
-	if (si->bss_transition_response.status_code) {
+	if (si->bss_transition_response.status_code && si->kick_time && si->sta->aggressiveness) {
 		/* Cancel imminent kick in case BSS transition was rejected */
 		si->kick_time = 0;
-		MSG(VERBOSE, "Kick canceled because transition was rejected by sta=" MAC_ADDR_FMT "\n", MAC_ADDR_DATA(si->sta->addr));
+		MSG(VERBOSE, "Kick canceled because transition rejected by sta=" MAC_ADDR_FMT "\n", MAC_ADDR_DATA(si->sta->addr));
 	}
 
 	return 0;
@@ -978,20 +978,20 @@  void config_get_ssid_list(struct blob_buf *buf)
 		blobmsg_add_blob(buf, config.ssid_list);
 }
 
-void config_set_aggressive_mac_list(struct blob_attr *data)
+void config_set_aggressiveness_mac_list(struct blob_attr *data)
 {
-	free(config.aggressive_mac_list);
+	free(config.aggressiveness_mac_list);
 
 	if (data && blobmsg_len(data))
-		config.aggressive_mac_list = blob_memdup(data);
+		config.aggressiveness_mac_list = blob_memdup(data);
 	else
-		config.aggressive_mac_list = NULL;
+		config.aggressiveness_mac_list = NULL;
 }
 
-void config_get_aggressive_mac_list(struct blob_buf *buf)
+void config_get_aggressiveness_mac_list(struct blob_buf *buf)
 {
-	if (config.aggressive_mac_list)
-		blobmsg_add_blob(buf, config.aggressive_mac_list);
+	if (config.aggressiveness_mac_list)
+		blobmsg_add_blob(buf, config.aggressiveness_mac_list);
 }
 
 void usteer_local_nodes_init(struct ubus_context *ctx)
diff --git a/main.c b/main.c
index 69e05ae..e4a6fd0 100644
--- a/main.c
+++ b/main.c
@@ -97,7 +97,7 @@  void usteer_init_defaults(void)
 	config.initial_connect_delay = 0;
 	config.remote_node_timeout = 10;
 	config.reassociation_delay = 30;
-	config.aggressive_all = false;
+	config.aggressiveness = 3;
 
 	config.steer_reject_timeout = 60000;
 
diff --git a/openwrt/usteer/files/etc/config/usteer b/openwrt/usteer/files/etc/config/usteer
index 9d343e7..cd8c060 100644
--- a/openwrt/usteer/files/etc/config/usteer
+++ b/openwrt/usteer/files/etc/config/usteer
@@ -73,14 +73,17 @@  config usteer
 	# Timeout (ms) for which a client will not be steered after rejecting a BSS-transition-request
 	#option steer_reject_timeout 60000
 
-	# Timeout (s "1024ms") a station is requested to avoid reassociation after bss transition
+	# Timeout (s "1024ms") a station is requested to avoid reassociation after BSS-transition
 	#option reassociation_delay 30
 	
-	# Use aggressive roaming to push clients to another AP for all stations (0/1)
-	#option aggressive_all 0
-
-	# List of MACs (lower case) to enable aggressive roaming on. If not set all stations will handled aggressive
-	#list aggressive_mac_list ''
+	# Aggressiveness of roaming to push a station to another node
+	# 0 = no active roaming / 1 = passive roaming / 2 = roaming with disassociation imminent
+	# 3 = roaming with disassociation imminent and timer
+	# 4 = roaming with disassociation imminent, timer and forced disassociation
+	#option aggressiveness 3
+
+	# List of MACs (lower case) to set aggressiveness per station (ff:ff:ff:ff:ff,2)
+	#list aggressiveness_mac_list ''
 
 	# Timeout (in ms) after which a association following a disassociation is not seen
 	# as a roam
diff --git a/openwrt/usteer/files/etc/init.d/usteer b/openwrt/usteer/files/etc/init.d/usteer
index d517f93..e155bd5 100755
--- a/openwrt/usteer/files/etc/init.d/usteer
+++ b/openwrt/usteer/files/etc/init.d/usteer
@@ -69,10 +69,10 @@  uci_usteer() {
 	uci_option_to_json_bool "$cfg" local_mode
 	uci_option_to_json_bool "$cfg" load_kick_enabled
 	uci_option_to_json_bool "$cfg" assoc_steering
-	uci_option_to_json_bool "$cfg" aggressive_all
+	uci_option_to_json_bool "$cfg" aggressiveness
 	uci_option_to_json_string "$cfg" node_up_script
 	uci_option_to_json_string_array "$cfg" ssid_list
-	uci_option_to_json_string_array "$cfg" aggressive_mac_list
+	uci_option_to_json_string_array "$cfg" aggressiveness_mac_list
 	uci_option_to_json_string_array "$cfg" event_log_types
 
 	for opt in \
diff --git a/policy.c b/policy.c
index 933c529..61017a2 100644
--- a/policy.c
+++ b/policy.c
@@ -366,6 +366,13 @@  usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
 		break;
 
 	case ROAM_TRIGGER_SCAN_DONE:
+		/* Roaming time over, switch back to ROAM_TRIGGER_IDLE */
+		if (si->roam_transition_start && current_time - si->roam_transition_start > config.roam_kick_delay) {
+			si->roam_transition_start = 0;
+			usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
+			break;
+		}
+
 		candidate = usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_SCAN_DONE);
 		/* Kick back in case no better node is found */
 		if (!candidate) {
@@ -376,18 +383,27 @@  usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
 		if (!candidate->node->rrm_nr)
 			MSG(FATAL, "Candiates node rrm nr not returned from hostapd. Neighbor list empty!");
 
+		if (!si->roam_transition_start)
+			si->roam_transition_start = current_time;
 		si->roam_transition_request_validity_end = current_time + 10000;
 		validity_period = 10000 / usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */
-		if (si->sta->aggressive) {
+		if (si->sta->aggressiveness >= 2) {
 			if (!si->kick_time)
 				si->kick_time = current_time + config.roam_kick_delay;
-			disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln);
+			if (si->sta->aggressiveness >= 3)
+				disassoc_timer = (si->kick_time - current_time) / usteer_local_node_get_beacon_interval(ln);
+			else
+				disassoc_timer = 0;
 			usteer_ubus_bss_transition_request(si, 1, true, disassoc_timer, true, validity_period, candidate->node);
+			/* Countdown end */
+			if (disassoc_timer < validity_period) {
+				si->roam_transition_start = 0;
+				usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
+			}
 		} else {
 			usteer_ubus_bss_transition_request(si, 1, false, 0, true, validity_period, candidate->node);
+			usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
 		}
-
-		usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
 		break;
 	}
 
@@ -400,6 +416,10 @@  bool usteer_policy_can_perform_roam(struct sta_info *si)
 	if (si->connected != STA_CONNECTED)
 		return false;
 
+	/* Only trigger for STA with active roaming */
+	if (!si->sta->aggressiveness)
+		return false;
+
 	/* Skip on pending kick */
 	if (si->kick_time && si->kick_time <= current_time)
 		return false;
@@ -412,6 +432,10 @@  bool usteer_policy_can_perform_roam(struct sta_info *si)
 	if (si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.steer_reject_timeout)
 		return false;
 
+	/* Skip if transition accepted */
+	if (!si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.roam_kick_delay)
+		return false;
+
 	/* Skip on previous kick attempt */
 	if (current_time - si->roam_kick < config.roam_trigger_interval)
 		return false;
diff --git a/sta.c b/sta.c
index 6cce149..059e987 100644
--- a/sta.c
+++ b/sta.c
@@ -77,24 +77,26 @@  usteer_sta_info_timeout(struct usteer_timeout_queue *q, struct usteer_timeout *t
 }
 
 static void
-usteer_sta_update_aggressive(struct sta *sta)
+usteer_sta_update_aggressiveness(struct sta *sta)
 {
 	struct blob_attr *cur;
 	int rem;
 	char sta_mac[18];
+	char config_entry[20];
+	char config_mac[18];
+	
 	sprintf(sta_mac, MAC_ADDR_FMT, MAC_ADDR_DATA(sta->addr));
-
-	if (config.aggressive_all)
-		sta->aggressive = true;
-	else {
-		sta->aggressive = false;
-		blobmsg_for_each_attr(cur, config.aggressive_mac_list, rem) {
-			if (strcmp(blobmsg_get_string(cur), sta_mac) != 0)
-				continue;
-
-			sta->aggressive = true;
-			break;
-		}
+	sta->aggressiveness = config.aggressiveness;
+	blobmsg_for_each_attr(cur, config.aggressiveness_mac_list, rem) {
+		strcpy(config_entry, blobmsg_get_string(cur));
+		if (strlen(config_entry) != 19)
+			continue;
+		strncpy(config_mac, config_entry, 18);
+		config_mac[17] = '\0';
+		if (strcmp(config_mac, sta_mac) != 0)
+			continue;
+		sta->aggressiveness = config_entry[18] - '0';
+		break;
 	}
 }
 
@@ -127,7 +129,7 @@  usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create)
 	si->created = current_time;
 	*create = true;
 
-	usteer_sta_update_aggressive(sta);
+	usteer_sta_update_aggressiveness(sta);
 
 	/* Node is by default not connected. */
 	usteer_sta_disconnected(si);
diff --git a/ubus.c b/ubus.c
index 8d0f2be..efa3a15 100644
--- a/ubus.c
+++ b/ubus.c
@@ -162,8 +162,8 @@  struct cfg_item {
 	_cfg(U32, remote_update_interval), \
 	_cfg(U32, remote_node_timeout), \
 	_cfg(BOOL, assoc_steering), \
-	_cfg(BOOL, aggressive_all), \
-	_cfg(ARRAY_CB, aggressive_mac_list), \
+	_cfg(U32, aggressiveness), \
+	_cfg(ARRAY_CB, aggressiveness_mac_list), \
 	_cfg(U32, aggressive_disassoc_timer), \
 	_cfg(I32, min_connect_snr), \
 	_cfg(I32, min_snr), \
@@ -686,18 +686,18 @@  int usteer_ubus_bss_transition_request(struct sta_info *si,
 	blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
 	if (disassoc_imminent) {
 		blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer);
+		blobmsg_add_u32(&b, "reassoc_delay", config.reassociation_delay);
 	}
 	blobmsg_add_u8(&b, "abridged", abridged);
 	blobmsg_add_u32(&b, "validity_period", validity_period);
 	blobmsg_add_u32(&b, "mbo_reason", 5);
-	blobmsg_add_u32(&b, "reassoc_delay", config.reassociation_delay);
 
 	if (!target_node) {
 		// Add all known neighbors if no specific target set
 		MSG(VERBOSE, "ROAMING sta=" MAC_ADDR_FMT " without target\n", MAC_ADDR_DATA(si->sta->addr));
 		usteer_ubus_disassoc_add_neighbors(si);
 	} else {
-		MSG(VERBOSE, "ROAMING sta=" MAC_ADDR_FMT " to " MAC_ADDR_FMT " (%s) disassociation timer %u\n", MAC_ADDR_DATA(target_node->bssid), MAC_ADDR_DATA(si->sta->addr), usteer_node_name(target_node), disassoc_timer);
+		MSG(VERBOSE, "ROAMING sta=" MAC_ADDR_FMT " to " MAC_ADDR_FMT " (%s) disassociation timer %u\n", MAC_ADDR_DATA(si->sta->addr), MAC_ADDR_DATA(target_node->bssid), usteer_node_name(target_node), disassoc_timer);
 		usteer_ubus_disassoc_add_neighbor(si, target_node);
 	}
 	return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request", b.head, NULL, 0, 100);
@@ -720,11 +720,11 @@  int usteer_ubus_band_steering_request(struct sta_info *si,
 	blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent);
 	if (disassoc_imminent) {
 		blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer);
+		blobmsg_add_u32(&b, "reassoc_delay", config.reassociation_delay);
 	}
 	blobmsg_add_u8(&b, "abridged", abridged);
 	blobmsg_add_u32(&b, "validity_period", validity_period);
 	blobmsg_add_u32(&b, "mbo_reason", 5);
-	blobmsg_add_u32(&b, "reassoc_delay", config.reassociation_delay);
 
 	c = blobmsg_open_array(&b, "neighbors");
 	for_each_local_node(node) {
diff --git a/usteer.h b/usteer.h
index 15e3911..ee24dbe 100644
--- a/usteer.h
+++ b/usteer.h
@@ -170,8 +170,8 @@  struct usteer_config {
 	uint32_t remote_update_interval;
 	uint32_t remote_node_timeout;
 
-	bool aggressive_all;
-	struct blob_attr *aggressive_mac_list;
+	uint32_t aggressiveness;
+	struct blob_attr *aggressiveness_mac_list;
 	uint32_t aggressive_disassoc_timer;
 	uint32_t reassociation_delay;
 
@@ -260,6 +260,7 @@  struct sta_info {
 	uint8_t roam_tries;
 	uint64_t roam_event;
 	uint64_t roam_transition_request_validity_end;
+	uint64_t roam_transition_start;
 	uint64_t roam_kick;
 	uint64_t roam_scan_start;
 	uint64_t roam_scan_timeout_start;
@@ -291,7 +292,7 @@  struct sta {
 	uint8_t seen_2ghz : 1;
 	uint8_t seen_5ghz : 1;
 
-	bool aggressive;
+	uint32_t aggressiveness;
 
 	uint8_t addr[6];
 };
@@ -390,8 +391,8 @@  void config_get_node_up_script(struct blob_buf *buf);
 void config_set_ssid_list(struct blob_attr *data);
 void config_get_ssid_list(struct blob_buf *buf);
 
-void config_set_aggressive_mac_list(struct blob_attr *data);
-void config_get_aggressive_mac_list(struct blob_buf *buf);
+void config_set_aggressiveness_mac_list(struct blob_attr *data);
+void config_get_aggressiveness_mac_list(struct blob_buf *buf);
 
 int usteer_interface_init(void);
 void usteer_interface_add(const char *name);