Compare commits

10 Commits

Author SHA1 Message Date
Christian Marangi
e218150979 remote: close file on usteer_init_local_id fread fail
Fix Coverity Scan CID 1521041 reporting a not closed FILE on fread fail.
Correctly close the FILE on fread fail to fix this leak.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
2023-05-29 19:27:02 +02:00
David Bauer
7d2b17c91b ubus: optimize connected_clients output format
- Drop seen / last-connected as the list only contains currently
   connected clients
 - Convert past timestamps to relative age
 - Include current roam-sm state

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-18 15:32:31 +02:00
David Bauer
8b10a4b296 policy: don't alter stats when remaining idle
Don't alter roam-sm stats when remaining idle. Previously, a
roam-sm-event was registered when keeping the idle-state.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-18 15:31:31 +02:00
David Bauer
3cc0f456f0 policy: count kick total
Always increase the kick-counter when usteer de-associates a STA. This
was previously exclusively done when kicking clients due to insufficient
SNR.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-18 15:30:28 +02:00
David Bauer
aadc562dcb policy: make steering ability evaluation uniform
Usteer imposes minimum intervals for steering actions in order to avoid
creating endless roam-kick loops due to the decentral aspect of usteer.

Make these basic limits to roamsteering usable across band-steering and
signal-based roam-steering.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-17 23:00:42 +02:00
David Bauer
17c558d4b9 ubus: include SSID in node dump
Include a nodes SSID into the ubus dump.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-17 22:57:33 +02:00
David Bauer
fc158e0ec7 policy: only trigger roam-sm after client becomes roamable
Onky trigger the roaming-sm after a client becomes roamable. This is the
case when a STA is connected for longer than roam_trigger_interval.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-17 22:08:05 +02:00
David Bauer
837f144f6c usteer: add connected-since
Fetch the age of the association for STAs in order to implement minimum
intervals after which a STA is considered kickable.

Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-17 22:07:53 +02:00
David Bauer
9e6002d29a policy: improve readability
Signed-off-by: David Bauer <mail@david-bauer.net>
2022-08-17 22:07:42 +02:00
Stijn Tintel
041e884240 local_node: query client MBO support from hostapd
Query client MBO support from hostapd and display it in the output of
the connected_clients ubus method as "multi-band-operation".

Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
2022-08-16 10:40:28 +03:00
8 changed files with 100 additions and 27 deletions

View File

@@ -81,7 +81,8 @@ void usteer_band_steering_perform_steer(struct usteer_local_node *ln)
ln->band_steering_interval = 0;
list_for_each_entry(si, &ln->node.sta_info, node_list) {
if (si->connected != STA_CONNECTED)
/* Check if client is eligable to be steerd */
if (!usteer_policy_can_perform_roam(si))
continue;
/* Skip clients with insufficient SNR-state */

View File

@@ -388,6 +388,10 @@ usteer_local_node_assoc_update(struct sta_info *si, struct blob_attr *data)
static void
usteer_local_node_update_sta_rrm_wnm(struct sta_info *si, struct blob_attr *client_attr)
{
static const struct blobmsg_policy mbo_policy = {
.name = "mbo",
.type = BLOBMSG_TYPE_BOOL,
};
static const struct blobmsg_policy rrm_policy = {
.name = "rrm",
.type = BLOBMSG_TYPE_ARRAY,
@@ -396,10 +400,18 @@ usteer_local_node_update_sta_rrm_wnm(struct sta_info *si, struct blob_attr *clie
.name = "extended_capabilities",
.type = BLOBMSG_TYPE_ARRAY,
};
struct blob_attr *rrm_blob = NULL, *wnm_blob = NULL, *cur;
struct blob_attr *mbo_blob = NULL, *rrm_blob = NULL, *wnm_blob = NULL, *cur;
int rem;
int i = 0;
/* MBO */
blobmsg_parse(&mbo_policy, 1, &mbo_blob, blobmsg_data(client_attr), blobmsg_data_len(client_attr));
if (mbo_blob)
si->mbo = blobmsg_get_u8(mbo_blob);
else
si->mbo = false;
/* RRM */
blobmsg_parse(&rrm_policy, 1, &rrm_blob, blobmsg_data(client_attr), blobmsg_data_len(client_attr));
if (!rrm_blob)

View File

@@ -269,6 +269,9 @@ static void nl80211_update_sta(struct usteer_node *node, struct sta_info *si)
if (tb_sta[NL80211_STA_INFO_SIGNAL_AVG])
signal = (int8_t) nla_get_u8(tb_sta[NL80211_STA_INFO_SIGNAL_AVG]);
if (tb_sta[NL80211_STA_INFO_CONNECTED_TIME])
si->connected_since = current_time - (nla_get_u32(tb_sta[NL80211_STA_INFO_CONNECTED_TIME]) * 1000);
usteer_sta_info_update(si, signal, true);

View File

@@ -264,14 +264,15 @@ static void
usteer_roam_set_state(struct sta_info *si, enum roam_trigger_state state,
struct uevent *ev)
{
/* NOP in case we remain 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 == ROAM_TRIGGER_IDLE) {
si->roam_tries = 0;
return;
}
si->roam_tries++;
} else {
si->roam_tries = 0;
@@ -378,6 +379,44 @@ usteer_roam_trigger_sm(struct usteer_local_node *ln, struct sta_info *si)
return false;
}
bool usteer_policy_can_perform_roam(struct sta_info *si)
{
/* Only trigger for connected STAs */
if (si->connected != STA_CONNECTED)
return false;
/* Skip on pending kick */
if (si->kick_time)
return false;
/* Skip on rejected transition */
if (si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.steer_reject_timeout)
return false;
/* Skip on previous kick attempt */
if (current_time - si->roam_kick < config.roam_trigger_interval)
return false;
/* Skip if connection is established shorter than the trigger-interval */
if (current_time - si->connected_since < config.roam_trigger_interval)
return false;
return true;
}
static bool
usteer_local_node_roam_sm_active(struct sta_info *si, int min_signal)
{
if (!usteer_policy_can_perform_roam(si))
return false;
/* Signal has to be below scan / roam threshold */
if (si->signal >= min_signal)
return false;
return true;
}
static void
usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev)
{
@@ -395,10 +434,7 @@ usteer_local_node_roam_check(struct usteer_local_node *ln, struct uevent *ev)
min_signal = usteer_snr_to_signal(&ln->node, min_signal);
list_for_each_entry(si, &ln->node.sta_info, node_list) {
if (si->connected != STA_CONNECTED || si->signal >= min_signal ||
si->kick_time ||
(si->bss_transition_response.status_code && current_time - si->bss_transition_response.timestamp < config.steer_reject_timeout) ||
current_time - si->roam_kick < config.roam_trigger_interval) {
if (!usteer_local_node_roam_sm_active(si, min_signal)) {
usteer_roam_set_state(si, ROAM_TRIGGER_IDLE, ev);
continue;
}
@@ -442,8 +478,6 @@ usteer_local_node_snr_kick(struct usteer_local_node *ln)
if (si->below_min_snr <= min_count)
continue;
si->kick_count++;
ev.type = UEV_SIGNAL_KICK;
ev.threshold.cur = si->signal;
ev.count = si->kick_count;

View File

@@ -678,8 +678,10 @@ usteer_init_local_id(void)
return -1;
}
if (fread(&local_id, sizeof(local_id), 1, f) < 1)
if (fread(&local_id, sizeof(local_id), 1, f) < 1) {
fclose(f);
return -1;
}
fclose(f);
return 0;

1
sta.c
View File

@@ -150,6 +150,7 @@ void usteer_sta_disconnected(struct sta_info *si)
{
si->connected = STA_NOT_CONNECTED;
si->kick_time = 0;
si->connected_since = 0;
usteer_sta_info_update_timeout(si, config.local_sta_timeout);
}

41
ubus.c
View File

@@ -293,6 +293,7 @@ void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node)
c = blobmsg_open_table(buf, usteer_node_name(node));
blobmsg_printf(buf, "bssid", MAC_ADDR_FMT, MAC_ADDR_DATA(node->bssid));
blobmsg_add_string(buf, "ssid", node->ssid);
blobmsg_add_u32(buf, "freq", node->freq);
blobmsg_add_u32(buf, "n_assoc", node->n_assoc);
blobmsg_add_u32(buf, "noise", node->noise);
@@ -380,6 +381,19 @@ usteer_ubus_remote_info(struct ubus_context *ctx, struct ubus_object *obj,
return 0;
}
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";
}
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,
@@ -401,29 +415,26 @@ usteer_ubus_get_connected_clients(struct ubus_context *ctx, struct ubus_object *
s = blobmsg_open_table_mac(&b, si->sta->addr);
blobmsg_add_u32(&b, "signal", si->signal);
blobmsg_add_u64(&b, "created", si->created);
blobmsg_add_u64(&b, "seen", si->seen);
blobmsg_add_u64(&b, "last_connected", si->last_connected);
blobmsg_add_u64(&b, "created", current_time - si->created);
blobmsg_add_u64(&b, "connected", current_time - si->connected_since);
t = blobmsg_open_table(&b, "snr-kick");
blobmsg_add_u32(&b, "seen-below", si->below_min_snr);
blobmsg_close_table(&b, t);
t = blobmsg_open_table(&b, "load-kick");
blobmsg_add_u32(&b, "count", si->kick_count);
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_u32(&b, "tries", si->roam_tries);
blobmsg_add_u64(&b, "event", si->roam_event);
blobmsg_add_u64(&b, "kick", si->roam_kick);
blobmsg_add_u64(&b, "scan_start", si->roam_scan_start);
blobmsg_add_u64(&b, "scan_timeout_start", si->roam_scan_timeout_start);
blobmsg_add_u64(&b, "event", si->roam_event ? current_time - si->roam_event : 0);
blobmsg_add_u32(&b, "kick-count", si->kick_count);
blobmsg_add_u64(&b, "last-kick", si->roam_kick ? current_time - si->roam_kick : 0);
blobmsg_add_u64(&b, "scan_start", si->roam_scan_start ? current_time - si->roam_scan_start : 0);
blobmsg_add_u64(&b, "scan_timeout_start", si->roam_scan_timeout_start ? current_time - si->roam_scan_timeout_start : 0);
blobmsg_close_table(&b, t);
t = blobmsg_open_table(&b, "bss-transition-response");
blobmsg_add_u32(&b, "status-code", si->bss_transition_response.status_code);
blobmsg_add_u64(&b, "timestamp", si->bss_transition_response.timestamp);
blobmsg_add_u64(&b, "age", si->bss_transition_response.timestamp ? current_time - si->bss_transition_response.timestamp : 0);
blobmsg_close_table(&b, t);
/* Beacon measurement modes */
@@ -442,6 +453,9 @@ usteer_ubus_get_connected_clients(struct ubus_context *ctx, struct ubus_object *
/* BSS-Transition support */
blobmsg_add_u8(&b, "bss-transition-management", si->bss_transition);
/* MBO support */
blobmsg_add_u8(&b, "multi-band-operation", si->mbo);
/* Measurements */
a = blobmsg_open_array(&b, "measurements");
list_for_each_entry(mr, &si->sta->measurements, sta_list) {
@@ -450,7 +464,7 @@ usteer_ubus_get_connected_clients(struct ubus_context *ctx, struct ubus_object *
blobmsg_add_u32(&b, "rcpi", mr->rcpi);
blobmsg_add_u32(&b, "rsni", mr->rsni);
blobmsg_add_u32(&b, "rssi", usteer_measurement_get_rssi(mr));
blobmsg_add_u64(&b, "timestamp", mr->timestamp);
blobmsg_add_u64(&b, "age", current_time - mr->timestamp);
blobmsg_close_table(&b, t);
}
blobmsg_close_array(&b, a);
@@ -746,6 +760,7 @@ void usteer_ubus_kick_client(struct sta_info *si)
blobmsg_add_u8(&b, "deauth", 1);
ubus_invoke(ubus_ctx, ln->obj_id, "del_client", b.head, NULL, 0, 100);
usteer_sta_disconnected(si);
si->kick_count++;
si->roam_kick = current_time;
}

View File

@@ -241,11 +241,15 @@ struct sta_info {
struct sta_info_stats stats[__EVENT_TYPE_MAX];
uint64_t created;
uint64_t seen;
uint64_t connected_since;
uint64_t last_connected;
int signal;
uint8_t rrm;
bool bss_transition;
bool mbo;
enum roam_trigger_state roam_state;
uint8_t roam_tries;
@@ -323,6 +327,7 @@ void usteer_local_node_kick(struct usteer_local_node *ln);
int usteer_local_node_get_beacon_interval(struct usteer_local_node *ln);
bool usteer_policy_node_below_max_assoc(struct usteer_node *node);
bool usteer_policy_can_perform_roam(struct sta_info *si);
void usteer_band_steering_perform_steer(struct usteer_local_node *ln);
void usteer_band_steering_sta_update(struct sta_info *si);