policy: make roam-steers client-rejectable
While usteer tries it's best to determine the availability of a better node for a certain client, it might still attempt to direct the client to a unsuitable AP. Transition away from using BSS-Transition-Requests with the disassoc-imminent bit set and instead unset this bit. This way, the client can inform the AP it will not transition to a different BSS but instead wishes to remain connected to the current AP. usteer will still kick clients in case they either accepted the BSS-transition-request and do not roam or ignore the request completely. Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
@@ -180,6 +180,11 @@ 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.status_code = blobmsg_get_u8(tb[BSS_TM_RESPONSE_STATUS_CODE]);
|
||||||
si->bss_transition_response.timestamp = current_time;
|
si->bss_transition_response.timestamp = current_time;
|
||||||
|
|
||||||
|
if (si->bss_transition_response.status_code) {
|
||||||
|
/* Cancel imminent kick in case BSS transition was rejected */
|
||||||
|
si->kick_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
policy.c
50
policy.c
@@ -314,14 +314,11 @@ usteer_roam_sm_found_better_node(struct sta_info *si, struct uevent *ev, enum ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
usteer_roam_trigger_sm(struct sta_info *si)
|
usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
|
||||||
{
|
{
|
||||||
struct uevent ev = {
|
struct uevent ev = {
|
||||||
.si_cur = si,
|
.si_cur = si,
|
||||||
};
|
};
|
||||||
uint64_t min_signal;
|
|
||||||
|
|
||||||
min_signal = usteer_snr_to_signal(si->node, config.roam_trigger_snr);
|
|
||||||
|
|
||||||
switch (si->roam_state) {
|
switch (si->roam_state) {
|
||||||
case ROAM_TRIGGER_SCAN:
|
case ROAM_TRIGGER_SCAN:
|
||||||
@@ -341,7 +338,7 @@ usteer_roam_trigger_sm(struct sta_info *si)
|
|||||||
if (config.roam_scan_tries && si->roam_tries >= config.roam_scan_tries) {
|
if (config.roam_scan_tries && si->roam_tries >= config.roam_scan_tries) {
|
||||||
if (!config.roam_scan_timeout) {
|
if (!config.roam_scan_timeout) {
|
||||||
/* Prepare to kick client */
|
/* Prepare to kick client */
|
||||||
usteer_roam_set_state(si, ROAM_TRIGGER_WAIT_KICK, &ev);
|
usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev);
|
||||||
} else {
|
} else {
|
||||||
/* Kick in scan timeout */
|
/* Kick in scan timeout */
|
||||||
si->roam_scan_timeout_start = current_time;
|
si->roam_scan_timeout_start = current_time;
|
||||||
@@ -360,30 +357,10 @@ usteer_roam_trigger_sm(struct sta_info *si)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ROAM_TRIGGER_SCAN_DONE:
|
case ROAM_TRIGGER_SCAN_DONE:
|
||||||
if (usteer_roam_sm_found_better_node(si, &ev, ROAM_TRIGGER_WAIT_KICK))
|
usteer_ubus_bss_transition_request(si, 1, false, false, 100);
|
||||||
break;
|
si->kick_time = current_time;
|
||||||
|
|
||||||
/* Kick back to SCAN state if candidate expired */
|
|
||||||
usteer_roam_sm_start_scan(si, &ev);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ROAM_TRIGGER_WAIT_KICK:
|
|
||||||
if (si->signal > min_signal)
|
|
||||||
break;
|
|
||||||
|
|
||||||
usteer_roam_set_state(si, ROAM_TRIGGER_NOTIFY_KICK, &ev);
|
|
||||||
usteer_ubus_notify_client_disassoc(si);
|
|
||||||
break;
|
|
||||||
case ROAM_TRIGGER_NOTIFY_KICK:
|
|
||||||
if (current_time - si->roam_event < config.roam_kick_delay * 100)
|
|
||||||
break;
|
|
||||||
|
|
||||||
usteer_roam_set_state(si, ROAM_TRIGGER_KICK, &ev);
|
|
||||||
break;
|
|
||||||
case ROAM_TRIGGER_KICK:
|
|
||||||
usteer_ubus_kick_client(si);
|
|
||||||
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
|
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -407,6 +384,7 @@ usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev)
|
|||||||
|
|
||||||
list_for_each_entry(si, &ln->node.sta_info, node_list) {
|
list_for_each_entry(si, &ln->node.sta_info, node_list) {
|
||||||
if (si->connected != STA_CONNECTED || si->signal >= min_signal ||
|
if (si->connected != STA_CONNECTED || si->signal >= min_signal ||
|
||||||
|
si->kick_time ||
|
||||||
current_time - si->roam_kick < config.roam_trigger_interval) {
|
current_time - si->roam_kick < config.roam_trigger_interval) {
|
||||||
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
|
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
|
||||||
continue;
|
continue;
|
||||||
@@ -416,7 +394,7 @@ usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev)
|
|||||||
* If the state machine kicked a client, other clients should wait
|
* If the state machine kicked a client, other clients should wait
|
||||||
* until the next turn
|
* until the next turn
|
||||||
*/
|
*/
|
||||||
if (usteer_roam_trigger_sm(si))
|
if (usteer_roam_trigger_sm(ln, si))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -548,6 +526,18 @@ out:
|
|||||||
usteer_event(&ev);
|
usteer_event(&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usteer_local_node_perform_kick(struct usteer_local_node *ln)
|
||||||
|
{
|
||||||
|
struct sta_info *si;
|
||||||
|
|
||||||
|
list_for_each_entry(si, &ln->node.sta_info, node_list) {
|
||||||
|
if (!si->kick_time || si->kick_time > current_time)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
usteer_ubus_kick_client(si);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usteer_local_node_kick(struct usteer_local_node *ln)
|
usteer_local_node_kick(struct usteer_local_node *ln)
|
||||||
@@ -556,6 +546,8 @@ usteer_local_node_kick(struct usteer_local_node *ln)
|
|||||||
.node_local = &ln->node,
|
.node_local = &ln->node,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
usteer_local_node_perform_kick(ln);
|
||||||
|
|
||||||
usteer_local_node_snr_kick(ln);
|
usteer_local_node_snr_kick(ln);
|
||||||
usteer_local_node_load_kick(ln);
|
usteer_local_node_load_kick(ln);
|
||||||
usteer_local_node_roam_check(ln, &ev);
|
usteer_local_node_roam_check(ln, &ev);
|
||||||
|
1
sta.c
1
sta.c
@@ -149,6 +149,7 @@ usteer_sta_get(const uint8_t *addr, bool create)
|
|||||||
void usteer_sta_disconnected(struct sta_info *si)
|
void usteer_sta_disconnected(struct sta_info *si)
|
||||||
{
|
{
|
||||||
si->connected = STA_NOT_CONNECTED;
|
si->connected = STA_NOT_CONNECTED;
|
||||||
|
si->kick_time = 0;
|
||||||
usteer_sta_info_update_timeout(si, config.local_sta_timeout);
|
usteer_sta_info_update_timeout(si, config.local_sta_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
usteer.h
5
usteer.h
@@ -219,9 +219,6 @@ enum roam_trigger_state {
|
|||||||
ROAM_TRIGGER_IDLE,
|
ROAM_TRIGGER_IDLE,
|
||||||
ROAM_TRIGGER_SCAN,
|
ROAM_TRIGGER_SCAN,
|
||||||
ROAM_TRIGGER_SCAN_DONE,
|
ROAM_TRIGGER_SCAN_DONE,
|
||||||
ROAM_TRIGGER_WAIT_KICK,
|
|
||||||
ROAM_TRIGGER_NOTIFY_KICK,
|
|
||||||
ROAM_TRIGGER_KICK,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sta_info {
|
struct sta_info {
|
||||||
@@ -254,6 +251,8 @@ struct sta_info {
|
|||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
} bss_transition_response;
|
} bss_transition_response;
|
||||||
|
|
||||||
|
uint64_t kick_time;
|
||||||
|
|
||||||
int kick_count;
|
int kick_count;
|
||||||
|
|
||||||
uint32_t below_min_snr;
|
uint32_t below_min_snr;
|
||||||
|
Reference in New Issue
Block a user