diff --git a/local_node.c b/local_node.c index bc27766..3c1b3e1 100644 --- a/local_node.c +++ b/local_node.c @@ -150,10 +150,29 @@ usteer_local_node_assoc_update(struct sta_info *si, struct blob_attr *data) [MSG_ASSOC] = { "assoc", BLOBMSG_TYPE_BOOL }, }; struct blob_attr *tb[__MSG_MAX]; + struct usteer_remote_node *rn; + struct sta_info *remote_si; blobmsg_parse(policy, __MSG_MAX, tb, blobmsg_data(data), blobmsg_data_len(data)); - if (tb[MSG_ASSOC] && blobmsg_get_u8(tb[MSG_ASSOC])) + if (tb[MSG_ASSOC] && blobmsg_get_u8(tb[MSG_ASSOC])) { + if (si->connected == STA_NOT_CONNECTED) { + /* New connection. Check if STA roamed. */ + for_each_remote_node(rn) { + remote_si = usteer_sta_info_get(si->sta, &rn->node, NULL); + if (!remote_si) + continue; + + if (current_time - remote_si->last_connected < config.roam_process_timeout) { + rn->node.roam_source++; + /* Don't abort looking for roam sources here. + * The client might have roamed via another node + * within the roam-timeout. + */ + } + } + } si->connected = STA_CONNECTED; + } if (si->node->freq < 4000) si->sta->seen_2ghz = 1; diff --git a/main.c b/main.c index 9d01419..9fb6d4a 100644 --- a/main.c +++ b/main.c @@ -96,6 +96,7 @@ void usteer_init_defaults(void) config.remote_node_timeout = 10; config.roam_kick_delay = 100; + config.roam_process_timeout = 5 * 1000; config.roam_scan_tries = 3; config.roam_scan_interval = 10 * 1000; config.roam_trigger_interval = 60 * 1000; diff --git a/openwrt/usteer/files/etc/config/usteer b/openwrt/usteer/files/etc/config/usteer index 3ba1c6d..9031ea8 100644 --- a/openwrt/usteer/files/etc/config/usteer +++ b/openwrt/usteer/files/etc/config/usteer @@ -50,6 +50,10 @@ config usteer # Minimum signal-to-noise ratio or signal level (dBm) to remain connected #option min_snr 0 + # Timeout (in ms) after which a association following a disassociation is not seen + # as a roam + #option roam_process_timeout 5000 + # Minimum signal-to-noise ratio or signal level (dBm) before attempting to trigger # client scans for roaming #option roam_scan_snr 0 diff --git a/openwrt/usteer/files/etc/init.d/usteer b/openwrt/usteer/files/etc/init.d/usteer index 15add88..65a6b9a 100755 --- a/openwrt/usteer/files/etc/init.d/usteer +++ b/openwrt/usteer/files/etc/init.d/usteer @@ -79,7 +79,7 @@ uci_usteer() { load_balancing_threshold band_steering_threshold \ remote_update_interval \ min_connect_snr min_snr signal_diff_threshold \ - initial_connect_delay \ + initial_connect_delay roam_process_timeout\ roam_kick_delay roam_scan_tries \ roam_scan_snr roam_scan_interval \ roam_trigger_snr roam_trigger_interval \ diff --git a/remote.c b/remote.c index d0d9e17..4887cc0 100644 --- a/remote.c +++ b/remote.c @@ -155,9 +155,11 @@ static void interface_add_station(struct usteer_remote_node *node, struct blob_attr *data) { struct sta *sta; - struct sta_info *si; + struct sta_info *si, *local_si; struct apmsg_sta msg; + struct usteer_node *local_node; bool create; + bool connect_change; if (!parse_apmsg_sta(&msg, data)) { MSG(DEBUG, "Cannot parse station in message\n"); @@ -177,10 +179,26 @@ interface_add_station(struct usteer_remote_node *node, struct blob_attr *data) if (!si) return; + connect_change = si->connected != msg.connected; si->connected = msg.connected; si->signal = msg.signal; si->seen = current_time - msg.seen; si->last_connected = current_time - msg.last_connected; + + /* Check if client roamed to this foreign node */ + if ((connect_change || create) && si->connected == STA_CONNECTED) { + for_each_local_node(local_node) { + local_si = usteer_sta_info_get(sta, local_node, NULL); + if (!local_si) + continue; + + if (current_time - local_si->last_connected < config.roam_process_timeout) { + node->node.roam_destination++; + break; + } + } + } + usteer_sta_info_update_timeout(si, msg.timeout); } diff --git a/ubus.c b/ubus.c index 1f57194..776b0bf 100644 --- a/ubus.c +++ b/ubus.c @@ -154,6 +154,7 @@ struct cfg_item { _cfg(BOOL, assoc_steering), \ _cfg(I32, min_connect_snr), \ _cfg(I32, min_snr), \ + _cfg(U32, roam_process_timeout), \ _cfg(I32, roam_scan_snr), \ _cfg(U32, roam_scan_tries), \ _cfg(U32, roam_scan_interval), \ @@ -281,6 +282,8 @@ void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node) blobmsg_add_u32(buf, "noise", node->noise); blobmsg_add_u32(buf, "load", node->load); blobmsg_add_u32(buf, "max_assoc", node->max_assoc); + blobmsg_add_u32(buf, "roam_source", node->roam_source); + blobmsg_add_u32(buf, "roam_destination", node->roam_destination); if (node->rrm_nr) blobmsg_add_field(buf, BLOBMSG_TYPE_ARRAY, "rrm_nr", blobmsg_data(node->rrm_nr), diff --git a/usteer.h b/usteer.h index 866c0b2..05dca14 100644 --- a/usteer.h +++ b/usteer.h @@ -87,6 +87,9 @@ struct usteer_node { int n_assoc; int max_assoc; int load; + + int roam_source; + int roam_destination; }; struct usteer_scan_request { @@ -160,6 +163,8 @@ struct usteer_config { uint32_t signal_diff_threshold; int32_t roam_scan_snr; + uint32_t roam_process_timeout; + uint32_t roam_scan_tries; uint32_t roam_scan_interval;