local-node: prioritize neighbor candidates
Prioritize neighbor candidates installed to hostapd. Add a new config option to set a limit for neighbor reports installed to hostapd. This is due to the fact, most devices will only evaluate a certain amount of neighbor reports. Furthermore, the number of neighbor reports possible is limited by the maximum frame size. Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
38
local_node.c
38
local_node.c
@@ -287,35 +287,53 @@ usteer_local_node_req_cb(struct ubus_request *req, int ret)
|
|||||||
uloop_timeout_set(&ln->req_timer, 1);
|
uloop_timeout_set(&ln->req_timer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
usteer_add_rrm_data(struct usteer_local_node *ln, struct usteer_node *node)
|
usteer_add_rrm_data(struct usteer_local_node *ln, struct usteer_node *node)
|
||||||
{
|
{
|
||||||
if (node == &ln->node)
|
if (node == &ln->node)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (!node->rrm_nr)
|
if (!node->rrm_nr)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
|
/* Remote node only adds same SSID. Required for local-node. */
|
||||||
if (strcmp(ln->node.ssid, node->ssid) != 0)
|
if (strcmp(ln->node.ssid, node->ssid) != 0)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
blobmsg_add_field(&b, BLOBMSG_TYPE_ARRAY, "",
|
blobmsg_add_field(&b, BLOBMSG_TYPE_ARRAY, "",
|
||||||
blobmsg_data(node->rrm_nr),
|
blobmsg_data(node->rrm_nr),
|
||||||
blobmsg_data_len(node->rrm_nr));
|
blobmsg_data_len(node->rrm_nr));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usteer_local_node_prepare_rrm_set(struct usteer_local_node *ln)
|
usteer_local_node_prepare_rrm_set(struct usteer_local_node *ln)
|
||||||
{
|
{
|
||||||
struct usteer_remote_node *rn;
|
struct usteer_node *node, *last_remote_neighbor = NULL;
|
||||||
struct usteer_node *node;
|
int i = 0;
|
||||||
void *c;
|
void *c;
|
||||||
|
|
||||||
c = blobmsg_open_array(&b, "list");
|
c = blobmsg_open_array(&b, "list");
|
||||||
for_each_local_node(node)
|
for_each_local_node(node) {
|
||||||
usteer_add_rrm_data(ln, node);
|
if (i >= config.max_neighbor_reports)
|
||||||
for_each_remote_node(rn)
|
break;
|
||||||
usteer_add_rrm_data(ln, &rn->node);
|
if (usteer_add_rrm_data(ln, node))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < config.max_neighbor_reports) {
|
||||||
|
node = usteer_node_get_next_neighbor(&ln->node, last_remote_neighbor);
|
||||||
|
if (!node) {
|
||||||
|
/* No more nodes available */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_remote_neighbor = node;
|
||||||
|
if (usteer_add_rrm_data(ln, node))
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
blobmsg_close_array(&b, c);
|
blobmsg_close_array(&b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
main.c
1
main.c
@@ -88,6 +88,7 @@ void usteer_init_defaults(void)
|
|||||||
config.local_sta_timeout = 120 * 1000;
|
config.local_sta_timeout = 120 * 1000;
|
||||||
config.local_sta_update = 1 * 1000;
|
config.local_sta_update = 1 * 1000;
|
||||||
config.max_retry_band = 5;
|
config.max_retry_band = 5;
|
||||||
|
config.max_neighbor_reports = 8;
|
||||||
config.seen_policy_timeout = 30 * 1000;
|
config.seen_policy_timeout = 30 * 1000;
|
||||||
config.band_steering_threshold = 5;
|
config.band_steering_threshold = 5;
|
||||||
config.load_balancing_threshold = 5;
|
config.load_balancing_threshold = 5;
|
||||||
|
104
node.c
104
node.c
@@ -17,6 +17,7 @@
|
|||||||
* Copyright (C) 2020 John Crispin <john@phrozen.org>
|
* Copyright (C) 2020 John Crispin <john@phrozen.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "node.h"
|
||||||
#include "usteer.h"
|
#include "usteer.h"
|
||||||
|
|
||||||
void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val)
|
void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val)
|
||||||
@@ -36,3 +37,106 @@ void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val)
|
|||||||
*dest = realloc(*dest, new_len);
|
*dest = realloc(*dest, new_len);
|
||||||
memcpy(*dest, val, new_len);
|
memcpy(*dest, val, new_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct usteer_node *
|
||||||
|
usteer_node_higher_bssid(struct usteer_node *node1, struct usteer_node *node2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
if (node1->bssid[i] == node2->bssid[i])
|
||||||
|
continue;
|
||||||
|
if (node1->bssid[i] < node2->bssid[i])
|
||||||
|
return node2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usteer_node *
|
||||||
|
usteer_node_more_roam_interactions(struct usteer_node *node, struct usteer_node *ref)
|
||||||
|
{
|
||||||
|
int roam_actions_node, roam_actions_ref;
|
||||||
|
|
||||||
|
roam_actions_node = node->roam_source + node->roam_destination;
|
||||||
|
roam_actions_ref = ref->roam_source + ref->roam_destination;
|
||||||
|
if (roam_actions_node < roam_actions_ref)
|
||||||
|
return ref;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usteer_node *
|
||||||
|
usteer_node_better_neighbor(struct usteer_node *node, struct usteer_node *ref)
|
||||||
|
{
|
||||||
|
struct usteer_node *n1, *n2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Return one node if the other one is NULL
|
||||||
|
* 2. Return the node with the higher roam events.
|
||||||
|
* 3. Return the node with the higher BSSID.
|
||||||
|
* 4. Return first method argument.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
return node;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return ref;
|
||||||
|
|
||||||
|
n1 = usteer_node_more_roam_interactions(node, ref);
|
||||||
|
n2 = usteer_node_more_roam_interactions(ref, node);
|
||||||
|
if (n1 == n2)
|
||||||
|
return n1;
|
||||||
|
|
||||||
|
/* Identical roam interactions. Check BSSID */
|
||||||
|
n1 = usteer_node_higher_bssid(node, ref);
|
||||||
|
n2 = usteer_node_higher_bssid(ref, node);
|
||||||
|
if (n1 == n2)
|
||||||
|
return n1;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usteer_node *
|
||||||
|
usteer_node_get_next_neighbor(struct usteer_node *current_node, struct usteer_node *last)
|
||||||
|
{
|
||||||
|
struct usteer_remote_node *rn;
|
||||||
|
struct usteer_node *next = NULL, *n1, *n2;
|
||||||
|
|
||||||
|
for_each_remote_node(rn) {
|
||||||
|
if (next == &rn->node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(current_node->ssid, rn->node.ssid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Check if this node is ranked lower than the last one */
|
||||||
|
n1 = usteer_node_better_neighbor(last, &rn->node);
|
||||||
|
n2 = usteer_node_better_neighbor(&rn->node, last);
|
||||||
|
if (n1 != n2) {
|
||||||
|
/* Identical rank. Skip. */
|
||||||
|
continue;
|
||||||
|
} else if (last && n1 == &rn->node) {
|
||||||
|
/* Candidate rank is higher than the last neighbor. Skip. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check with current next candidate */
|
||||||
|
n1 = usteer_node_better_neighbor(next, &rn->node);
|
||||||
|
n2 = usteer_node_better_neighbor(&rn->node, next);
|
||||||
|
if (n1 != n2) {
|
||||||
|
/* Identical rank. Skip. */
|
||||||
|
continue;
|
||||||
|
} else if (n1 != &rn->node) {
|
||||||
|
/* Next candidate ranked higher. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = n1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
@@ -17,6 +17,9 @@ config usteer
|
|||||||
# 5 = all debug messages
|
# 5 = all debug messages
|
||||||
option 'debug_level' '2'
|
option 'debug_level' '2'
|
||||||
|
|
||||||
|
# Maximum number of neighbor reports set for a node
|
||||||
|
#option max_neighbor_reports 8
|
||||||
|
|
||||||
# Maximum amount of time (ms) a station may be blocked due to policy decisions
|
# Maximum amount of time (ms) a station may be blocked due to policy decisions
|
||||||
#option sta_block_timeout 30000
|
#option sta_block_timeout 30000
|
||||||
|
|
||||||
|
@@ -75,7 +75,7 @@ uci_usteer() {
|
|||||||
for opt in \
|
for opt in \
|
||||||
debug_level \
|
debug_level \
|
||||||
sta_block_timeout local_sta_timeout local_sta_update \
|
sta_block_timeout local_sta_timeout local_sta_update \
|
||||||
max_retry_band seen_policy_timeout \
|
max_neighbor_reports max_retry_band seen_policy_timeout \
|
||||||
load_balancing_threshold band_steering_threshold \
|
load_balancing_threshold band_steering_threshold \
|
||||||
remote_update_interval \
|
remote_update_interval \
|
||||||
min_connect_snr min_snr signal_diff_threshold \
|
min_connect_snr min_snr signal_diff_threshold \
|
||||||
|
1
ubus.c
1
ubus.c
@@ -146,6 +146,7 @@ struct cfg_item {
|
|||||||
_cfg(U32, sta_block_timeout), \
|
_cfg(U32, sta_block_timeout), \
|
||||||
_cfg(U32, local_sta_timeout), \
|
_cfg(U32, local_sta_timeout), \
|
||||||
_cfg(U32, local_sta_update), \
|
_cfg(U32, local_sta_update), \
|
||||||
|
_cfg(U32, max_neighbor_reports), \
|
||||||
_cfg(U32, max_retry_band), \
|
_cfg(U32, max_retry_band), \
|
||||||
_cfg(U32, seen_policy_timeout), \
|
_cfg(U32, seen_policy_timeout), \
|
||||||
_cfg(U32, load_balancing_threshold), \
|
_cfg(U32, load_balancing_threshold), \
|
||||||
|
3
usteer.h
3
usteer.h
@@ -152,6 +152,8 @@ struct usteer_config {
|
|||||||
|
|
||||||
bool assoc_steering;
|
bool assoc_steering;
|
||||||
|
|
||||||
|
uint32_t max_neighbor_reports;
|
||||||
|
|
||||||
uint32_t band_steering_threshold;
|
uint32_t band_steering_threshold;
|
||||||
uint32_t load_balancing_threshold;
|
uint32_t load_balancing_threshold;
|
||||||
|
|
||||||
@@ -274,6 +276,7 @@ static inline const char *usteer_node_name(struct usteer_node *node)
|
|||||||
}
|
}
|
||||||
void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val);
|
void usteer_node_set_blob(struct blob_attr **dest, struct blob_attr *val);
|
||||||
|
|
||||||
|
struct usteer_node *usteer_node_get_next_neighbor(struct usteer_node *current_node, struct usteer_node *last);
|
||||||
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);
|
||||||
|
|
||||||
void config_set_interfaces(struct blob_attr *data);
|
void config_set_interfaces(struct blob_attr *data);
|
||||||
|
Reference in New Issue
Block a user