From c43d6699e3a618a3269f3b299ee7673eb8f44099 Mon Sep 17 00:00:00 2001 From: Nils Hendrik Rottgardt <n.rottga...@gmail.com> Date: Sat, 19 Oct 2024 21:20:36 +0200 Subject: [usteer] New aggressive roaming to support Intel Wifi Cards (and also other devices)
Intel Wifi Cards does not understand the actual implementation because of missing disassociation_timer and disassociation_imminent = true. So they and other devices send a BSS-TM-RESP with status=1 (error). This patch with add some new options to correct this behavior and also fix the wrong bss_transition_request call. - Added aggressive roaming (disaccociation_timer) and corrected calling bss_transition_request with disassociation_imminent = false. - Added 3 new options in config to control aggressive roaming for all or specific MAC addresses. Signed-off-by: Nils Hendrik Rottgardt <n.rottga...@gmail.com> --- band_steering.c | 11 ++++- local_node.c | 21 +++++++-- main.c | 2 + openwrt/usteer/files/etc/config/usteer | 9 ++++ openwrt/usteer/files/etc/init.d/usteer | 4 +- policy.c | 20 +++++++-- sta.c | 26 +++++++++++ ubus.c | 61 +++++++++++++++++++------- usteer.h | 30 ++++++++++--- 9 files changed, 152 insertions(+), 32 deletions(-) diff --git a/band_steering.c b/band_steering.c index 7fce1df..7b2ee00 100644 --- a/band_steering.c +++ b/band_steering.c @@ -86,13 +86,20 @@ void usteer_band_steering_perform_steer(struct usteer_local_node *ln) continue; /* Skip clients with insufficient SNR-state */ - if (si->band_steering.below_snr) { + if (si->band_steering.below_snr) + { si->band_steering.below_snr = false; continue; } if (si->bss_transition) - usteer_ubus_band_steering_request(si); + { + // usteer_ubus_band_steering_request(si, 0, false, 100, true, 100); + if (si->sta->aggressive) + usteer_ubus_band_steering_request(si, 0, true, config.aggressive_disassoc_timer, true, config.aggressive_disassoc_timer); + else + usteer_ubus_band_steering_request(si, 0, false, 0, true, 100); + } si->band_steering.below_snr = false; } diff --git a/local_node.c b/local_node.c index e74d945..6aa7008 100644 --- a/local_node.c +++ b/local_node.c @@ -748,7 +748,7 @@ usteer_local_node_process_bss_tm_queries(struct uloop_timeout *timeout) if (!si) continue; - usteer_ubus_bss_transition_request(si, query->dialog_token, false, false, validity_period, NULL); + usteer_ubus_bss_transition_request(si, query->dialog_token, config.aggressive_all, validity_period, true, validity_period, NULL); } /* Free pending queries we can not handle */ @@ -977,8 +977,23 @@ void config_get_ssid_list(struct blob_buf *buf) blobmsg_add_blob(buf, config.ssid_list); } -void -usteer_local_nodes_init(struct ubus_context *ctx) +void config_set_aggressive_mac_list(struct blob_attr *data) +{ + free(config.aggressive_mac_list); + + if (data && blobmsg_len(data)) + config.aggressive_mac_list = blob_memdup(data); + else + config.aggressive_mac_list = NULL; +} + +void config_get_aggressive_mac_list(struct blob_buf *buf) +{ + if (config.aggressive_mac_list) + blobmsg_add_blob(buf, config.aggressive_mac_list); +} + +void usteer_local_nodes_init(struct ubus_context *ctx) { usteer_register_events(ctx); ubus_lookup(ctx, "hostapd.*", node_list_cb, NULL); diff --git a/main.c b/main.c index 99aa6ad..b07b624 100644 --- a/main.c +++ b/main.c @@ -96,6 +96,8 @@ void usteer_init_defaults(void) config.remote_update_interval = 1000; config.initial_connect_delay = 0; config.remote_node_timeout = 10; + config.aggressive_all = false; + config.aggressive_disassoc_timer = 100; config.steer_reject_timeout = 60000; diff --git a/openwrt/usteer/files/etc/config/usteer b/openwrt/usteer/files/etc/config/usteer index f53c338..2fe47f3 100644 --- a/openwrt/usteer/files/etc/config/usteer +++ b/openwrt/usteer/files/etc/config/usteer @@ -71,6 +71,15 @@ config usteer # Timeout (ms) for which a client will not be steered after rejecting a BSS-transition-request #option steer_reject_timeout 60000 + # Use aggressvice roaming to push clients to another AP + #option aggressive_all 0 + + # List of MACs to enable aggressive roaming on. If not set all macs will handled aggressive + #list aggressive_mac_list '' + + # Disassociation imminent tuner - in aggresive mode the time a client has to roam away before disconnected hardly + #option aggressive_disassoc_timer 100 + # Timeout (in ms) after which a association following a disassociation is not seen # as a roam #option roam_process_timeout 5000 diff --git a/openwrt/usteer/files/etc/init.d/usteer b/openwrt/usteer/files/etc/init.d/usteer index 07fd99e..fdc8211 100755 --- a/openwrt/usteer/files/etc/init.d/usteer +++ b/openwrt/usteer/files/etc/init.d/usteer @@ -69,8 +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_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" event_log_types for opt in \ @@ -84,7 +86,7 @@ uci_usteer() { initial_connect_delay steer_reject_timeout roam_process_timeout\ roam_kick_delay roam_scan_tries roam_scan_timeout \ roam_scan_snr roam_scan_interval \ - roam_trigger_snr roam_trigger_interval \ + roam_trigger_snr roam_trigger_interval aggressive_disassoc_timer\ band_steering_interval band_steering_min_snr link_measurement_interval \ load_kick_threshold load_kick_delay load_kick_min_clients \ load_kick_reason_code diff --git a/policy.c b/policy.c index 8c5d244..856c03e 100644 --- a/policy.c +++ b/policy.c @@ -370,8 +370,18 @@ usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si) break; } - usteer_ubus_bss_transition_request(si, 1, false, false, 100, candidate->node); - si->kick_time = current_time + config.roam_kick_delay; + if (si->sta->aggressive) + { + // TODO: Disaccociation Timer noch konfigurierbar machen + usteer_ubus_bss_transition_request(si, 1, true, config.aggressive_disassoc_timer, true, config.aggressive_disassoc_timer, candidate->node); + si->roam_disassoc_time = current_time + (100 * 100); + } + else + { + usteer_ubus_bss_transition_request(si, 1, false, 0, true, 100, candidate->node); + si->kick_time = current_time + config.roam_kick_delay; + } + usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev); break; } @@ -400,7 +410,11 @@ bool usteer_policy_can_perform_roam(struct sta_info *si) /* Skip if connection is established shorter than the trigger-interval */ if (current_time - si->connected_since < config.roam_trigger_interval) return false; - + + /* Skip on aggressive roaming in progress - wait 10s after disassociation event*/ + if (current_time - si->roam_disassoc_time < 10000) + return false; + return true; } diff --git a/sta.c b/sta.c index ed7e40e..ee8cbb1 100644 --- a/sta.c +++ b/sta.c @@ -76,6 +76,30 @@ usteer_sta_info_timeout(struct usteer_timeout_queue *q, struct usteer_timeout *t usteer_sta_info_del(si); } +static void +usteer_sta_update_aggressive(struct sta *sta) +{ + struct blob_attr *cur; + int rem; + char sta_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; + } + } +} + struct sta_info * usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create) { @@ -105,6 +129,8 @@ usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create) si->created = current_time; *create = true; + usteer_sta_update_aggressive(sta); + /* Node is by default not connected. */ usteer_sta_disconnected(si); diff --git a/ubus.c b/ubus.c index 40daf74..918255c 100644 --- a/ubus.c +++ b/ubus.c @@ -162,6 +162,9 @@ 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, aggressive_disassoc_timer), \ _cfg(I32, min_connect_snr), \ _cfg(I32, min_snr), \ _cfg(U32, min_snr_kick_delay), \ @@ -668,11 +671,12 @@ usteer_ubus_disassoc_add_neighbors(struct sta_info *si) } int usteer_ubus_bss_transition_request(struct sta_info *si, - uint8_t dialog_token, - bool disassoc_imminent, - bool abridged, - uint8_t validity_period, - struct usteer_node *target_node) + uint8_t dialog_token, + bool disassoc_imminent, + uint8_t disassoc_timer, + bool abridged, + uint8_t validity_period, + struct usteer_node *target_node) { struct usteer_local_node *ln = container_of(si->node, struct usteer_local_node, node); @@ -680,17 +684,32 @@ int usteer_ubus_bss_transition_request(struct sta_info *si, blobmsg_printf(&b, "addr", MAC_ADDR_FMT, MAC_ADDR_DATA(si->sta->addr)); blobmsg_add_u32(&b, "dialog_token", dialog_token); blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent); + if (disassoc_imminent) + { + blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer); + } blobmsg_add_u8(&b, "abridged", abridged); blobmsg_add_u32(&b, "validity_period", validity_period); - if (!target_node) { + if (!target_node) + { + // Add all known neighbors if no specific target set + MSG(DEBUG, "ROAMING requested for sta=" MAC_ADDR_FMT " without target\n", MAC_ADDR_DATA(si->sta->addr)); usteer_ubus_disassoc_add_neighbors(si); - } else { + } + else + { + MSG(DEBUG, "ROAMING requested for sta=" MAC_ADDR_FMT " to %s with disassociation timer %i\n", MAC_ADDR_DATA(si->sta->addr), 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); } -int usteer_ubus_band_steering_request(struct sta_info *si) +int usteer_ubus_band_steering_request(struct sta_info *si, + uint8_t dialog_token, + bool disassoc_imminent, + uint8_t disassoc_timer, + bool abridged, + uint8_t validity_period) { struct usteer_local_node *ln = container_of(si->node, struct usteer_local_node, node); struct usteer_node *node; @@ -698,21 +717,31 @@ int usteer_ubus_band_steering_request(struct sta_info *si) blob_buf_init(&b, 0); blobmsg_printf(&b, "addr", MAC_ADDR_FMT, MAC_ADDR_DATA(si->sta->addr)); - blobmsg_add_u32(&b, "dialog_token", 0); - blobmsg_add_u8(&b, "disassociation_imminent", false); - blobmsg_add_u8(&b, "abridged", false); - blobmsg_add_u32(&b, "validity_period", 100); + blobmsg_add_u32(&b, "dialog_token", dialog_token); + blobmsg_add_u8(&b, "disassociation_imminent", disassoc_imminent); + if (disassoc_imminent) + { + blobmsg_add_u32(&b, "disassociation_timer", disassoc_timer); + } + blobmsg_add_u8(&b, "abridged", abridged); + blobmsg_add_u32(&b, "validity_period", validity_period); c = blobmsg_open_array(&b, "neighbors"); - for_each_local_node(node) { + for_each_local_node(node) + { if (!usteer_band_steering_is_target(ln, node)) continue; - + // TODO: Funktioniert nicht, Targets werden nicht korrekt ausgewiesen. usteer_add_nr_entry(si->node, node); } blobmsg_close_array(&b, c); - - return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request", b.head, NULL, 0, 100); + if (sizeof(si->node) > 0) + { + MSG(DEBUG, "BAND STEERING requested for sta=" MAC_ADDR_FMT " with disassociation timer %i\n", MAC_ADDR_DATA(si->sta->addr), disassoc_timer); + return ubus_invoke(ubus_ctx, ln->obj_id, "bss_transition_request", b.head, NULL, 0, 100); + } + else + MSG(DEBUG, "BAND STEERING no targets found for sta=" MAC_ADDR_FMT "\n", MAC_ADDR_DATA(si->sta->addr)); } int usteer_ubus_trigger_link_measurement(struct sta_info *si) diff --git a/usteer.h b/usteer.h index f692fb8..7a5739c 100644 --- a/usteer.h +++ b/usteer.h @@ -170,6 +170,10 @@ struct usteer_config { uint32_t remote_update_interval; uint32_t remote_node_timeout; + bool aggressive_all; + struct blob_attr *aggressive_mac_list; + uint32_t aggressive_disassoc_timer; + int32_t min_snr; uint32_t min_snr_kick_delay; int32_t min_connect_snr; @@ -190,7 +194,7 @@ struct usteer_config { uint32_t roam_kick_delay; uint32_t band_steering_interval; - int32_t band_steering_min_snr; + int32_t band_steering_min_snr; uint32_t link_measurement_interval; @@ -255,6 +259,7 @@ struct sta_info { uint8_t roam_tries; uint64_t roam_event; uint64_t roam_kick; + uint64_t roam_disassoc_time; uint64_t roam_scan_start; uint64_t roam_scan_timeout_start; @@ -285,6 +290,8 @@ struct sta { uint8_t seen_2ghz : 1; uint8_t seen_5ghz : 1; + bool aggressive; + uint8_t addr[6]; }; @@ -336,13 +343,19 @@ bool usteer_band_steering_is_target(struct usteer_local_node *ln, struct usteer_ void usteer_ubus_init(struct ubus_context *ctx); void usteer_ubus_kick_client(struct sta_info *si); int usteer_ubus_trigger_client_scan(struct sta_info *si); -int usteer_ubus_band_steering_request(struct sta_info *si); +int usteer_ubus_band_steering_request(struct sta_info *si, + uint8_t dialog_token, + bool disassoc_imminent, + uint8_t disassoc_timer, + bool abridged, + uint8_t validity_period); int usteer_ubus_bss_transition_request(struct sta_info *si, - uint8_t dialog_token, - bool disassoc_imminent, - bool abridged, - uint8_t validity_period, - struct usteer_node *target_node); + uint8_t dialog_token, + bool disassoc_imminent, + uint8_t disassoc_timer, + bool abridged, + uint8_t validity_period, + struct usteer_node *target_node); struct sta *usteer_sta_get(const uint8_t *addr, bool create); struct sta_info *usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool *create); @@ -376,6 +389,9 @@ 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); + int usteer_interface_init(void); void usteer_interface_add(const char *name); void usteer_sta_node_cleanup(struct usteer_node *node); -- 2.39.5 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel