measurement: add handling of measurements
authorDavid Bauer <mail@david-bauer.net>
Fri, 21 Jan 2022 20:27:39 +0000 (21:27 +0100)
committerDavid Bauer <mail@david-bauer.net>
Thu, 3 Feb 2022 21:50:13 +0000 (22:50 +0100)
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>
CMakeLists.txt
local_node.c
main.c
measurement.c [new file with mode: 0644]
openwrt/usteer/files/etc/config/usteer
openwrt/usteer/files/etc/init.d/usteer
remote.c
sta.c
ubus.c
usteer.h

index e22b7ae5cef9c8bf37f38924547a79230a340dfe..6344aab0731a36548f207d802705e715dca8c478 100644 (file)
@@ -24,7 +24,7 @@ IF(NOT HAVE_PCAP_H)
        MESSAGE(FATAL_ERROR "pcap/pcap.h is not found")
 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)
        ADD_DEFINITIONS(${NL_CFLAGS})
index e69ec2157585d471c09bbbbe3822bcced15d1533..25387abc2eebc47283d3df1d937da2cb2c3ed5f4 100644 (file)
@@ -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_state_reset(ln);
        usteer_sta_node_cleanup(&ln->node);
+       usteer_measurement_report_node_cleanup(&ln->node);
        uloop_timeout_cancel(&ln->update);
        uloop_timeout_cancel(&ln->bss_tm_queries_timeout);
        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);
        kvlist_init(&ln->node_info, kvlist_blob_len);
        INIT_LIST_HEAD(&node->sta_info);
+       INIT_LIST_HEAD(&node->measurements);
 
        ln->bss_tm_queries_timeout.cb = usteer_local_node_process_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));
                usteer_local_node_state_reset(ln);
                usteer_sta_node_cleanup(&ln->node);
+               usteer_measurement_report_node_cleanup(&ln->node);
                uloop_timeout_cancel(&ln->update);
                ubus_unsubscribe(ubus_ctx, &ln->ev, ln->obj_id);
                return;
diff --git a/main.c b/main.c
index d8fdbf0421c0cf92695bc56ebf4d074f0dea1f30..37053d36d54185a2d1b510a82169d2ea7c2d2b23 100644 (file)
--- a/main.c
+++ b/main.c
@@ -86,6 +86,7 @@ void usteer_init_defaults(void)
 
        config.sta_block_timeout = 30 * 1000;
        config.local_sta_timeout = 120 * 1000;
+       config.measurement_report_timeout = 120 * 1000;
        config.local_sta_update = 1 * 1000;
        config.max_retry_band = 5;
        config.max_neighbor_reports = 8;
diff --git a/measurement.c b/measurement.c
new file mode 100644 (file)
index 0000000..c1b5ab4
--- /dev/null
@@ -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;
+}
index 92e9443af9c535c21701db9a6940a683e4198e62..fb27fd9475fb67ce7234d04193d93c777eaa53fd 100644 (file)
@@ -26,6 +26,9 @@ config usteer
        # Maximum amount of time (ms) a local unconnected station is tracked
        #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)
        #option local_sta_update 1000
 
index 921cccb9a2eb38be03ddf576162d18e429f2835c..29a43a208c8dc9f5259793f13bf67232d2da00b2 100755 (executable)
@@ -76,6 +76,7 @@ uci_usteer() {
                debug_level \
                sta_block_timeout local_sta_timeout local_sta_update \
                max_neighbor_reports max_retry_band seen_policy_timeout \
+               measurement_report_timeout \
                load_balancing_threshold band_steering_threshold \
                remote_update_interval remote_node_timeout\
                min_connect_snr min_snr min_snr_kick_delay signal_diff_threshold \
index bad5f8b56b89de01f306eb09e3c5794b59eed908..f000e687efd581e6b91a73ba182b86dc1d206bee 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -210,6 +210,7 @@ remote_node_free(struct usteer_remote_node *node)
        list_del(&node->list);
        list_del(&node->host_list);
        usteer_sta_node_cleanup(&node->node);
+       usteer_measurement_report_node_cleanup(&node->node);
        free(node);
 
        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->host = host;
        INIT_LIST_HEAD(&node->node.sta_info);
+       INIT_LIST_HEAD(&node->node.measurements);
 
        list_add_tail(&node->list, &remote_nodes);
        list_add_tail(&node->host_list, &host->nodes);
diff --git a/sta.c b/sta.c
index 2868a67652cdf1dca805d7c4909aca6ce42d0ebc..af4f17e9f474a2e920fa6da61a018f4f9264c74f 100644 (file)
--- a/sta.c
+++ b/sta.c
@@ -35,6 +35,7 @@ usteer_sta_del(struct sta *sta)
            MAC_ADDR_DATA(sta->addr));
 
        avl_delete(&stations, &sta->avl);
+       usteer_measurement_report_sta_cleanup(sta);
        free(sta);
 }
 
@@ -140,6 +141,7 @@ usteer_sta_get(const uint8_t *addr, bool create)
        sta->avl.key = sta->addr;
        avl_insert(&stations, &sta->avl);
        INIT_LIST_HEAD(&sta->nodes);
+       INIT_LIST_HEAD(&sta->measurements);
 
        return sta;
 }
diff --git a/ubus.c b/ubus.c
index 69604645f0d401b40b142fee9fcce91b1ad1409d..bb4e4d2b73fa2b764dc12cd71428724ed6adbd87 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -149,6 +149,7 @@ struct cfg_item {
        _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), \
index 0ad9499c9c0a995e090d2c8e9a575ac96e1c036e..2f74a01c662e716fddb744b48312ad85a147ca56 100644 (file)
--- a/usteer.h
+++ b/usteer.h
@@ -73,6 +73,7 @@ struct usteer_remote_host;
 struct usteer_node {
        struct avl_node avl;
        struct list_head sta_info;
+       struct list_head measurements;
 
        enum usteer_node_type type;
 
@@ -155,6 +156,7 @@ struct usteer_config {
 
        uint32_t max_retry_band;
        uint32_t seen_policy_timeout;
+       uint32_t measurement_report_timeout;
 
        bool assoc_steering;
 
@@ -254,6 +256,7 @@ struct sta_info {
 struct sta {
        struct avl_node avl;
        struct list_head nodes;
+       struct list_head measurements;
 
        uint8_t seen_2ghz : 1;
        uint8_t seen_5ghz : 1;
@@ -263,6 +266,27 @@ struct sta {
        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 usteer_config config;
 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_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