Add known-station tracking and per-SSID configuration overrides - #22
Add known-station tracking and per-SSID configuration overrides#22grzegorz914 wants to merge 7 commits into
Conversation
Persist the best signal ever observed for a station on each node (known.c), synced between usteer peers over the existing remote protocol (remote.c). Stations that never probe or report RRM measurements once associated never generate live sta_info data on any node but their current one, so the normal candidate scan can never find them a roaming target no matter how bad their signal gets - this fallback consults the persisted record instead. Candidates found only through this fallback are exploratory: the signal was never actually observed on that node, just marked "worth exploring" once a peer reports the station connected elsewhere. They are only ever used to trigger a passive BSS-transition-request, never a forced kick or an outright probe/assoc rejection, since the reading backing them could be stale or simply never realized. Adds a known_stations/known_stations_timeout UCI toggle and a delete_known ubus method for manually discarding stale entries. Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
Add a usteer_ssid UCI section type keyed by SSID that overrides selected global settings (signal thresholds, roam-scan/trigger tuning, band-steering, load-kick, aggressiveness and its MAC-list) for stations on that SSID only, via the new SSID_CFG(ssid, field) lookup (ssid_config.c). Any option left unset on a usteer_ssid section falls back to the corresponding global usteer setting, so existing single-SSID configs keep working unchanged. Also moves per-station aggressiveness from struct sta (global to the station) to struct sta_info (per station+node), since a station seen on multiple SSIDs must use each SSID's own aggressiveness for decisions made on that SSID's nodes. Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
Band steering previously had no explicit on/off switch - it was only implicitly active whenever band_steering_interval was non-zero. Add a real band_steering_enabled bool (global and per-SSID, following the same pattern as load_kick_enabled) that gates the actual steering action in usteer_band_steering_perform_steer(), alongside the existing interval check. Defaults to true, preserving existing behavior for configs that already rely on a non-zero band_steering_interval. Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
Add sta_block_timeout, local_sta_timeout, max_retry_band, seen_policy_timeout, assoc_steering, probe_steering, max_neighbor_reports, load_balancing_threshold, steer_reject_timeout, roam_process_timeout, roam_kick_delay, initial_connect_delay and node_up_script as per-SSID overrides, mirroring the pattern already used for the SNR/band-steering/load-kick fields: each is consulted in a station+node scoped context (SSID_CFG(ssid, field)) that was previously only reading the network-wide global, and falls back to the global value when no override exists. node_up_script needed different handling than the others: its real storage isn't config.node_up_script (that struct field is dead) but a private static in local_node.c set via config_set_node_up_script(), so it can't use the SSID_CFG() macro's built-in "fall back to config.field" - the per-SSID override is resolved manually at the one call site instead, falling back to that static when unset. probe_steering was previously configurable only via a hardcoded default in usteer_init_defaults() (config.probe_steering = 0) - it was never wired into the global UCI config policy in ubus.c, so there was no way to actually turn it on. It's now settable per-SSID. Enum/policy/struct field order in ssid_config.h/.c mirrors struct usteer_config's declaration order throughout, to keep the two structures easy to diff against each other as fields are added. Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
local_sta_update already re-arms its timeout individually per local node (one struct usteer_local_node per SSID interface), so unlike remote_update_interval/remote_node_timeout (a single daemon-wide sync timer and peer table), it was already structurally per-SSID - it just read the same global value everywhere. Add it to usteer_ssid_config following struct usteer_config's declaration order, and update its five call sites (band_steering.c, local_node.c, policy.c) to consult the station's own SSID via SSID_CFG(). Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
|
About the band steering enable/disable toggle, i do not really thing that is necessary, as the zero is clearly documented. The downside of adding this is that you can now have a double disable. This may break user expectations. Also Link measurement interval also disables with a zero. So it should be keep it as is, or change both. |
|
Fair point, and I'd rather remove the ambiguity than duplicate the fix onto link_measurement_interval too. The reason band_steering_enabled exists as its own field rather than reusing the interval=0 convention: band steering became a per-SSID setting in this same series, and the LuCI UI hides all four dependent fields (interval, min_snr, signal_threshold, and the toggle's own siblings) when it's off, driven off this one boolean - link_measurement_interval doesn't have that per-SSID/dependent-field-visibility angle, so the two aren't quite the same shape of problem. To kill the double-disable you're flagging rather than spread it: band_steering_interval=0 no longer disables band steering on its own - band_steering_enabled is now the sole switch. Setting interval=0 while enabled=true means "steer every tick" rather than "disabled", same as it would for any other interval field once it's not also doing double duty as a sentinel. |
band_steering_interval=0 used to disable band steering too, alongside the band_steering_enabled toggle - two independent ways to turn the same feature off that could disagree with each other. Drop the interval=0 special case so the toggle is the only switch; interval=0 with the toggle on now means "steer every tick" like any other interval field, not "disabled". Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
That implementation may break current installations, i.e. if somebody has it set to zero then with this patch instead of disabling it will now do very aggressive band steering. About the per SSID and known system tracking. What is exactly the point of that? To circumvent some bad behaving STAs? If so then maybe it is better to tune a few of the parameters based on client mac like the |
|
Fair - didn't think through the migration impact for anyone already relying on interval=0. Reverted band_steering_enabled entirely: back to interval=0 as the sole disable convention, same as link_measurement_interval, no new field. On the per-SSID question in general: in my case (and I'd guess this is common) each SSID maps 1:1 to a radio, not to multiple SSIDs sharing one radio - Multimedia is a 5GHz-only SSID, another is 2.4GHz-only, one sits on a DFS channel and one doesn't. So it's less "tune SSID A differently from SSID B on the same hardware" and more "tune per-radio RF characteristics", which do genuinely warrant different min_snr/roam thresholds/timing even though the daemon config historically had no way to express that below the whole-instance level. A MAC-based blacklist/allowlist (extending aggressiveness_mac_list) solves a different problem - steering exceptions for specific misbehaving clients - not radio-specific tuning, so I don't think it replaces this, but happy to hear if you see it differently. |
Reverts 458519e and the toggle itself, added a day earlier. Migration risk: an existing deployment with band_steering_interval=0 (the documented way to disable band steering) would silently switch from "disabled" to "steer every tick" once band_steering_enabled became the sole switch, instead of staying disabled. Back to interval=0 as the only disable convention, same as link_measurement_interval. Signed-off-by: Grzegorz Kaczor <grzegorz914@icloud.com>
Summary
usteer_ssidUCI section type keyed by SSID, overriding signal thresholds, roam-scan/trigger tuning, band-steering (including a newband_steering_enabledtoggle - band steering had no explicit on/off switch before, only an implicit one via a non-zero interval), load-kick, aggressiveness (plus its MAC-list), and a further batch of station/node-scoped policy fields (sta_block_timeout,local_sta_timeout,max_retry_band,seen_policy_timeout,assoc_steering,probe_steering,max_neighbor_reports,load_balancing_threshold,steer_reject_timeout,roam_process_timeout,roam_kick_delay,initial_connect_delay,node_up_script) for stations on that SSID only. Any option left unset falls back to the global setting, so existing single-SSID configs are unaffected.probe_steeringwas previously configurable only via a hardcoded default (config.probe_steering = 0inusteer_init_defaults()) - it was never wired into the global UCI config policy, so there was no way to actually turn it on. It's now settable per-SSID.ssid_config.h/.c's enum/policy/struct field order mirrorsstruct usteer_config's declaration order throughout, to keep the two structures easy to diff against each other as fields are added.Test plan
ipq806x/generic(arm_cortex-a15_neon-vfpv4) andramips/mt7620(mipsel_24kc)