node: keep track of roam-sources and roam-destinations
Keep track of STA journeys between multiple nodes. When a new STA is reported from a foreign node, check whether this STA was previously associated with a local node. Vice versa, check upon association whether or not the STA was previously associated with a foreign node. Keep track of these roaming transactions using two new (local) fields of the node struct. Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
21
local_node.c
21
local_node.c
@@ -150,10 +150,29 @@ usteer_local_node_assoc_update(struct sta_info *si, struct blob_attr *data)
|
|||||||
[MSG_ASSOC] = { "assoc", BLOBMSG_TYPE_BOOL },
|
[MSG_ASSOC] = { "assoc", BLOBMSG_TYPE_BOOL },
|
||||||
};
|
};
|
||||||
struct blob_attr *tb[__MSG_MAX];
|
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));
|
blobmsg_parse(policy, __MSG_MAX, tb, blobmsg_data(data), blobmsg_data_len(data));
|
||||||
if (tb[MSG_ASSOC] && blobmsg_get_u8(tb[MSG_ASSOC]))
|
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) {
|
||||||
|
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) {
|
||||||
|
rn->node.roam_source++;
|
||||||
|
/* Don't abort looking for roam sources here.
|
||||||
|
* The client might have roamed via another node
|
||||||
|
* within the roam-timeout.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
si->connected = STA_CONNECTED;
|
si->connected = STA_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (si->node->freq < 4000)
|
if (si->node->freq < 4000)
|
||||||
si->sta->seen_2ghz = 1;
|
si->sta->seen_2ghz = 1;
|
||||||
|
1
main.c
1
main.c
@@ -96,6 +96,7 @@ void usteer_init_defaults(void)
|
|||||||
config.remote_node_timeout = 10;
|
config.remote_node_timeout = 10;
|
||||||
|
|
||||||
config.roam_kick_delay = 100;
|
config.roam_kick_delay = 100;
|
||||||
|
config.roam_process_timeout = 5 * 1000;
|
||||||
config.roam_scan_tries = 3;
|
config.roam_scan_tries = 3;
|
||||||
config.roam_scan_interval = 10 * 1000;
|
config.roam_scan_interval = 10 * 1000;
|
||||||
config.roam_trigger_interval = 60 * 1000;
|
config.roam_trigger_interval = 60 * 1000;
|
||||||
|
@@ -50,6 +50,10 @@ config usteer
|
|||||||
# Minimum signal-to-noise ratio or signal level (dBm) to remain connected
|
# Minimum signal-to-noise ratio or signal level (dBm) to remain connected
|
||||||
#option min_snr 0
|
#option min_snr 0
|
||||||
|
|
||||||
|
# Timeout (in ms) after which a association following a disassociation is not seen
|
||||||
|
# as a roam
|
||||||
|
#option roam_process_timeout 5000
|
||||||
|
|
||||||
# Minimum signal-to-noise ratio or signal level (dBm) before attempting to trigger
|
# Minimum signal-to-noise ratio or signal level (dBm) before attempting to trigger
|
||||||
# client scans for roaming
|
# client scans for roaming
|
||||||
#option roam_scan_snr 0
|
#option roam_scan_snr 0
|
||||||
|
@@ -79,7 +79,7 @@ uci_usteer() {
|
|||||||
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 \
|
||||||
initial_connect_delay \
|
initial_connect_delay roam_process_timeout\
|
||||||
roam_kick_delay roam_scan_tries \
|
roam_kick_delay roam_scan_tries \
|
||||||
roam_scan_snr roam_scan_interval \
|
roam_scan_snr roam_scan_interval \
|
||||||
roam_trigger_snr roam_trigger_interval \
|
roam_trigger_snr roam_trigger_interval \
|
||||||
|
20
remote.c
20
remote.c
@@ -155,9 +155,11 @@ static void
|
|||||||
interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
|
interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
|
||||||
{
|
{
|
||||||
struct sta *sta;
|
struct sta *sta;
|
||||||
struct sta_info *si;
|
struct sta_info *si, *local_si;
|
||||||
struct apmsg_sta msg;
|
struct apmsg_sta msg;
|
||||||
|
struct usteer_node *local_node;
|
||||||
bool create;
|
bool create;
|
||||||
|
bool connect_change;
|
||||||
|
|
||||||
if (!parse_apmsg_sta(&msg, data)) {
|
if (!parse_apmsg_sta(&msg, data)) {
|
||||||
MSG(DEBUG, "Cannot parse station in message\n");
|
MSG(DEBUG, "Cannot parse station in message\n");
|
||||||
@@ -177,10 +179,26 @@ interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
|
|||||||
if (!si)
|
if (!si)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
connect_change = si->connected != msg.connected;
|
||||||
si->connected = msg.connected;
|
si->connected = msg.connected;
|
||||||
si->signal = msg.signal;
|
si->signal = msg.signal;
|
||||||
si->seen = current_time - msg.seen;
|
si->seen = current_time - msg.seen;
|
||||||
si->last_connected = current_time - msg.last_connected;
|
si->last_connected = current_time - msg.last_connected;
|
||||||
|
|
||||||
|
/* Check if client roamed to this foreign node */
|
||||||
|
if ((connect_change || create) && si->connected == STA_CONNECTED) {
|
||||||
|
for_each_local_node(local_node) {
|
||||||
|
local_si = usteer_sta_info_get(sta, local_node, NULL);
|
||||||
|
if (!local_si)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (current_time - local_si->last_connected < config.roam_process_timeout) {
|
||||||
|
node->node.roam_destination++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
usteer_sta_info_update_timeout(si, msg.timeout);
|
usteer_sta_info_update_timeout(si, msg.timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
ubus.c
3
ubus.c
@@ -154,6 +154,7 @@ struct cfg_item {
|
|||||||
_cfg(BOOL, assoc_steering), \
|
_cfg(BOOL, assoc_steering), \
|
||||||
_cfg(I32, min_connect_snr), \
|
_cfg(I32, min_connect_snr), \
|
||||||
_cfg(I32, min_snr), \
|
_cfg(I32, min_snr), \
|
||||||
|
_cfg(U32, roam_process_timeout), \
|
||||||
_cfg(I32, roam_scan_snr), \
|
_cfg(I32, roam_scan_snr), \
|
||||||
_cfg(U32, roam_scan_tries), \
|
_cfg(U32, roam_scan_tries), \
|
||||||
_cfg(U32, roam_scan_interval), \
|
_cfg(U32, roam_scan_interval), \
|
||||||
@@ -281,6 +282,8 @@ void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node)
|
|||||||
blobmsg_add_u32(buf, "noise", node->noise);
|
blobmsg_add_u32(buf, "noise", node->noise);
|
||||||
blobmsg_add_u32(buf, "load", node->load);
|
blobmsg_add_u32(buf, "load", node->load);
|
||||||
blobmsg_add_u32(buf, "max_assoc", node->max_assoc);
|
blobmsg_add_u32(buf, "max_assoc", node->max_assoc);
|
||||||
|
blobmsg_add_u32(buf, "roam_source", node->roam_source);
|
||||||
|
blobmsg_add_u32(buf, "roam_destination", node->roam_destination);
|
||||||
if (node->rrm_nr)
|
if (node->rrm_nr)
|
||||||
blobmsg_add_field(buf, BLOBMSG_TYPE_ARRAY, "rrm_nr",
|
blobmsg_add_field(buf, BLOBMSG_TYPE_ARRAY, "rrm_nr",
|
||||||
blobmsg_data(node->rrm_nr),
|
blobmsg_data(node->rrm_nr),
|
||||||
|
5
usteer.h
5
usteer.h
@@ -87,6 +87,9 @@ struct usteer_node {
|
|||||||
int n_assoc;
|
int n_assoc;
|
||||||
int max_assoc;
|
int max_assoc;
|
||||||
int load;
|
int load;
|
||||||
|
|
||||||
|
int roam_source;
|
||||||
|
int roam_destination;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usteer_scan_request {
|
struct usteer_scan_request {
|
||||||
@@ -160,6 +163,8 @@ struct usteer_config {
|
|||||||
uint32_t signal_diff_threshold;
|
uint32_t signal_diff_threshold;
|
||||||
|
|
||||||
int32_t roam_scan_snr;
|
int32_t roam_scan_snr;
|
||||||
|
uint32_t roam_process_timeout;
|
||||||
|
|
||||||
uint32_t roam_scan_tries;
|
uint32_t roam_scan_tries;
|
||||||
uint32_t roam_scan_interval;
|
uint32_t roam_scan_interval;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user