measurement: add handling of measurements
Add logic for saving measurement-reports from STAs. This commit does not yet save the measurement-reports received from clients but adds the necessary code to do so. Currently the codes can only handle beacon-reports, but link measurements can be added to it in the future. It also adds the new config-key measurement_report_timeout which controls how long measurements are saved upon they are received by a STA. Signed-off-by: David Bauer <mail@david-bauer.net>
This commit is contained in:
@@ -24,7 +24,7 @@ IF(NOT HAVE_PCAP_H)
|
|||||||
MESSAGE(FATAL_ERROR "pcap/pcap.h is not found")
|
MESSAGE(FATAL_ERROR "pcap/pcap.h is not found")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
SET(SOURCES main.c local_node.c node.c sta.c policy.c ubus.c remote.c parse.c netifd.c timeout.c event.c)
|
SET(SOURCES main.c local_node.c node.c sta.c policy.c ubus.c remote.c parse.c netifd.c timeout.c event.c measurement.c)
|
||||||
|
|
||||||
IF(NL_CFLAGS)
|
IF(NL_CFLAGS)
|
||||||
ADD_DEFINITIONS(${NL_CFLAGS})
|
ADD_DEFINITIONS(${NL_CFLAGS})
|
||||||
|
@@ -71,6 +71,7 @@ usteer_free_node(struct ubus_context *ctx, struct usteer_local_node *ln)
|
|||||||
usteer_local_node_pending_bss_tm_free(ln);
|
usteer_local_node_pending_bss_tm_free(ln);
|
||||||
usteer_local_node_state_reset(ln);
|
usteer_local_node_state_reset(ln);
|
||||||
usteer_sta_node_cleanup(&ln->node);
|
usteer_sta_node_cleanup(&ln->node);
|
||||||
|
usteer_measurement_report_node_cleanup(&ln->node);
|
||||||
uloop_timeout_cancel(&ln->update);
|
uloop_timeout_cancel(&ln->update);
|
||||||
uloop_timeout_cancel(&ln->bss_tm_queries_timeout);
|
uloop_timeout_cancel(&ln->bss_tm_queries_timeout);
|
||||||
avl_delete(&local_nodes, &ln->node.avl);
|
avl_delete(&local_nodes, &ln->node.avl);
|
||||||
@@ -578,6 +579,7 @@ usteer_get_node(struct ubus_context *ctx, const char *name)
|
|||||||
avl_insert(&local_nodes, &node->avl);
|
avl_insert(&local_nodes, &node->avl);
|
||||||
kvlist_init(&ln->node_info, kvlist_blob_len);
|
kvlist_init(&ln->node_info, kvlist_blob_len);
|
||||||
INIT_LIST_HEAD(&node->sta_info);
|
INIT_LIST_HEAD(&node->sta_info);
|
||||||
|
INIT_LIST_HEAD(&node->measurements);
|
||||||
|
|
||||||
ln->bss_tm_queries_timeout.cb = usteer_local_node_process_bss_tm_queries;
|
ln->bss_tm_queries_timeout.cb = usteer_local_node_process_bss_tm_queries;
|
||||||
INIT_LIST_HEAD(&ln->bss_tm_queries);
|
INIT_LIST_HEAD(&ln->bss_tm_queries);
|
||||||
@@ -623,6 +625,7 @@ usteer_check_node_enabled(struct usteer_local_node *ln)
|
|||||||
MSG(INFO, "Disconnecting from local node %s\n", usteer_node_name(&ln->node));
|
MSG(INFO, "Disconnecting from local node %s\n", usteer_node_name(&ln->node));
|
||||||
usteer_local_node_state_reset(ln);
|
usteer_local_node_state_reset(ln);
|
||||||
usteer_sta_node_cleanup(&ln->node);
|
usteer_sta_node_cleanup(&ln->node);
|
||||||
|
usteer_measurement_report_node_cleanup(&ln->node);
|
||||||
uloop_timeout_cancel(&ln->update);
|
uloop_timeout_cancel(&ln->update);
|
||||||
ubus_unsubscribe(ubus_ctx, &ln->ev, ln->obj_id);
|
ubus_unsubscribe(ubus_ctx, &ln->ev, ln->obj_id);
|
||||||
return;
|
return;
|
||||||
|
1
main.c
1
main.c
@@ -86,6 +86,7 @@ void usteer_init_defaults(void)
|
|||||||
|
|
||||||
config.sta_block_timeout = 30 * 1000;
|
config.sta_block_timeout = 30 * 1000;
|
||||||
config.local_sta_timeout = 120 * 1000;
|
config.local_sta_timeout = 120 * 1000;
|
||||||
|
config.measurement_report_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.max_neighbor_reports = 8;
|
||||||
|
112
measurement.c
Normal file
112
measurement.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* 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) 2021 David Bauer <mail@david-bauer.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "usteer.h"
|
||||||
|
|
||||||
|
LIST_HEAD(measurements);
|
||||||
|
static struct usteer_timeout_queue tq;
|
||||||
|
|
||||||
|
void
|
||||||
|
usteer_measurement_report_node_cleanup(struct usteer_node *node)
|
||||||
|
{
|
||||||
|
struct usteer_measurement_report *mr, *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(mr, tmp, &node->measurements, node_list)
|
||||||
|
usteer_measurement_report_del(mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usteer_measurement_report_sta_cleanup(struct sta *sta)
|
||||||
|
{
|
||||||
|
struct usteer_measurement_report *mr, *tmp;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(mr, tmp, &sta->measurements, sta_list)
|
||||||
|
usteer_measurement_report_del(mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usteer_measurement_report *
|
||||||
|
usteer_measurement_report_get(struct sta *sta, struct usteer_node *node, bool create)
|
||||||
|
{
|
||||||
|
struct usteer_measurement_report *mr;
|
||||||
|
|
||||||
|
list_for_each_entry(mr, &sta->measurements, sta_list) {
|
||||||
|
if (mr->node == node)
|
||||||
|
return mr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!create)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mr = calloc(1, sizeof(*mr));
|
||||||
|
if (!mr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Set node & add to nodes list */
|
||||||
|
mr->node = node;
|
||||||
|
list_add(&mr->node_list, &node->measurements);
|
||||||
|
|
||||||
|
/* Set sta & add to STAs list */
|
||||||
|
mr->sta = sta;
|
||||||
|
list_add(&mr->sta_list, &sta->measurements);
|
||||||
|
|
||||||
|
/* Add to Measurement list */
|
||||||
|
list_add(&mr->list, &measurements);
|
||||||
|
|
||||||
|
/* Set measurement expiration */
|
||||||
|
usteer_timeout_set(&tq, &mr->timeout, config.measurement_report_timeout);
|
||||||
|
|
||||||
|
return mr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct usteer_measurement_report *
|
||||||
|
usteer_measurement_report_add_beacon_report(struct sta *sta, struct usteer_node *node,
|
||||||
|
struct usteer_beacon_report *br, uint64_t timestamp)
|
||||||
|
{
|
||||||
|
struct usteer_measurement_report *mr = usteer_measurement_report_get(sta, node, true);
|
||||||
|
|
||||||
|
if (!mr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mr->timestamp = timestamp;
|
||||||
|
memcpy(&mr->beacon_report, br, sizeof(*br));
|
||||||
|
|
||||||
|
return mr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usteer_measurement_report_del(struct usteer_measurement_report *mr)
|
||||||
|
{
|
||||||
|
usteer_timeout_cancel(&tq, &mr->timeout);
|
||||||
|
list_del(&mr->node_list);
|
||||||
|
list_del(&mr->sta_list);
|
||||||
|
list_del(&mr->list);
|
||||||
|
free(mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usteer_measurement_timeout(struct usteer_timeout_queue *q, struct usteer_timeout *t)
|
||||||
|
{
|
||||||
|
struct usteer_measurement_report *mr = container_of(t, struct usteer_measurement_report, timeout);
|
||||||
|
|
||||||
|
usteer_measurement_report_del(mr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __usteer_init usteer_measurement_init(void)
|
||||||
|
{
|
||||||
|
usteer_timeout_init(&tq);
|
||||||
|
tq.cb = usteer_measurement_timeout;
|
||||||
|
}
|
@@ -26,6 +26,9 @@ config usteer
|
|||||||
# Maximum amount of time (ms) a local unconnected station is tracked
|
# Maximum amount of time (ms) a local unconnected station is tracked
|
||||||
#option local_sta_timeout 120000
|
#option local_sta_timeout 120000
|
||||||
|
|
||||||
|
# Maximum amount of time (ms) a measurement report is stored
|
||||||
|
#option measurement_report_timeout 120000
|
||||||
|
|
||||||
# Local station information update interval (ms)
|
# Local station information update interval (ms)
|
||||||
#option local_sta_update 1000
|
#option local_sta_update 1000
|
||||||
|
|
||||||
|
@@ -76,6 +76,7 @@ uci_usteer() {
|
|||||||
debug_level \
|
debug_level \
|
||||||
sta_block_timeout local_sta_timeout local_sta_update \
|
sta_block_timeout local_sta_timeout local_sta_update \
|
||||||
max_neighbor_reports max_retry_band seen_policy_timeout \
|
max_neighbor_reports max_retry_band seen_policy_timeout \
|
||||||
|
measurement_report_timeout \
|
||||||
load_balancing_threshold band_steering_threshold \
|
load_balancing_threshold band_steering_threshold \
|
||||||
remote_update_interval remote_node_timeout\
|
remote_update_interval remote_node_timeout\
|
||||||
min_connect_snr min_snr min_snr_kick_delay signal_diff_threshold \
|
min_connect_snr min_snr min_snr_kick_delay signal_diff_threshold \
|
||||||
|
2
remote.c
2
remote.c
@@ -210,6 +210,7 @@ remote_node_free(struct usteer_remote_node *node)
|
|||||||
list_del(&node->list);
|
list_del(&node->list);
|
||||||
list_del(&node->host_list);
|
list_del(&node->host_list);
|
||||||
usteer_sta_node_cleanup(&node->node);
|
usteer_sta_node_cleanup(&node->node);
|
||||||
|
usteer_measurement_report_node_cleanup(&node->node);
|
||||||
free(node);
|
free(node);
|
||||||
|
|
||||||
if (!list_empty(&host->nodes))
|
if (!list_empty(&host->nodes))
|
||||||
@@ -264,6 +265,7 @@ interface_get_node(struct usteer_remote_host *host, const char *name)
|
|||||||
node->name = buf + addr_len + 1;
|
node->name = buf + addr_len + 1;
|
||||||
node->host = host;
|
node->host = host;
|
||||||
INIT_LIST_HEAD(&node->node.sta_info);
|
INIT_LIST_HEAD(&node->node.sta_info);
|
||||||
|
INIT_LIST_HEAD(&node->node.measurements);
|
||||||
|
|
||||||
list_add_tail(&node->list, &remote_nodes);
|
list_add_tail(&node->list, &remote_nodes);
|
||||||
list_add_tail(&node->host_list, &host->nodes);
|
list_add_tail(&node->host_list, &host->nodes);
|
||||||
|
2
sta.c
2
sta.c
@@ -35,6 +35,7 @@ usteer_sta_del(struct sta *sta)
|
|||||||
MAC_ADDR_DATA(sta->addr));
|
MAC_ADDR_DATA(sta->addr));
|
||||||
|
|
||||||
avl_delete(&stations, &sta->avl);
|
avl_delete(&stations, &sta->avl);
|
||||||
|
usteer_measurement_report_sta_cleanup(sta);
|
||||||
free(sta);
|
free(sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ usteer_sta_get(const uint8_t *addr, bool create)
|
|||||||
sta->avl.key = sta->addr;
|
sta->avl.key = sta->addr;
|
||||||
avl_insert(&stations, &sta->avl);
|
avl_insert(&stations, &sta->avl);
|
||||||
INIT_LIST_HEAD(&sta->nodes);
|
INIT_LIST_HEAD(&sta->nodes);
|
||||||
|
INIT_LIST_HEAD(&sta->measurements);
|
||||||
|
|
||||||
return sta;
|
return sta;
|
||||||
}
|
}
|
||||||
|
1
ubus.c
1
ubus.c
@@ -149,6 +149,7 @@ struct cfg_item {
|
|||||||
_cfg(U32, max_neighbor_reports), \
|
_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, measurement_report_timeout), \
|
||||||
_cfg(U32, load_balancing_threshold), \
|
_cfg(U32, load_balancing_threshold), \
|
||||||
_cfg(U32, band_steering_threshold), \
|
_cfg(U32, band_steering_threshold), \
|
||||||
_cfg(U32, remote_update_interval), \
|
_cfg(U32, remote_update_interval), \
|
||||||
|
32
usteer.h
32
usteer.h
@@ -73,6 +73,7 @@ struct usteer_remote_host;
|
|||||||
struct usteer_node {
|
struct usteer_node {
|
||||||
struct avl_node avl;
|
struct avl_node avl;
|
||||||
struct list_head sta_info;
|
struct list_head sta_info;
|
||||||
|
struct list_head measurements;
|
||||||
|
|
||||||
enum usteer_node_type type;
|
enum usteer_node_type type;
|
||||||
|
|
||||||
@@ -155,6 +156,7 @@ struct usteer_config {
|
|||||||
|
|
||||||
uint32_t max_retry_band;
|
uint32_t max_retry_band;
|
||||||
uint32_t seen_policy_timeout;
|
uint32_t seen_policy_timeout;
|
||||||
|
uint32_t measurement_report_timeout;
|
||||||
|
|
||||||
bool assoc_steering;
|
bool assoc_steering;
|
||||||
|
|
||||||
@@ -254,6 +256,7 @@ struct sta_info {
|
|||||||
struct sta {
|
struct sta {
|
||||||
struct avl_node avl;
|
struct avl_node avl;
|
||||||
struct list_head nodes;
|
struct list_head nodes;
|
||||||
|
struct list_head measurements;
|
||||||
|
|
||||||
uint8_t seen_2ghz : 1;
|
uint8_t seen_2ghz : 1;
|
||||||
uint8_t seen_5ghz : 1;
|
uint8_t seen_5ghz : 1;
|
||||||
@@ -263,6 +266,27 @@ struct sta {
|
|||||||
uint8_t rrm;
|
uint8_t rrm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct usteer_beacon_report {
|
||||||
|
uint8_t rcpi;
|
||||||
|
uint8_t rsni;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usteer_measurement_report {
|
||||||
|
struct usteer_timeout timeout;
|
||||||
|
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
|
struct usteer_node *node;
|
||||||
|
struct list_head node_list;
|
||||||
|
|
||||||
|
struct sta *sta;
|
||||||
|
struct list_head sta_list;
|
||||||
|
|
||||||
|
uint64_t timestamp;
|
||||||
|
|
||||||
|
struct usteer_beacon_report beacon_report;
|
||||||
|
};
|
||||||
|
|
||||||
extern struct ubus_context *ubus_ctx;
|
extern struct ubus_context *ubus_ctx;
|
||||||
extern struct usteer_config config;
|
extern struct usteer_config config;
|
||||||
extern struct list_head node_handlers;
|
extern struct list_head node_handlers;
|
||||||
@@ -335,4 +359,12 @@ void usteer_run_hook(const char *name, const char *arg);
|
|||||||
void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node);
|
void usteer_dump_node(struct blob_buf *buf, struct usteer_node *node);
|
||||||
void usteer_dump_host(struct blob_buf *buf, struct usteer_remote_host *host);
|
void usteer_dump_host(struct blob_buf *buf, struct usteer_remote_host *host);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct usteer_measurement_report *
|
||||||
|
usteer_measurement_report_add_beacon_report(struct sta *sta, struct usteer_node *node, struct usteer_beacon_report *br, uint64_t timestamp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user