@@ -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);
@@ -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)
@@ -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;
@@ -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
@@ -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 \
@@ -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;
@@ -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);
@@ -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) {
@@ -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);
- 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(-)