[usteer] New aggressive roaming to support Intel Wifi Cards (and also, other devices)
Nils Rottgardt
n.rottgardt at gmail.com
Sat Oct 19 09:06:11 PDT 2024
>From 2b0bb0b37e0f34be67be5d8e115a60354d55fce0 Mon Sep 17 00:00:00 2001
From: Nils Hendrik Rottgardt <n.rottgardt at gmail.com>
Date: Tue, 8 Oct 2024 23:30:19 +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.
- sta: corrected some linebreaks
Signed-off-by: Nils Hendrik Rottgardt <n.rottgardt at gmail.com>
---
band_steering.c | 27 +-
local_node.c | 267 ++++++++++++--------
main.c | 56 +++--
openwrt/usteer/files/etc/config/usteer | 9 +
openwrt/usteer/files/etc/init.d/usteer | 4 +-
policy.c | 148 +++++++----
sta.c | 101 +++++---
ubus.c | 335 ++++++++++++++-----------
usteer.h | 123 +++++----
9 files changed, 654 insertions(+), 416 deletions(-)
diff --git a/band_steering.c b/band_steering.c
index 7fce1df..470f904 100644
--- a/band_steering.c
+++ b/band_steering.c
@@ -37,18 +37,18 @@ bool usteer_band_steering_is_target(struct
usteer_local_node *ln, struct usteer_
if (!usteer_policy_node_below_max_assoc(node))
return false;
-
+
/* ToDo: Skip nodes with active load-kick */
-
- return true;
- }
+ return true;
+}
static bool usteer_band_steering_has_target_iface(struct
usteer_local_node *ln)
{
struct usteer_node *node;
- for_each_local_node(node) {
+ for_each_local_node(node)
+ {
if (usteer_band_steering_is_target(ln, node))
return true;
}
@@ -73,26 +73,35 @@ void usteer_band_steering_perform_steer(struct
usteer_local_node *ln)
return;
/* Only steer every interval */
- if (ln->band_steering_interval < min_count) {
+ if (ln->band_steering_interval < min_count)
+ {
ln->band_steering_interval++;
return;
}
ln->band_steering_interval = 0;
- list_for_each_entry(si, &ln->node.sta_info, node_list) {
+ list_for_each_entry(si, &ln->node.sta_info, node_list)
+ {
/* Check if client is eligable to be steerd */
if (!usteer_policy_can_perform_roam(si))
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..b415196 100644
--- a/local_node.c
+++ b/local_node.c
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#include <sys/types.h>
@@ -51,7 +51,8 @@ usteer_local_node_pending_bss_tm_free(struct
usteer_local_node *ln)
{
struct usteer_bss_tm_query *query, *tmp;
- list_for_each_entry_safe(query, tmp, &ln->bss_tm_queries, list) {
+ list_for_each_entry_safe(query, tmp, &ln->bss_tm_queries, list)
+ {
list_del(&query->list);
free(query);
}
@@ -62,7 +63,8 @@ usteer_free_node(struct ubus_context *ctx, struct
usteer_local_node *ln)
{
struct usteer_node_handler *h;
- list_for_each_entry(h, &node_handlers, list) {
+ list_for_each_entry(h, &node_handlers, list)
+ {
if (!h->free_node)
continue;
h->free_node(&ln->node);
@@ -80,11 +82,13 @@ usteer_free_node(struct ubus_context *ctx, struct
usteer_local_node *ln)
free(ln);
}
-struct usteer_local_node *usteer_local_node_by_bssid(uint8_t *bssid) {
+struct usteer_local_node *usteer_local_node_by_bssid(uint8_t *bssid)
+{
struct usteer_local_node *ln;
struct usteer_node *n;
- for_each_local_node(n) {
+ for_each_local_node(n)
+ {
ln = container_of(n, struct usteer_local_node, node);
if (!memcmp(n->bssid, bssid, 6))
return ln;
@@ -95,7 +99,7 @@ struct usteer_local_node
*usteer_local_node_by_bssid(uint8_t *bssid) {
static void
usteer_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
- uint32_t id)
+ uint32_t id)
{
struct usteer_local_node *ln = container_of(s, struct
usteer_local_node, ev);
@@ -105,16 +109,17 @@ usteer_handle_remove(struct ubus_context *ctx,
struct ubus_subscriber *s,
static int
usteer_handle_bss_tm_query(struct usteer_local_node *ln, struct
blob_attr *msg)
{
- enum {
+ enum
+ {
BSS_TM_QUERY_ADDRESS,
BSS_TM_QUERY_DIALOG_TOKEN,
BSS_TM_QUERY_CANDIDATE_LIST,
__BSS_TM_QUERY_MAX
};
struct blobmsg_policy policy[__BSS_TM_QUERY_MAX] = {
- [BSS_TM_QUERY_ADDRESS] = { .name = "address", .type =
BLOBMSG_TYPE_STRING },
- [BSS_TM_QUERY_DIALOG_TOKEN] = { .name = "dialog-token", .type =
BLOBMSG_TYPE_INT8 },
- [BSS_TM_QUERY_CANDIDATE_LIST] = { .name = "candidate-list",
.type = BLOBMSG_TYPE_STRING },
+ [BSS_TM_QUERY_ADDRESS] = {.name = "address", .type =
BLOBMSG_TYPE_STRING},
+ [BSS_TM_QUERY_DIALOG_TOKEN] = {.name = "dialog-token", .type =
BLOBMSG_TYPE_INT8},
+ [BSS_TM_QUERY_CANDIDATE_LIST] = {.name = "candidate-list",
.type = BLOBMSG_TYPE_STRING},
};
struct blob_attr *tb[__BSS_TM_QUERY_MAX];
struct usteer_bss_tm_query *query;
@@ -131,7 +136,7 @@ usteer_handle_bss_tm_query(struct usteer_local_node
*ln, struct blob_attr *msg)
query->dialog_token = blobmsg_get_u8(tb[BSS_TM_QUERY_DIALOG_TOKEN]);
- sta_addr = (uint8_t *)
ether_aton(blobmsg_get_string(tb[BSS_TM_QUERY_ADDRESS]));
+ sta_addr = (uint8_t
*)ether_aton(blobmsg_get_string(tb[BSS_TM_QUERY_ADDRESS]));
if (!sta_addr)
return 0;
@@ -146,14 +151,15 @@ usteer_handle_bss_tm_query(struct
usteer_local_node *ln, struct blob_attr *msg)
static int
usteer_handle_bss_tm_response(struct usteer_local_node *ln, struct
blob_attr *msg)
{
- enum {
+ enum
+ {
BSS_TM_RESPONSE_ADDRESS,
BSS_TM_RESPONSE_STATUS_CODE,
__BSS_TM_RESPONSE_MAX
};
struct blobmsg_policy policy[__BSS_TM_RESPONSE_MAX] = {
- [BSS_TM_RESPONSE_ADDRESS] = { .name = "address", .type =
BLOBMSG_TYPE_STRING },
- [BSS_TM_RESPONSE_STATUS_CODE] = { .name = "status-code", .type
= BLOBMSG_TYPE_INT8 },
+ [BSS_TM_RESPONSE_ADDRESS] = {.name = "address", .type =
BLOBMSG_TYPE_STRING},
+ [BSS_TM_RESPONSE_STATUS_CODE] = {.name = "status-code", .type =
BLOBMSG_TYPE_INT8},
};
struct blob_attr *tb[__BSS_TM_RESPONSE_MAX];
struct sta_info *si;
@@ -165,7 +171,7 @@ usteer_handle_bss_tm_response(struct
usteer_local_node *ln, struct blob_attr *ms
if (!tb[BSS_TM_RESPONSE_ADDRESS] || !tb[BSS_TM_RESPONSE_STATUS_CODE])
return 0;
- sta_addr = (uint8_t *)
ether_aton(blobmsg_get_string(tb[BSS_TM_RESPONSE_ADDRESS]));
+ sta_addr = (uint8_t
*)ether_aton(blobmsg_get_string(tb[BSS_TM_RESPONSE_ADDRESS]));
if (!sta_addr)
return 0;
@@ -180,7 +186,8 @@ 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)
+ {
/* Cancel imminent kick in case BSS transition was rejected */
si->kick_time = 0;
}
@@ -191,7 +198,8 @@ usteer_handle_bss_tm_response(struct
usteer_local_node *ln, struct blob_attr *ms
static int
usteer_local_node_handle_beacon_report(struct usteer_local_node *ln,
struct blob_attr *msg)
{
- enum {
+ enum
+ {
BR_ADDRESS,
BR_BSSID,
BR_RCPI,
@@ -199,10 +207,10 @@ usteer_local_node_handle_beacon_report(struct
usteer_local_node *ln, struct blob
__BR_MAX
};
struct blobmsg_policy policy[__BR_MAX] = {
- [BR_ADDRESS] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
- [BR_BSSID] = { .name = "bssid", .type = BLOBMSG_TYPE_STRING },
- [BR_RCPI] = { .name = "rcpi", .type = BLOBMSG_TYPE_INT16 },
- [BR_RSNI] = { .name = "rsni", .type = BLOBMSG_TYPE_INT16 },
+ [BR_ADDRESS] = {.name = "address", .type = BLOBMSG_TYPE_STRING},
+ [BR_BSSID] = {.name = "bssid", .type = BLOBMSG_TYPE_STRING},
+ [BR_RCPI] = {.name = "rcpi", .type = BLOBMSG_TYPE_INT16},
+ [BR_RSNI] = {.name = "rsni", .type = BLOBMSG_TYPE_INT16},
};
struct blob_attr *tb[__BR_MAX];
struct usteer_node *node;
@@ -213,7 +221,7 @@ usteer_local_node_handle_beacon_report(struct
usteer_local_node *ln, struct blob
if (!tb[BR_ADDRESS] || !tb[BR_BSSID] || !tb[BR_RCPI] || !tb[BR_RSNI])
return 0;
- addr = (uint8_t *) ether_aton(blobmsg_get_string(tb[BR_ADDRESS]));
+ addr = (uint8_t *)ether_aton(blobmsg_get_string(tb[BR_ADDRESS]));
if (!addr)
return 0;
@@ -221,7 +229,7 @@ usteer_local_node_handle_beacon_report(struct
usteer_local_node *ln, struct blob
if (!sta)
return 0;
- addr = (uint8_t *) ether_aton(blobmsg_get_string(tb[BR_BSSID]));
+ addr = (uint8_t *)ether_aton(blobmsg_get_string(tb[BR_BSSID]));
if (!addr)
return 0;
@@ -230,25 +238,26 @@ usteer_local_node_handle_beacon_report(struct
usteer_local_node *ln, struct blob
return 0;
usteer_measurement_report_add(sta, node,
- (uint8_t)blobmsg_get_u16(tb[BR_RCPI]),
- (uint8_t)blobmsg_get_u16(tb[BR_RSNI]),
- current_time);
+ (uint8_t)blobmsg_get_u16(tb[BR_RCPI]),
+ (uint8_t)blobmsg_get_u16(tb[BR_RSNI]),
+ current_time);
return 0;
}
static int
usteer_local_node_handle_link_measurement_report(struct
usteer_local_node *ln, struct blob_attr *msg)
{
- enum {
+ enum
+ {
LMR_ADDRESS,
LMR_RCPI,
LMR_RSNI,
__LMR_MAX
};
struct blobmsg_policy policy[__LMR_MAX] = {
- [LMR_ADDRESS] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
- [LMR_RCPI] = { .name = "rcpi", .type = BLOBMSG_TYPE_INT16 },
- [LMR_RSNI] = { .name = "rsni", .type = BLOBMSG_TYPE_INT16 },
+ [LMR_ADDRESS] = {.name = "address", .type = BLOBMSG_TYPE_STRING},
+ [LMR_RCPI] = {.name = "rcpi", .type = BLOBMSG_TYPE_INT16},
+ [LMR_RSNI] = {.name = "rsni", .type = BLOBMSG_TYPE_INT16},
};
struct blob_attr *tb[__LMR_MAX];
uint8_t *addr;
@@ -258,7 +267,7 @@
usteer_local_node_handle_link_measurement_report(struct
usteer_local_node *ln, s
if (!tb[LMR_ADDRESS] || !tb[LMR_RCPI] || !tb[LMR_RSNI])
return 0;
- addr = (uint8_t *) ether_aton(blobmsg_get_string(tb[LMR_ADDRESS]));
+ addr = (uint8_t *)ether_aton(blobmsg_get_string(tb[LMR_ADDRESS]));
if (!addr)
return 0;
@@ -267,18 +276,19 @@
usteer_local_node_handle_link_measurement_report(struct
usteer_local_node *ln, s
return 0;
usteer_measurement_report_add(sta, &ln->node,
- (uint8_t)blobmsg_get_u16(tb[LMR_RCPI]),
- (uint8_t)blobmsg_get_u16(tb[LMR_RSNI]),
- current_time);
+ (uint8_t)blobmsg_get_u16(tb[LMR_RCPI]),
+ (uint8_t)blobmsg_get_u16(tb[LMR_RSNI]),
+ current_time);
return 0;
}
static int
usteer_handle_event(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
- enum {
+ enum
+ {
EVENT_ADDR,
EVENT_SIGNAL,
EVENT_TARGET,
@@ -286,10 +296,10 @@ usteer_handle_event(struct ubus_context *ctx,
struct ubus_object *obj,
__EVENT_MAX
};
struct blobmsg_policy policy[__EVENT_MAX] = {
- [EVENT_ADDR] = { .name = "address", .type = BLOBMSG_TYPE_STRING },
- [EVENT_SIGNAL] = { .name = "signal", .type = BLOBMSG_TYPE_INT32 },
- [EVENT_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
- [EVENT_FREQ] = { .name = "freq", .type = BLOBMSG_TYPE_INT32 },
+ [EVENT_ADDR] = {.name = "address", .type = BLOBMSG_TYPE_STRING},
+ [EVENT_SIGNAL] = {.name = "signal", .type = BLOBMSG_TYPE_INT32},
+ [EVENT_TARGET] = {.name = "target", .type = BLOBMSG_TYPE_STRING},
+ [EVENT_FREQ] = {.name = "freq", .type = BLOBMSG_TYPE_INT32},
};
enum usteer_event_type ev_type = __EVENT_TYPE_MAX;
struct blob_attr *tb[__EVENT_MAX];
@@ -306,17 +316,25 @@ usteer_handle_event(struct ubus_context *ctx,
struct ubus_object *obj,
ln = container_of(obj, struct usteer_local_node, ev.obj);
- if(!strcmp(method, "bss-transition-query")) {
+ if (!strcmp(method, "bss-transition-query"))
+ {
return usteer_handle_bss_tm_query(ln, msg);
- } else if(!strcmp(method, "bss-transition-response")) {
+ }
+ else if (!strcmp(method, "bss-transition-response"))
+ {
return usteer_handle_bss_tm_response(ln, msg);
- } else if(!strcmp(method, "beacon-report")) {
+ }
+ else if (!strcmp(method, "beacon-report"))
+ {
return usteer_local_node_handle_beacon_report(ln, msg);
- } else if(!strcmp(method, "link-measurement-report")) {
+ }
+ else if (!strcmp(method, "link-measurement-report"))
+ {
return usteer_local_node_handle_link_measurement_report(ln, msg);
}
- for (i = 0; i < ARRAY_SIZE(event_types); i++) {
+ for (i = 0; i < ARRAY_SIZE(event_types); i++)
+ {
if (strcmp(method, event_types[i]) != 0)
continue;
@@ -331,20 +349,20 @@ usteer_handle_event(struct ubus_context *ctx,
struct ubus_object *obj,
return UBUS_STATUS_INVALID_ARGUMENT;
if (tb[EVENT_SIGNAL])
- signal = (int32_t) blobmsg_get_u32(tb[EVENT_SIGNAL]);
+ signal = (int32_t)blobmsg_get_u32(tb[EVENT_SIGNAL]);
if (tb[EVENT_FREQ])
freq = blobmsg_get_u32(tb[EVENT_FREQ]);
addr_str = blobmsg_data(tb[EVENT_ADDR]);
- addr = (uint8_t *) ether_aton(addr_str);
+ addr = (uint8_t *)ether_aton(addr_str);
if (!addr)
return UBUS_STATUS_INVALID_ARGUMENT;
ret = usteer_handle_sta_event(node, addr, ev_type, freq, signal);
MSG(DEBUG, "received %s event from %s, signal=%d, freq=%d,
handled:%s\n",
- method, addr_str, signal, freq, ret ? "true" : "false");
+ method, addr_str, signal, freq, ret ? "true" : "false");
return ret ? 0 : 17 /* WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA */;
}
@@ -352,27 +370,32 @@ usteer_handle_event(struct ubus_context *ctx,
struct ubus_object *obj,
static void
usteer_local_node_assoc_update(struct sta_info *si, struct blob_attr *data)
{
- enum {
+ enum
+ {
MSG_ASSOC,
__MSG_MAX,
};
static struct blobmsg_policy policy[__MSG_MAX] = {
- [MSG_ASSOC] = { "assoc", BLOBMSG_TYPE_BOOL },
+ [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 (si->connected == STA_NOT_CONNECTED) {
+ 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) {
+ 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) {
+ if (current_time - remote_si->last_connected <
config.roam_process_timeout)
+ {
rn->node.roam_events.source++;
/* Don't abort looking for roam sources here.
* The client might have roamed via another node
@@ -424,11 +447,13 @@ usteer_local_node_update_sta_rrm_wnm(struct
sta_info *si, struct blob_attr *clie
if (!wnm_blob)
return;
- blobmsg_for_each_attr(cur, wnm_blob, rem) {
+ blobmsg_for_each_attr(cur, wnm_blob, rem)
+ {
if (blobmsg_type(cur) != BLOBMSG_TYPE_INT32)
return;
-
- if (i == 2) {
+
+ if (i == 2)
+ {
if (blobmsg_get_u32(cur) & (1 << 3))
si->bss_transition = true;
}
@@ -450,13 +475,15 @@ usteer_local_node_set_assoc(struct
usteer_local_node *ln, struct blob_attr *cl)
usteer_update_time();
- list_for_each_entry(si, &node->sta_info, node_list) {
+ list_for_each_entry(si, &node->sta_info, node_list)
+ {
if (si->connected)
si->connected = STA_DISCONNECTED;
}
- blobmsg_for_each_attr(cur, cl, rem) {
- uint8_t *addr = (uint8_t *) ether_aton(blobmsg_name(cur));
+ blobmsg_for_each_attr(cur, cl, rem)
+ {
+ uint8_t *addr = (uint8_t *)ether_aton(blobmsg_name(cur));
bool create;
if (!addr)
@@ -464,14 +491,16 @@ usteer_local_node_set_assoc(struct
usteer_local_node *ln, struct blob_attr *cl)
sta = usteer_sta_get(addr, true);
si = usteer_sta_info_get(sta, node, &create);
- list_for_each_entry(h, &node_handlers, list) {
+ list_for_each_entry(h, &node_handlers, list)
+ {
if (!h->update_sta)
continue;
h->update_sta(node, si);
}
usteer_local_node_assoc_update(si, cur);
- if (si->connected == STA_CONNECTED) {
+ if (si->connected == STA_CONNECTED)
+ {
si->last_connected = current_time;
n_assoc++;
}
@@ -482,12 +511,13 @@ usteer_local_node_set_assoc(struct
usteer_local_node *ln, struct blob_attr *cl)
node->n_assoc = n_assoc;
- list_for_each_entry(si, &node->sta_info, node_list) {
+ list_for_each_entry(si, &node->sta_info, node_list)
+ {
if (si->connected != STA_DISCONNECTED)
continue;
usteer_sta_disconnected(si);
- MSG(VERBOSE, "station "MAC_ADDR_FMT" disconnected from node %s\n",
+ MSG(VERBOSE, "station " MAC_ADDR_FMT " disconnected from node
%s\n",
MAC_ADDR_DATA(si->sta->addr), usteer_node_name(node));
}
}
@@ -495,14 +525,15 @@ usteer_local_node_set_assoc(struct
usteer_local_node *ln, struct blob_attr *cl)
static void
usteer_local_node_list_cb(struct ubus_request *req, int type, struct
blob_attr *msg)
{
- enum {
+ enum
+ {
MSG_FREQ,
MSG_CLIENTS,
__MSG_MAX,
};
static struct blobmsg_policy policy[__MSG_MAX] = {
- [MSG_FREQ] = { "freq", BLOBMSG_TYPE_INT32 },
- [MSG_CLIENTS] = { "clients", BLOBMSG_TYPE_TABLE },
+ [MSG_FREQ] = {"freq", BLOBMSG_TYPE_INT32},
+ [MSG_CLIENTS] = {"clients", BLOBMSG_TYPE_TABLE},
};
struct blob_attr *tb[__MSG_MAX];
struct usteer_local_node *ln;
@@ -522,7 +553,8 @@ usteer_local_node_list_cb(struct ubus_request *req,
int type, struct blob_attr *
static void
usteer_local_node_status_cb(struct ubus_request *req, int type, struct
blob_attr *msg)
{
- enum {
+ enum
+ {
MSG_FREQ,
MSG_CHANNEL,
MSG_OP_CLASS,
@@ -530,10 +562,10 @@ usteer_local_node_status_cb(struct ubus_request
*req, int type, struct blob_attr
__MSG_MAX,
};
static struct blobmsg_policy policy[__MSG_MAX] = {
- [MSG_FREQ] = { "freq", BLOBMSG_TYPE_INT32 },
- [MSG_CHANNEL] = { "channel", BLOBMSG_TYPE_INT32 },
- [MSG_OP_CLASS] = { "op_class", BLOBMSG_TYPE_INT32 },
- [MSG_BEACON_INTERVAL] = { "beacon_interval", BLOBMSG_TYPE_INT32 },
+ [MSG_FREQ] = {"freq", BLOBMSG_TYPE_INT32},
+ [MSG_CHANNEL] = {"channel", BLOBMSG_TYPE_INT32},
+ [MSG_OP_CLASS] = {"op_class", BLOBMSG_TYPE_INT32},
+ [MSG_BEACON_INTERVAL] = {"beacon_interval", BLOBMSG_TYPE_INT32},
};
struct blob_attr *tb[__MSG_MAX];
struct usteer_local_node *ln;
@@ -548,7 +580,7 @@ usteer_local_node_status_cb(struct ubus_request
*req, int type, struct blob_attr
if (tb[MSG_CHANNEL])
node->channel = blobmsg_get_u32(tb[MSG_CHANNEL]);
if (tb[MSG_OP_CLASS])
- node->op_class = blobmsg_get_u32(tb[MSG_OP_CLASS]);
+ node->op_class = blobmsg_get_u32(tb[MSG_OP_CLASS]);
/* Local-Node */
if (tb[MSG_BEACON_INTERVAL])
@@ -559,8 +591,7 @@ static void
usteer_local_node_rrm_nr_cb(struct ubus_request *req, int type, struct
blob_attr *msg)
{
static const struct blobmsg_policy policy = {
- "value", BLOBMSG_TYPE_ARRAY
- };
+ "value", BLOBMSG_TYPE_ARRAY};
struct usteer_local_node *ln;
struct blob_attr *tb;
@@ -596,8 +627,8 @@ usteer_add_rrm_data(struct usteer_local_node *ln,
struct usteer_node *node)
return false;
blobmsg_add_field(&b, BLOBMSG_TYPE_ARRAY, "",
- blobmsg_data(node->rrm_nr),
- blobmsg_data_len(node->rrm_nr));
+ blobmsg_data(node->rrm_nr),
+ blobmsg_data_len(node->rrm_nr));
return true;
}
@@ -610,16 +641,19 @@ usteer_local_node_prepare_rrm_set(struct
usteer_local_node *ln)
void *c;
c = blobmsg_open_array(&b, "list");
- for_each_local_node(node) {
+ for_each_local_node(node)
+ {
if (i >= config.max_neighbor_reports)
break;
if (usteer_add_rrm_data(ln, node))
i++;
}
- while (i < config.max_neighbor_reports) {
+ while (i < config.max_neighbor_reports)
+ {
node = usteer_node_get_next_neighbor(&ln->node,
last_remote_neighbor);
- if (!node) {
+ if (!node)
+ {
/* No more nodes available */
break;
}
@@ -628,7 +662,7 @@ usteer_local_node_prepare_rrm_set(struct
usteer_local_node *ln)
if (usteer_add_rrm_data(ln, node))
i++;
}
-
+
blobmsg_close_array(&b, c);
}
@@ -640,13 +674,15 @@ usteer_local_node_state_next(struct uloop_timeout
*timeout)
ln = container_of(timeout, struct usteer_local_node, req_timer);
ln->req_state++;
- if (ln->req_state >= __REQ_MAX) {
+ if (ln->req_state >= __REQ_MAX)
+ {
ln->req_state = REQ_IDLE;
return;
}
blob_buf_init(&b, 0);
- switch (ln->req_state) {
+ switch (ln->req_state)
+ {
case REQ_CLIENTS:
ubus_invoke_async(ubus_ctx, ln->obj_id, "get_clients", b.head,
&ln->req);
ln->req.data_cb = usteer_local_node_list_cb;
@@ -680,17 +716,19 @@ usteer_local_node_request_link_measurement(struct
usteer_local_node *ln)
node = &ln->node;
- if (ln->link_measurement_tries < min_count) {
+ if (ln->link_measurement_tries < min_count)
+ {
ln->link_measurement_tries++;
return;
}
-
+
ln->link_measurement_tries = 0;
if (!config.link_measurement_interval)
return;
- list_for_each_entry(si, &node->sta_info, node_list) {
+ list_for_each_entry(si, &node->sta_info, node_list)
+ {
if (si->connected != STA_CONNECTED)
continue;
@@ -708,7 +746,8 @@ usteer_local_node_update(struct uloop_timeout *timeout)
ln = container_of(timeout, struct usteer_local_node, update);
node = &ln->node;
- list_for_each_entry(h, &node_handlers, list) {
+ list_for_each_entry(h, &node_handlers, list)
+ {
if (!h->update_node)
continue;
@@ -739,7 +778,8 @@ usteer_local_node_process_bss_tm_queries(struct
uloop_timeout *timeout)
validity_period = 10000 /
usteer_local_node_get_beacon_interval(ln); /* ~ 10 seconds */
- list_for_each_entry_safe(query, tmp, &ln->bss_tm_queries, list) {
+ list_for_each_entry_safe(query, tmp, &ln->bss_tm_queries, list)
+ {
sta = usteer_sta_get(query->sta_addr, false);
if (!sta)
continue;
@@ -748,7 +788,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 */
@@ -808,7 +848,8 @@ usteer_check_node_enabled(struct usteer_local_node *ln)
struct blob_attr *cur;
int rem;
- blobmsg_for_each_attr(cur, config.ssid_list, rem) {
+ blobmsg_for_each_attr(cur, config.ssid_list, rem)
+ {
if (strcmp(blobmsg_get_string(cur), ln->node.ssid) != 0)
continue;
@@ -821,7 +862,8 @@ usteer_check_node_enabled(struct usteer_local_node *ln)
ln->node.disabled = ssid_disabled;
- if (ssid_disabled) {
+ if (ssid_disabled)
+ {
MSG(INFO, "Disconnecting from local node %s\n",
usteer_node_name(&ln->node));
usteer_local_node_state_reset(ln);
usteer_sta_node_cleanup(&ln->node);
@@ -866,7 +908,8 @@ usteer_register_node(struct ubus_context *ctx, const
char *name, uint32_t id)
blobmsg_add_u8(&b, "bss_transition", 1);
ubus_invoke(ctx, id, "bss_mgmt_enable", b.head, NULL, NULL, 1000);
- list_for_each_entry(h, &node_handlers, list) {
+ list_for_each_entry(h, &node_handlers, list)
+ {
if (!h->init_node)
continue;
@@ -879,11 +922,11 @@ usteer_register_node(struct ubus_context *ctx,
const char *name, uint32_t id)
static void
usteer_event_handler(struct ubus_context *ctx, struct
ubus_event_handler *ev,
- const char *type, struct blob_attr *msg)
+ const char *type, struct blob_attr *msg)
{
static const struct blobmsg_policy policy[2] = {
- { .name = "id", .type = BLOBMSG_TYPE_INT32 },
- { .name = "path", .type = BLOBMSG_TYPE_STRING },
+ {.name = "id", .type = BLOBMSG_TYPE_INT32},
+ {.name = "path", .type = BLOBMSG_TYPE_STRING},
};
struct blob_attr *tb[2];
const char *path;
@@ -901,8 +944,7 @@ static void
usteer_register_events(struct ubus_context *ctx)
{
static struct ubus_event_handler handler = {
- .cb = usteer_event_handler
- };
+ .cb = usteer_event_handler};
ubus_register_event_handler(ctx, &handler, "ubus.object.add");
}
@@ -913,8 +955,7 @@ node_list_cb(struct ubus_context *ctx, struct
ubus_object_data *obj, void *priv)
usteer_register_node(ctx, obj->path, obj->id);
}
-int
-usteer_local_node_get_beacon_interval(struct usteer_local_node *ln)
+int usteer_local_node_get_beacon_interval(struct usteer_local_node *ln)
{
/* Check if beacon-interval is not available (pre-21.02+) */
if (ln->beacon_interval < 1)
@@ -937,7 +978,8 @@ void config_set_node_up_script(struct blob_attr *data)
free(node_up_script);
- if (!strlen(val)) {
+ if (!strlen(val))
+ {
node_up_script = NULL;
return;
}
@@ -977,8 +1019,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..96386ca 100644
--- a/main.c
+++ b/main.c
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#include <unistd.h>
@@ -35,7 +35,7 @@ static int dump_time;
LIST_HEAD(node_handlers);
-const char * const event_types[__EVENT_TYPE_MAX] = {
+const char *const event_types[__EVENT_TYPE_MAX] = {
[EVENT_TYPE_PROBE] = "probe",
[EVENT_TYPE_AUTH] = "auth",
[EVENT_TYPE_ASSOC] = "assoc",
@@ -65,7 +65,6 @@ void debug_msg(int level, const char *func, int line,
const char *format, ...)
else
vfprintf(stderr, format, ap);
va_end(ap);
-
}
void debug_msg_cont(int level, const char *format, ...)
@@ -96,6 +95,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;
@@ -127,26 +128,26 @@ void usteer_init_defaults(void)
void usteer_update_time(void)
{
struct timespec ts;
-
clock_gettime(CLOCK_MONOTONIC, &ts);
- current_time = (uint64_t) ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+ current_time = (uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}
static int usage(const char *prog)
{
fprintf(stderr, "Usage: %s [options]\n"
- "Options:\n"
- " -v: Increase debug level (repeat for more messages):\n"
- " 1: info messages\n"
- " 2: debug messages\n"
- " 3: verbose debug messages\n"
- " 4: include network messages\n"
- " 5: include extra testing messages\n"
- " -i <name>: Connect to other instances on interface <name>\n"
- " -s: Output log messages via syslog instead of stderr\n"
- " -D <n>: Do not daemonize, wait for <n> seconds and print\n"
- " remote hosts and nodes\n"
- "\n", prog);
+ "Options:\n"
+ " -v: Increase debug level (repeat for
more messages):\n"
+ " 1: info messages\n"
+ " 2: debug messages\n"
+ " 3: verbose debug messages\n"
+ " 4: include network messages\n"
+ " 5: include extra testing messages\n"
+ " -i <name>: Connect to other instances on
interface <name>\n"
+ " -s: Output log messages via syslog instead
of stderr\n"
+ " -D <n>: Do not daemonize, wait for <n> seconds
and print\n"
+ " remote hosts and nodes\n"
+ "\n",
+ prog);
return 1;
}
@@ -187,8 +188,10 @@ int main(int argc, char **argv)
usteer_init_defaults();
- while ((ch = getopt(argc, argv, "D:i:sv")) != -1) {
- switch(ch) {
+ while ((ch = getopt(argc, argv, "D:i:sv")) != -1)
+ {
+ switch (ch)
+ {
case 'v':
config.debug_level++;
break;
@@ -213,19 +216,24 @@ int main(int argc, char **argv)
uloop_init();
ubus_ctx = ubus_connect(NULL);
- if (!ubus_ctx) {
+ if (!ubus_ctx)
+ {
fprintf(stderr, "Failed to connect to ubus\n");
return -1;
}
ubus_add_uloop(ubus_ctx);
- if (dump_time) {
+ if (dump_time)
+ {
dump_timer.cb = usteer_dump_timeout;
uloop_timeout_set(&dump_timer, dump_time * 1000);
- } else {
+ }
+ else
+ {
usteer_ubus_init(ubus_ctx);
usteer_local_nodes_init(ubus_ctx);
}
+
uloop_run();
uloop_done();
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..7085114 100644
--- a/policy.c
+++ b/policy.c
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#include "usteer.h"
@@ -45,8 +45,7 @@ below_assoc_threshold(struct usteer_node *node_cur,
struct usteer_node *node_new
static bool
better_signal_strength(int signal_cur, int signal_new)
{
- const bool is_better = signal_new - signal_cur
- > (int) config.signal_diff_threshold;
+ const bool is_better = signal_new - signal_cur >
(int)config.signal_diff_threshold;
if (!config.signal_diff_threshold)
return false;
@@ -58,7 +57,7 @@ static bool
below_load_threshold(struct usteer_node *node)
{
return node->n_assoc >= config.load_kick_min_clients &&
- node->load > config.load_kick_threshold;
+ node->load > config.load_kick_threshold;
}
static bool
@@ -67,8 +66,7 @@ has_better_load(struct usteer_node *node_cur, struct
usteer_node *node_new)
return !below_load_threshold(node_cur) &&
below_load_threshold(node_new);
}
-bool
-usteer_policy_node_below_max_assoc(struct usteer_node *node)
+bool usteer_policy_node_below_max_assoc(struct usteer_node *node)
{
return !node->max_assoc || node->n_assoc < node->max_assoc;
}
@@ -81,7 +79,7 @@ over_min_signal(struct usteer_node *node, int signal)
if (config.roam_trigger_snr && signal < usteer_snr_to_signal(node,
config.roam_trigger_snr))
return false;
-
+
return true;
}
@@ -101,7 +99,7 @@ is_better_candidate(struct sta_info *si_cur, struct
sta_info *si_new)
return 0;
if (below_assoc_threshold(current_node, new_node) &&
- !below_assoc_threshold(new_node, current_node))
+ !below_assoc_threshold(new_node, current_node))
reasons |= (1 << UEV_SELECT_REASON_NUM_ASSOC);
if (better_signal_strength(current_signal, new_signal))
@@ -121,7 +119,8 @@ find_better_candidate(struct sta_info *si_ref,
struct uevent *ev, uint32_t requi
struct sta *sta = si_ref->sta;
uint32_t reasons;
- list_for_each_entry(si, &sta->nodes, list) {
+ list_for_each_entry(si, &sta->nodes, list)
+ {
if (si == si_ref)
continue;
@@ -141,7 +140,8 @@ find_better_candidate(struct sta_info *si_ref,
struct uevent *ev, uint32_t requi
if (!(reasons & required_criteria))
continue;
- if (ev) {
+ if (ev)
+ {
ev->si_other = si;
ev->select_reasons = reasons;
}
@@ -153,8 +153,7 @@ find_better_candidate(struct sta_info *si_ref,
struct uevent *ev, uint32_t requi
return candidate;
}
-int
-usteer_snr_to_signal(struct usteer_node *node, int snr)
+int usteer_snr_to_signal(struct usteer_node *node, int snr)
{
int noise = -95;
@@ -167,8 +166,7 @@ usteer_snr_to_signal(struct usteer_node *node, int snr)
return noise + snr;
}
-bool
-usteer_check_request(struct sta_info *si, enum usteer_event_type type)
+bool usteer_check_request(struct sta_info *si, enum usteer_event_type type)
{
struct uevent ev = {
.si_cur = si,
@@ -182,25 +180,30 @@ usteer_check_request(struct sta_info *si, enum
usteer_event_type type)
if (type == EVENT_TYPE_AUTH)
goto out;
- if (type == EVENT_TYPE_ASSOC) {
+ if (type == EVENT_TYPE_ASSOC)
+ {
/* Check if assoc request has lower signal than min_signal.
* If this is the case, block assoc even when assoc steering is
enabled.
*
* Otherwise, the client potentially ends up in a assoc - kick
loop.
*/
- if (config.min_snr && si->signal <
usteer_snr_to_signal(si->node, config.min_snr)) {
+ if (config.min_snr && si->signal <
usteer_snr_to_signal(si->node, config.min_snr))
+ {
ev.reason = UEV_REASON_LOW_SIGNAL;
ev.threshold.cur = si->signal;
ev.threshold.ref = usteer_snr_to_signal(si->node,
config.min_snr);
ret = false;
goto out;
- } else if (!config.assoc_steering) {
+ }
+ else if (!config.assoc_steering)
+ {
goto out;
}
}
min_signal = usteer_snr_to_signal(si->node, config.min_connect_snr);
- if (si->signal < min_signal) {
+ if (si->signal < min_signal)
+ {
ev.reason = UEV_REASON_LOW_SIGNAL;
ev.threshold.cur = si->signal;
ev.threshold.ref = min_signal;
@@ -208,7 +211,8 @@ usteer_check_request(struct sta_info *si, enum
usteer_event_type type)
goto out;
}
- if (current_time - si->created < config.initial_connect_delay) {
+ if (current_time - si->created < config.initial_connect_delay)
+ {
ev.reason = UEV_REASON_CONNECT_DELAY;
ev.threshold.cur = current_time - si->created;
ev.threshold.ref = config.initial_connect_delay;
@@ -224,7 +228,8 @@ usteer_check_request(struct sta_info *si, enum
usteer_event_type type)
ret = false;
out:
- switch (type) {
+ switch (type)
+ {
case EVENT_TYPE_PROBE:
ev.type = ret ? UEV_PROBE_REQ_ACCEPT : UEV_PROBE_REQ_DENY;
break;
@@ -238,7 +243,8 @@ out:
break;
}
- if (!ret && si->stats[type].blocked_cur >= config.max_retry_band) {
+ if (!ret && si->stats[type].blocked_cur >= config.max_retry_band)
+ {
ev.reason = UEV_REASON_RETRY_EXCEEDED;
ev.threshold.cur = si->stats[type].blocked_cur;
ev.threshold.ref = config.max_retry_band;
@@ -262,19 +268,23 @@ is_more_kickable(struct sta_info *si_cur, struct
sta_info *si_new)
static void
usteer_roam_set_state(struct sta_info *si, enum roam_trigger_state state,
- struct uevent *ev)
+ struct uevent *ev)
{
/* NOP in case we remain idle */
- if (si->roam_state == state && si->roam_state == ROAM_TRIGGER_IDLE) {
+ if (si->roam_state == state && si->roam_state == ROAM_TRIGGER_IDLE)
+ {
si->roam_tries = 0;
return;
}
si->roam_event = current_time;
- if (si->roam_state == state) {
+ if (si->roam_state == state)
+ {
si->roam_tries++;
- } else {
+ }
+ else
+ {
si->roam_tries = 0;
}
@@ -287,7 +297,8 @@ usteer_roam_sm_start_scan(struct sta_info *si,
struct uevent *ev)
{
/* Start scanning in case we are not timeout-constrained or timeout
has expired */
if (!config.roam_scan_timeout ||
- current_time > si->roam_scan_timeout_start +
config.roam_scan_timeout) {
+ current_time > si->roam_scan_timeout_start +
config.roam_scan_timeout)
+ {
usteer_roam_set_state(si, ROAM_TRIGGER_SCAN, ev);
return;
}
@@ -326,9 +337,11 @@ usteer_roam_trigger_sm(struct usteer_local_node
*ln, struct sta_info *si)
.si_cur = si,
};
- switch (si->roam_state) {
+ switch (si->roam_state)
+ {
case ROAM_TRIGGER_SCAN:
- if (!si->roam_tries) {
+ if (!si->roam_tries)
+ {
si->roam_scan_start = current_time;
}
@@ -341,11 +354,15 @@ usteer_roam_trigger_sm(struct usteer_local_node
*ln, struct sta_info *si)
break;
/* Check if no node was found within roam_scan_tries tries */
- if (config.roam_scan_tries && si->roam_tries >=
config.roam_scan_tries) {
- if (!config.roam_scan_timeout) {
+ if (config.roam_scan_tries && si->roam_tries >=
config.roam_scan_tries)
+ {
+ if (!config.roam_scan_timeout)
+ {
/* Prepare to kick client */
usteer_roam_set_state(si, ROAM_TRIGGER_SCAN_DONE, &ev);
- } else {
+ }
+ else
+ {
/* Kick in scan timeout */
si->roam_scan_timeout_start = current_time;
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
@@ -365,13 +382,24 @@ usteer_roam_trigger_sm(struct usteer_local_node
*ln, struct sta_info *si)
case ROAM_TRIGGER_SCAN_DONE:
candidate = usteer_roam_sm_found_better_node(si, &ev,
ROAM_TRIGGER_SCAN_DONE);
/* Kick back in case no better node is found */
- if (!candidate) {
+ if (!candidate)
+ {
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, &ev);
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 +428,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;
}
@@ -433,8 +465,10 @@ usteer_local_node_roam_check(struct
usteer_local_node *ln, struct uevent *ev)
usteer_update_time();
min_signal = usteer_snr_to_signal(&ln->node, min_signal);
- list_for_each_entry(si, &ln->node.sta_info, node_list) {
- if (!usteer_local_node_roam_sm_active(si, min_signal)) {
+ list_for_each_entry(si, &ln->node.sta_info, node_list)
+ {
+ if (!usteer_local_node_roam_sm_active(si, min_signal))
+ {
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
continue;
}
@@ -464,14 +498,18 @@ usteer_local_node_snr_kick(struct
usteer_local_node *ln)
min_signal = usteer_snr_to_signal(&ln->node, config.min_snr);
ev.threshold.ref = min_signal;
- 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)
continue;
- if (si->signal >= min_signal) {
+ if (si->signal >= min_signal)
+ {
si->below_min_snr = 0;
continue;
- } else {
+ }
+ else
+ {
si->below_min_snr++;
}
@@ -501,10 +539,11 @@ usteer_local_node_load_kick(struct
usteer_local_node *ln)
unsigned int min_count = DIV_ROUND_UP(config.load_kick_delay,
config.local_sta_update);
if (!config.load_kick_enabled || !config.load_kick_threshold ||
- !config.load_kick_delay)
+ !config.load_kick_delay)
return;
- if (node->load < config.load_kick_threshold) {
+ if (node->load < config.load_kick_threshold)
+ {
if (!ln->load_thr_count)
return;
@@ -515,7 +554,8 @@ usteer_local_node_load_kick(struct usteer_local_node
*ln)
goto out;
}
- if (++ln->load_thr_count <= min_count) {
+ if (++ln->load_thr_count <= min_count)
+ {
if (ln->load_thr_count > 1)
return;
@@ -526,14 +566,16 @@ usteer_local_node_load_kick(struct
usteer_local_node *ln)
}
ln->load_thr_count = 0;
- if (node->n_assoc < config.load_kick_min_clients) {
+ if (node->n_assoc < config.load_kick_min_clients)
+ {
ev.type = UEV_LOAD_KICK_MIN_CLIENTS;
ev.threshold.cur = node->n_assoc;
ev.threshold.ref = config.load_kick_min_clients;
goto out;
}
- list_for_each_entry(si, &ln->node.sta_info, node_list) {
+ list_for_each_entry(si, &ln->node.sta_info, node_list)
+ {
struct sta_info *tmp;
if (si->connected != STA_CONNECTED)
@@ -546,13 +588,15 @@ usteer_local_node_load_kick(struct
usteer_local_node *ln)
if (!tmp)
continue;
- if (is_more_kickable(kick2, si)) {
+ if (is_more_kickable(kick2, si))
+ {
kick2 = si;
candidate = tmp;
}
}
- if (!kick1) {
+ if (!kick1)
+ {
ev.type = UEV_LOAD_KICK_NO_CLIENT;
goto out;
}
@@ -578,7 +622,8 @@ 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) {
+ list_for_each_entry(si, &ln->node.sta_info, node_list)
+ {
if (!si->kick_time || si->kick_time > current_time)
continue;
@@ -586,8 +631,7 @@ usteer_local_node_perform_kick(struct
usteer_local_node *ln)
}
}
-void
-usteer_local_node_kick(struct usteer_local_node *ln)
+void usteer_local_node_kick(struct usteer_local_node *ln)
{
struct uevent ev = {
.node_local = &ln->node,
diff --git a/sta.c b/sta.c
index ed7e40e..42c0576 100644
--- a/sta.c
+++ b/sta.c
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#include "usteer.h"
@@ -28,24 +28,22 @@ avl_macaddr_cmp(const void *k1, const void *k2, void
*ptr)
AVL_TREE(stations, avl_macaddr_cmp, false, NULL);
static struct usteer_timeout_queue tq;
-static void
-usteer_sta_del(struct sta *sta)
+static void usteer_sta_del(struct sta *sta)
{
MSG(DEBUG, "Delete station " MAC_ADDR_FMT "\n",
- MAC_ADDR_DATA(sta->addr));
+ MAC_ADDR_DATA(sta->addr));
avl_delete(&stations, &sta->avl);
usteer_measurement_report_sta_cleanup(sta);
free(sta);
}
-static void
-usteer_sta_info_del(struct sta_info *si)
+static void usteer_sta_info_del(struct sta_info *si)
{
struct sta *sta = si->sta;
MSG(DEBUG, "Delete station " MAC_ADDR_FMT " entry for node %s\n",
- MAC_ADDR_DATA(sta->addr), usteer_node_name(si->node));
+ MAC_ADDR_DATA(sta->addr), usteer_node_name(si->node));
usteer_timeout_cancel(&tq, &si->timeout);
list_del(&si->list);
@@ -56,8 +54,7 @@ usteer_sta_info_del(struct sta_info *si)
usteer_sta_del(sta);
}
-void
-usteer_sta_node_cleanup(struct usteer_node *node)
+void usteer_sta_node_cleanup(struct usteer_node *node)
{
struct sta_info *si, *tmp;
@@ -68,20 +65,42 @@ usteer_sta_node_cleanup(struct usteer_node *node)
usteer_sta_info_del(si);
}
-static void
-usteer_sta_info_timeout(struct usteer_timeout_queue *q, struct
usteer_timeout *t)
+static void usteer_sta_info_timeout(struct usteer_timeout_queue *q,
struct usteer_timeout *t)
{
struct sta_info *si = container_of(t, struct sta_info, timeout);
usteer_sta_info_del(si);
}
-struct sta_info *
-usteer_sta_info_get(struct sta *sta, struct usteer_node *node, bool
*create)
+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)
{
struct sta_info *si;
- list_for_each_entry(si, &sta->nodes, list) {
+ list_for_each_entry(si, &sta->nodes, list)
+ {
if (si->node != node)
continue;
@@ -95,7 +114,7 @@ usteer_sta_info_get(struct sta *sta, struct
usteer_node *node, bool *create)
return NULL;
MSG(DEBUG, "Create station " MAC_ADDR_FMT " entry for node %s\n",
- MAC_ADDR_DATA(sta->addr), usteer_node_name(node));
+ MAC_ADDR_DATA(sta->addr), usteer_node_name(node));
si = calloc(1, sizeof(*si));
si->node = node;
@@ -105,15 +124,15 @@ 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);
return si;
}
-
-void
-usteer_sta_info_update_timeout(struct sta_info *si, int timeout)
+void usteer_sta_info_update_timeout(struct sta_info *si, int timeout)
{
if (si->connected == STA_CONNECTED)
usteer_timeout_cancel(&tq, &si->timeout);
@@ -123,8 +142,7 @@ usteer_sta_info_update_timeout(struct sta_info *si,
int timeout)
usteer_sta_info_del(si);
}
-struct sta *
-usteer_sta_get(const uint8_t *addr, bool create)
+struct sta *usteer_sta_get(const uint8_t *addr, bool create)
{
struct sta *sta;
@@ -154,14 +172,14 @@ void usteer_sta_disconnected(struct sta_info *si)
usteer_sta_info_update_timeout(si, config.local_sta_timeout);
}
-void
-usteer_sta_info_update(struct sta_info *si, int signal, bool avg)
+void usteer_sta_info_update(struct sta_info *si, int signal, bool avg)
{
/* ignore probe request signal when connected */
if (si->connected == STA_CONNECTED && si->signal != NO_SIGNAL && !avg)
signal = NO_SIGNAL;
- if (signal != NO_SIGNAL) {
+ if (signal != NO_SIGNAL)
+ {
si->signal = signal;
usteer_band_steering_sta_update(si);
}
@@ -176,9 +194,8 @@ usteer_sta_info_update(struct sta_info *si, int
signal, bool avg)
usteer_sta_info_update_timeout(si, config.local_sta_timeout);
}
-bool
-usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr,
- enum usteer_event_type type, int freq, int signal)
+bool usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr,
+ enum usteer_event_type type, int freq, int
signal)
{
struct sta *sta;
struct sta_info *si;
@@ -199,11 +216,14 @@ usteer_handle_sta_event(struct usteer_node *node,
const uint8_t *addr,
si->stats[type].blocked_cur = 0;
ret = usteer_check_request(si, type);
- if (!ret) {
+ if (!ret)
+ {
si->stats[type].blocked_cur++;
si->stats[type].blocked_total++;
si->stats[type].blocked_last_time = current_time;
- } else {
+ }
+ else
+ {
si->stats[type].blocked_cur = 0;
}
@@ -213,23 +233,22 @@ usteer_handle_sta_event(struct usteer_node *node,
const uint8_t *addr,
return ret;
}
-bool
-usteer_sta_supports_beacon_measurement_mode(struct sta_info *si, enum
usteer_beacon_measurement_mode mode)
+bool usteer_sta_supports_beacon_measurement_mode(struct sta_info *si,
enum usteer_beacon_measurement_mode mode)
{
- switch (mode) {
- case BEACON_MEASUREMENT_PASSIVE:
- return si->rrm & (1 << 4);
- case BEACON_MEASUREMENT_ACTIVE:
- return si->rrm & (1 << 5);
- case BEACON_MEASUREMENT_TABLE:
- return si->rrm & (1 << 6);
+ switch (mode)
+ {
+ case BEACON_MEASUREMENT_PASSIVE:
+ return si->rrm & (1 << 4);
+ case BEACON_MEASUREMENT_ACTIVE:
+ return si->rrm & (1 << 5);
+ case BEACON_MEASUREMENT_TABLE:
+ return si->rrm & (1 << 6);
}
return false;
}
-bool
-usteer_sta_supports_link_measurement(struct sta_info *si)
+bool usteer_sta_supports_link_measurement(struct sta_info *si)
{
return si->rrm & (1 << 0);
}
diff --git a/ubus.c b/ubus.c
index 40daf74..066a3c3 100644
--- a/ubus.c
+++ b/ubus.c
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#include <sys/types.h>
@@ -41,17 +41,19 @@ blobmsg_open_table_mac(struct blob_buf *buf, uint8_t
*addr)
static int
usteer_ubus_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
struct sta_info *si;
struct sta *sta;
void *_s, *_cur_n;
blob_buf_init(&b, 0);
- avl_for_each_element(&stations, sta, avl) {
+ avl_for_each_element(&stations, sta, avl)
+ {
_s = blobmsg_open_table_mac(&b, sta->addr);
- list_for_each_entry(si, &sta->nodes, list) {
+ list_for_each_entry(si, &sta->nodes, list)
+ {
_cur_n = blobmsg_open_table(&b, usteer_node_name(si->node));
blobmsg_add_u8(&b, "connected", si->connected);
blobmsg_add_u32(&b, "signal", si->signal);
@@ -64,7 +66,10 @@ usteer_ubus_get_clients(struct ubus_context *ctx,
struct ubus_object *obj,
}
static struct blobmsg_policy client_arg[] = {
- { .name = "address", .type = BLOBMSG_TYPE_STRING, },
+ {
+ .name = "address",
+ .type = BLOBMSG_TYPE_STRING,
+ },
};
static void
@@ -81,8 +86,8 @@ usteer_ubus_add_stats(struct sta_info_stats *stats,
const char *name)
static int
usteer_ubus_get_client_info(struct ubus_context *ctx, struct
ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char
*method,
+ struct blob_attr *msg)
{
struct sta_info *si;
struct sta *sta;
@@ -95,7 +100,7 @@ usteer_ubus_get_client_info(struct ubus_context *ctx,
struct ubus_object *obj,
if (!mac_str)
return UBUS_STATUS_INVALID_ARGUMENT;
- mac = (uint8_t *) ether_aton(blobmsg_data(mac_str));
+ mac = (uint8_t *)ether_aton(blobmsg_data(mac_str));
if (!mac)
return UBUS_STATUS_INVALID_ARGUMENT;
@@ -107,7 +112,8 @@ usteer_ubus_get_client_info(struct ubus_context
*ctx, struct ubus_object *obj,
blobmsg_add_u8(&b, "2ghz", sta->seen_2ghz);
blobmsg_add_u8(&b, "5ghz", sta->seen_5ghz);
_n = blobmsg_open_table(&b, "nodes");
- list_for_each_entry(si, &sta->nodes, list) {
+ list_for_each_entry(si, &sta->nodes, list)
+ {
_cur_n = blobmsg_open_table(&b, usteer_node_name(si->node));
blobmsg_add_u8(&b, "connected", si->connected);
blobmsg_add_u32(&b, "signal", si->signal);
@@ -124,7 +130,8 @@ usteer_ubus_get_client_info(struct ubus_context
*ctx, struct ubus_object *obj,
return 0;
}
-enum cfg_type {
+enum cfg_type
+{
CFG_BOOL,
CFG_I32,
CFG_U32,
@@ -132,64 +139,71 @@ enum cfg_type {
CFG_STRING_CB,
};
-struct cfg_item {
+struct cfg_item
+{
enum cfg_type type;
- union {
+ union
+ {
bool *BOOL;
uint32_t *U32;
int32_t *I32;
- struct {
+ struct
+ {
void (*set)(struct blob_attr *data);
void (*get)(struct blob_buf *buf);
} CB;
} ptr;
};
-#define __config_items \
- _cfg(BOOL, syslog), \
- _cfg(U32, debug_level), \
- _cfg(BOOL, ipv6), \
- _cfg(BOOL, local_mode), \
- _cfg(U32, sta_block_timeout), \
- _cfg(U32, local_sta_timeout), \
- _cfg(U32, local_sta_update), \
- _cfg(U32, max_neighbor_reports), \
- _cfg(U32, max_retry_band), \
- _cfg(U32, seen_policy_timeout), \
- _cfg(U32, measurement_report_timeout), \
- _cfg(U32, load_balancing_threshold), \
- _cfg(U32, band_steering_threshold), \
- _cfg(U32, remote_update_interval), \
- _cfg(U32, remote_node_timeout), \
- _cfg(BOOL, assoc_steering), \
- _cfg(I32, min_connect_snr), \
- _cfg(I32, min_snr), \
- _cfg(U32, min_snr_kick_delay), \
- _cfg(U32, steer_reject_timeout), \
- _cfg(U32, roam_process_timeout), \
- _cfg(I32, roam_scan_snr), \
- _cfg(U32, roam_scan_tries), \
- _cfg(U32, roam_scan_timeout), \
- _cfg(U32, roam_scan_interval), \
- _cfg(I32, roam_trigger_snr), \
- _cfg(U32, roam_trigger_interval), \
- _cfg(U32, roam_kick_delay), \
- _cfg(U32, signal_diff_threshold), \
- _cfg(U32, initial_connect_delay), \
- _cfg(BOOL, load_kick_enabled), \
- _cfg(U32, load_kick_threshold), \
- _cfg(U32, load_kick_delay), \
- _cfg(U32, load_kick_min_clients), \
- _cfg(U32, load_kick_reason_code), \
- _cfg(U32, band_steering_interval), \
- _cfg(I32, band_steering_min_snr), \
- _cfg(U32, link_measurement_interval), \
- _cfg(ARRAY_CB, interfaces), \
- _cfg(STRING_CB, node_up_script), \
- _cfg(ARRAY_CB, event_log_types), \
- _cfg(ARRAY_CB, ssid_list)
-
-enum cfg_items {
+#define __config_items \
+ _cfg(BOOL, syslog), \
+ _cfg(U32, debug_level), \
+ _cfg(BOOL, ipv6), \
+ _cfg(BOOL, local_mode), \
+ _cfg(U32, sta_block_timeout), \
+ _cfg(U32, local_sta_timeout), \
+ _cfg(U32, local_sta_update), \
+ _cfg(U32, max_neighbor_reports), \
+ _cfg(U32, max_retry_band), \
+ _cfg(U32, seen_policy_timeout), \
+ _cfg(U32, measurement_report_timeout), \
+ _cfg(U32, load_balancing_threshold), \
+ _cfg(U32, band_steering_threshold), \
+ _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), \
+ _cfg(U32, steer_reject_timeout), \
+ _cfg(U32, roam_process_timeout), \
+ _cfg(I32, roam_scan_snr), \
+ _cfg(U32, roam_scan_tries), \
+ _cfg(U32, roam_scan_timeout), \
+ _cfg(U32, roam_scan_interval), \
+ _cfg(I32, roam_trigger_snr), \
+ _cfg(U32, roam_trigger_interval), \
+ _cfg(U32, roam_kick_delay), \
+ _cfg(U32, signal_diff_threshold), \
+ _cfg(U32, initial_connect_delay), \
+ _cfg(BOOL, load_kick_enabled), \
+ _cfg(U32, load_kick_threshold), \
+ _cfg(U32, load_kick_delay), \
+ _cfg(U32, load_kick_min_clients), \
+ _cfg(U32, load_kick_reason_code), \
+ _cfg(U32, band_steering_interval), \
+ _cfg(I32, band_steering_min_snr), \
+ _cfg(U32, link_measurement_interval), \
+ _cfg(ARRAY_CB, interfaces), \
+ _cfg(STRING_CB, node_up_script), \
+ _cfg(ARRAY_CB, event_log_types), \
+ _cfg(ARRAY_CB, ssid_list)
+
+enum cfg_items
+{
#define _cfg(_type, _name) CFG_##_name
__config_items,
#undef _cfg
@@ -197,7 +211,7 @@ enum cfg_items {
};
static const struct blobmsg_policy config_policy[__CFG_MAX] = {
-#define _cfg_policy(_type, _name) [CFG_##_name] = { .name = #_name,
.type = BLOBMSG_TYPE_ ## _type }
+#define _cfg_policy(_type, _name) [CFG_##_name] = {.name = #_name,
.type = BLOBMSG_TYPE_##_type}
#define _cfg_policy_BOOL(_name) _cfg_policy(BOOL, _name)
#define _cfg_policy_U32(_name) _cfg_policy(INT32, _name)
#define _cfg_policy_I32(_name) _cfg_policy(INT32, _name)
@@ -212,31 +226,33 @@ static const struct cfg_item
config_data[__CFG_MAX] = {
#define _cfg_data_BOOL(_name) .ptr.BOOL = &config._name
#define _cfg_data_U32(_name) .ptr.U32 = &config._name
#define _cfg_data_I32(_name) .ptr.I32 = &config._name
-#define _cfg_data_ARRAY_CB(_name) .ptr.CB = { .set =
config_set_##_name, .get = config_get_##_name }
-#define _cfg_data_STRING_CB(_name) .ptr.CB = { .set =
config_set_##_name, .get = config_get_##_name }
-#define _cfg(_type, _name) [CFG_##_name] = { .type = CFG_##_type,
_cfg_data_##_type(_name) }
+#define _cfg_data_ARRAY_CB(_name) .ptr.CB = {.set = config_set_##_name,
.get = config_get_##_name}
+#define _cfg_data_STRING_CB(_name) .ptr.CB = {.set =
config_set_##_name, .get = config_get_##_name}
+#define _cfg(_type, _name) [CFG_##_name] = {.type = CFG_##_type,
_cfg_data_##_type(_name)}
__config_items,
#undef _cfg
};
static int
usteer_ubus_get_config(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
int i;
blob_buf_init(&b, 0);
- for (i = 0; i < __CFG_MAX; i++) {
- switch(config_data[i].type) {
+ for (i = 0; i < __CFG_MAX; i++)
+ {
+ switch (config_data[i].type)
+ {
case CFG_BOOL:
blobmsg_add_u8(&b, config_policy[i].name,
- *config_data[i].ptr.BOOL);
+ *config_data[i].ptr.BOOL);
break;
case CFG_I32:
case CFG_U32:
blobmsg_add_u32(&b, config_policy[i].name,
- *config_data[i].ptr.U32);
+ *config_data[i].ptr.U32);
break;
case CFG_ARRAY_CB:
case CFG_STRING_CB:
@@ -250,8 +266,8 @@ usteer_ubus_get_config(struct ubus_context *ctx,
struct ubus_object *obj,
static int
usteer_ubus_set_config(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
struct blob_attr *tb[__CFG_MAX];
int i;
@@ -260,8 +276,10 @@ usteer_ubus_set_config(struct ubus_context *ctx,
struct ubus_object *obj,
usteer_init_defaults();
blobmsg_parse(config_policy, __CFG_MAX, tb, blob_data(msg),
blob_len(msg));
- for (i = 0; i < __CFG_MAX; i++) {
- switch(config_data[i].type) {
+ for (i = 0; i < __CFG_MAX; i++)
+ {
+ switch (config_data[i].type)
+ {
case CFG_BOOL:
if (!tb[i])
continue;
@@ -307,12 +325,12 @@ void usteer_dump_node(struct blob_buf *buf, struct
usteer_node *node)
if (node->rrm_nr)
blobmsg_add_field(buf, BLOBMSG_TYPE_ARRAY, "rrm_nr",
- blobmsg_data(node->rrm_nr),
- blobmsg_data_len(node->rrm_nr));
+ blobmsg_data(node->rrm_nr),
+ blobmsg_data_len(node->rrm_nr));
if (node->node_info)
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "node_info",
- blob_data(node->node_info),
- blob_len(node->node_info));
+ blob_data(node->node_info),
+ blob_len(node->node_info));
blobmsg_close_table(buf, c);
}
@@ -325,15 +343,15 @@ void usteer_dump_host(struct blob_buf *buf, struct
usteer_remote_host *host)
blobmsg_add_u32(buf, "id", (uint32_t)(uintptr_t)host->avl.key);
if (host->host_info)
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "host_info",
- blobmsg_data(host->host_info),
- blobmsg_len(host->host_info));
+ blobmsg_data(host->host_info),
+ blobmsg_len(host->host_info));
blobmsg_close_table(buf, c);
}
static int
usteer_ubus_local_info(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
struct usteer_node *node;
@@ -349,8 +367,8 @@ usteer_ubus_local_info(struct ubus_context *ctx,
struct ubus_object *obj,
static int
usteer_ubus_remote_hosts(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
struct usteer_remote_host *host;
@@ -366,8 +384,8 @@ usteer_ubus_remote_hosts(struct ubus_context *ctx,
struct ubus_object *obj,
static int
usteer_ubus_remote_info(struct ubus_context *ctx, struct ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
{
struct usteer_remote_node *rn;
@@ -383,21 +401,22 @@ usteer_ubus_remote_info(struct ubus_context *ctx,
struct ubus_object *obj,
static const char *usteer_get_roam_sm_name(enum roam_trigger_state state)
{
- switch (state) {
- case ROAM_TRIGGER_IDLE:
- return "ROAM_TRIGGER_IDLE";
- case ROAM_TRIGGER_SCAN:
- return "ROAM_TRIGGER_SCAN";
- case ROAM_TRIGGER_SCAN_DONE:
- return "ROAM_TRIGGER_SCAN_DONE";
+ switch (state)
+ {
+ case ROAM_TRIGGER_IDLE:
+ return "ROAM_TRIGGER_IDLE";
+ case ROAM_TRIGGER_SCAN:
+ return "ROAM_TRIGGER_SCAN";
+ case ROAM_TRIGGER_SCAN_DONE:
+ return "ROAM_TRIGGER_SCAN_DONE";
}
return "N/A";
}
static int
usteer_ubus_get_connected_clients(struct ubus_context *ctx, struct
ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const
char *method,
+ struct blob_attr *msg)
{
struct usteer_measurement_report *mr;
struct usteer_node *node;
@@ -406,10 +425,12 @@ usteer_ubus_get_connected_clients(struct
ubus_context *ctx, struct ubus_object *
blob_buf_init(&b, 0);
- for_each_local_node(node) {
+ for_each_local_node(node)
+ {
n = blobmsg_open_table(&b, usteer_node_name(node));
- list_for_each_entry(si, &node->sta_info, node_list) {
+ list_for_each_entry(si, &node->sta_info, node_list)
+ {
if (si->connected != STA_CONNECTED)
continue;
@@ -423,7 +444,7 @@ usteer_ubus_get_connected_clients(struct
ubus_context *ctx, struct ubus_object *
blobmsg_close_table(&b, t);
t = blobmsg_open_table(&b, "roam-state-machine");
- blobmsg_add_string(&b,
"state",usteer_get_roam_sm_name(si->roam_state));
+ blobmsg_add_string(&b, "state",
usteer_get_roam_sm_name(si->roam_state));
blobmsg_add_u32(&b, "tries", si->roam_tries);
blobmsg_add_u64(&b, "event", si->roam_event ? current_time
- si->roam_event : 0);
blobmsg_add_u32(&b, "kick-count", si->kick_count);
@@ -458,7 +479,8 @@ usteer_ubus_get_connected_clients(struct
ubus_context *ctx, struct ubus_object *
/* Measurements */
a = blobmsg_open_array(&b, "measurements");
- list_for_each_entry(mr, &si->sta->measurements, sta_list) {
+ list_for_each_entry(mr, &si->sta->measurements, sta_list)
+ {
t = blobmsg_open_table(&b, "");
blobmsg_add_string(&b, "node", usteer_node_name(mr->node));
blobmsg_add_u32(&b, "rcpi", mr->rcpi);
@@ -480,30 +502,32 @@ usteer_ubus_get_connected_clients(struct
ubus_context *ctx, struct ubus_object *
return 0;
}
-enum {
+enum
+{
NODE_DATA_NODE,
NODE_DATA_VALUES,
__NODE_DATA_MAX,
};
static const struct blobmsg_policy set_node_data_policy[] = {
- [NODE_DATA_NODE] = { "node", BLOBMSG_TYPE_STRING },
- [NODE_DATA_VALUES] = { "data", BLOBMSG_TYPE_TABLE },
+ [NODE_DATA_NODE] = {"node", BLOBMSG_TYPE_STRING},
+ [NODE_DATA_VALUES] = {"data", BLOBMSG_TYPE_TABLE},
};
static const struct blobmsg_policy del_node_data_policy[] = {
- [NODE_DATA_NODE] = { "node", BLOBMSG_TYPE_STRING },
- [NODE_DATA_VALUES] = { "names", BLOBMSG_TYPE_ARRAY },
+ [NODE_DATA_NODE] = {"node", BLOBMSG_TYPE_STRING},
+ [NODE_DATA_VALUES] = {"names", BLOBMSG_TYPE_ARRAY},
};
static void
usteer_update_kvlist_data(struct kvlist *kv, struct blob_attr *data,
- bool delete)
+ bool delete)
{
struct blob_attr *cur;
int rem;
- blobmsg_for_each_attr(cur, data, rem) {
+ blobmsg_for_each_attr(cur, data, rem)
+ {
if (delete)
kvlist_delete(kv, blobmsg_get_string(cur));
else
@@ -520,7 +544,7 @@ usteer_update_kvlist_blob(struct blob_attr **dest,
struct kvlist *kv)
blob_buf_init(&b, 0);
kvlist_for_each(kv, name, val)
blobmsg_add_field(&b, blobmsg_type(val), name,
- blobmsg_data(val), blobmsg_len(val));
+ blobmsg_data(val), blobmsg_len(val));
val = b.head;
if (!blobmsg_len(val))
@@ -531,8 +555,8 @@ usteer_update_kvlist_blob(struct blob_attr **dest,
struct kvlist *kv)
static int
usteer_ubus_update_node_data(struct ubus_context *ctx, struct
ubus_object *obj,
- struct ubus_request_data *req, const char *method,
- struct blob_attr *msg)
+ struct ubus_request_data *req, const char
*method,
+ struct blob_attr *msg)
{
const struct blobmsg_policy *policy;
struct blob_attr *tb[__NODE_DATA_MAX];
@@ -550,10 +574,11 @@ usteer_ubus_update_node_data(struct ubus_context
*ctx, struct ubus_object *obj,
name = blobmsg_get_string(tb[NODE_DATA_NODE]);
val = tb[NODE_DATA_VALUES];
- if (delete && blobmsg_check_array(val, BLOBMSG_TYPE_STRING) < 0)
+ if (delete &&blobmsg_check_array(val, BLOBMSG_TYPE_STRING) < 0)
return UBUS_STATUS_INVALID_ARGUMENT;
- if (strcmp(name, "*") != 0) {
+ if (strcmp(name, "*") != 0)
+ {
ln = avl_find_element(&local_nodes, name, ln, node.avl);
if (!ln)
return UBUS_STATUS_NOT_FOUND;
@@ -598,9 +623,9 @@ static bool
usteer_add_nr_entry(struct usteer_node *ln, struct usteer_node *node)
{
struct blobmsg_policy policy[3] = {
- { .type = BLOBMSG_TYPE_STRING },
- { .type = BLOBMSG_TYPE_STRING },
- { .type = BLOBMSG_TYPE_STRING },
+ {.type = BLOBMSG_TYPE_STRING},
+ {.type = BLOBMSG_TYPE_STRING},
+ {.type = BLOBMSG_TYPE_STRING},
};
struct blob_attr *tb[3];
@@ -614,15 +639,15 @@ usteer_add_nr_entry(struct usteer_node *ln, struct
usteer_node *node)
return false;
blobmsg_parse_array(policy, ARRAY_SIZE(tb), tb,
- blobmsg_data(node->rrm_nr),
- blobmsg_data_len(node->rrm_nr));
+ blobmsg_data(node->rrm_nr),
+ blobmsg_data_len(node->rrm_nr));
if (!tb[2])
return false;
blobmsg_add_field(&b, BLOBMSG_TYPE_STRING, "",
- blobmsg_data(tb[2]),
- blobmsg_data_len(tb[2]));
-
+ blobmsg_data(tb[2]),
+ blobmsg_data_len(tb[2]));
+
return true;
}
@@ -644,7 +669,8 @@ usteer_ubus_disassoc_add_neighbors(struct sta_info *si)
void *c;
c = blobmsg_open_array(&b, "neighbors");
- for_each_local_node(node) {
+ for_each_local_node(node)
+ {
if (i >= config.max_neighbor_reports)
break;
if (si->node == node)
@@ -653,9 +679,11 @@ usteer_ubus_disassoc_add_neighbors(struct sta_info *si)
i++;
}
- while (i < config.max_neighbor_reports) {
+ while (i < config.max_neighbor_reports)
+ {
node = usteer_node_get_next_neighbor(si->node,
last_remote_neighbor);
- if (!node) {
+ if (!node)
+ {
/* No more nodes available */
break;
}
@@ -668,11 +696,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 +709,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 +742,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)
@@ -733,7 +787,8 @@ int usteer_ubus_trigger_client_scan(struct sta_info *si)
{
struct usteer_local_node *ln = container_of(si->node, struct
usteer_local_node, node);
- if (!usteer_sta_supports_beacon_measurement_mode(si,
BEACON_MEASUREMENT_ACTIVE)) {
+ if (!usteer_sta_supports_beacon_measurement_mode(si,
BEACON_MEASUREMENT_ACTIVE))
+ {
MSG(DEBUG, "STA does not support beacon measurement sta="
MAC_ADDR_FMT "\n", MAC_ADDR_DATA(si->sta->addr));
return 0;
}
diff --git a/usteer.h b/usteer.h
index f692fb8..26eeff0 100644
--- a/usteer.h
+++ b/usteer.h
@@ -12,9 +12,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
*
- * Copyright (C) 2020 embedd.ch
- * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
- * Copyright (C) 2020 John Crispin <john at phrozen.org>
+ * Copyright (C) 2020 embedd.ch
+ * Copyright (C) 2020 Felix Fietkau <nbd at nbd.name>
+ * Copyright (C) 2020 John Crispin <john at phrozen.org>
*/
#ifndef __APMGR_H
@@ -31,36 +31,40 @@
#define NO_SIGNAL 0xff
-#define __STR(x) #x
-#define _STR(x) __STR(x)
+#define __STR(x) #x
+#define _STR(x) __STR(x)
-#define APMGR_V6_MCAST_GROUP "ff02::4150"
+#define APMGR_V6_MCAST_GROUP "ff02::4150"
-#define APMGR_PORT 16720 /* AP */
-#define APMGR_PORT_STR _STR(APMGR_PORT)
-#define APMGR_BUFLEN (64 * 1024)
+#define APMGR_PORT 16720 /* AP */
+#define APMGR_PORT_STR _STR(APMGR_PORT)
+#define APMGR_BUFLEN (64 * 1024)
-#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
-enum usteer_event_type {
+enum usteer_event_type
+{
EVENT_TYPE_PROBE,
EVENT_TYPE_ASSOC,
EVENT_TYPE_AUTH,
__EVENT_TYPE_MAX,
};
-enum usteer_node_type {
+enum usteer_node_type
+{
NODE_TYPE_LOCAL,
NODE_TYPE_REMOTE,
};
-enum usteer_sta_connection_state {
+enum usteer_sta_connection_state
+{
STA_NOT_CONNECTED = 0,
STA_CONNECTED = 1,
STA_DISCONNECTED = 2,
};
-enum usteer_beacon_measurement_mode {
+enum usteer_beacon_measurement_mode
+{
BEACON_MEASUREMENT_PASSIVE = 0,
BEACON_MEASUREMENT_ACTIVE = 1,
BEACON_MEASUREMENT_TABLE = 2,
@@ -70,7 +74,8 @@ struct sta_info;
struct usteer_local_node;
struct usteer_remote_host;
-struct usteer_node {
+struct usteer_node
+{
struct avl_node avl;
struct list_head sta_info;
struct list_head measurements;
@@ -91,7 +96,8 @@ struct usteer_node {
int max_assoc;
int load;
- struct {
+ struct
+ {
int source;
int target;
} roam_events;
@@ -99,14 +105,16 @@ struct usteer_node {
uint64_t created;
};
-struct usteer_scan_request {
+struct usteer_scan_request
+{
int n_freq;
int *freq;
bool passive;
};
-struct usteer_scan_result {
+struct usteer_scan_result
+{
uint8_t bssid[6];
char ssid[33];
@@ -114,7 +122,8 @@ struct usteer_scan_result {
int signal;
};
-struct usteer_survey_data {
+struct usteer_survey_data
+{
uint16_t freq;
int8_t noise;
@@ -122,14 +131,16 @@ struct usteer_survey_data {
uint64_t time_busy;
};
-struct usteer_freq_data {
+struct usteer_freq_data
+{
uint16_t freq;
uint8_t txpower;
bool dfs;
};
-struct usteer_node_handler {
+struct usteer_node_handler
+{
struct list_head list;
void (*init_node)(struct usteer_node *);
@@ -137,14 +148,15 @@ struct usteer_node_handler {
void (*update_node)(struct usteer_node *);
void (*update_sta)(struct usteer_node *, struct sta_info *);
void (*get_survey)(struct usteer_node *, void *,
- void (*cb)(void *priv, struct usteer_survey_data *d));
+ void (*cb)(void *priv, struct usteer_survey_data
*d));
void (*get_freqlist)(struct usteer_node *, void *,
- void (*cb)(void *priv, struct usteer_freq_data *f));
+ void (*cb)(void *priv, struct usteer_freq_data
*f));
int (*scan)(struct usteer_node *, struct usteer_scan_request *,
- void *, void (*cb)(void *priv, struct usteer_scan_result *r));
+ void *, void (*cb)(void *priv, struct
usteer_scan_result *r));
};
-struct usteer_config {
+struct usteer_config
+{
bool syslog;
uint32_t debug_level;
@@ -170,6 +182,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 +206,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;
@@ -208,7 +224,8 @@ struct usteer_config {
struct blob_attr *ssid_list;
};
-struct usteer_bss_tm_query {
+struct usteer_bss_tm_query
+{
struct list_head list;
/* Can't use sta_info here, as the STA might already be deleted */
@@ -216,20 +233,23 @@ struct usteer_bss_tm_query {
uint8_t dialog_token;
};
-struct sta_info_stats {
+struct sta_info_stats
+{
uint32_t requests;
uint32_t blocked_cur;
uint32_t blocked_total;
uint32_t blocked_last_time;
};
-enum roam_trigger_state {
+enum roam_trigger_state
+{
ROAM_TRIGGER_IDLE,
ROAM_TRIGGER_SCAN,
ROAM_TRIGGER_SCAN_DONE,
};
-struct sta_info {
+struct sta_info
+{
struct list_head list;
struct list_head node_list;
@@ -255,15 +275,18 @@ 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;
- struct {
+ struct
+ {
uint8_t status_code;
uint64_t timestamp;
} bss_transition_response;
- struct {
+ struct
+ {
bool below_snr;
} band_steering;
@@ -277,7 +300,8 @@ struct sta_info {
uint8_t connected : 2;
};
-struct sta {
+struct sta
+{
struct avl_node avl;
struct list_head nodes;
struct list_head measurements;
@@ -285,10 +309,13 @@ struct sta {
uint8_t seen_2ghz : 1;
uint8_t seen_5ghz : 1;
+ bool aggressive;
+
uint8_t addr[6];
};
-struct usteer_measurement_report {
+struct usteer_measurement_report
+{
struct usteer_timeout timeout;
struct list_head list;
@@ -311,13 +338,13 @@ extern struct list_head node_handlers;
extern struct avl_tree stations;
extern struct ubus_object usteer_obj;
extern uint64_t current_time;
-extern const char * const event_types[__EVENT_TYPE_MAX];
+extern const char *const event_types[__EVENT_TYPE_MAX];
extern struct blob_attr *host_info_blob;
void usteer_update_time(void);
void usteer_init_defaults(void);
bool usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr,
- enum usteer_event_type type, int freq, int signal);
+ enum usteer_event_type type, int freq, int
signal);
int usteer_snr_to_signal(struct usteer_node *node, int snr);
@@ -336,13 +363,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 +409,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);
@@ -390,7 +426,7 @@ void usteer_dump_host(struct blob_buf *buf, struct
usteer_remote_host *host);
int usteer_measurement_get_rssi(struct usteer_measurement_report *report);
-struct usteer_measurement_report * usteer_measurement_report_get(struct
sta *sta, struct usteer_node *node, bool create);
+struct usteer_measurement_report *usteer_measurement_report_get(struct
sta *sta, struct usteer_node *node, bool create);
void usteer_measurement_report_node_cleanup(struct usteer_node *node);
void usteer_measurement_report_sta_cleanup(struct sta *sta);
void usteer_measurement_report_del(struct usteer_measurement_report *mr);
@@ -398,6 +434,5 @@ void usteer_measurement_report_del(struct
usteer_measurement_report *mr);
struct usteer_measurement_report *
usteer_measurement_report_add(struct sta *sta, struct usteer_node
*node, uint8_t rcpi, uint8_t rsni, uint64_t timestamp);
-
int usteer_ubus_trigger_link_measurement(struct sta_info *si);
#endif
--
2.39.5
More information about the openwrt-devel
mailing list