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>
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})
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);
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);
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;
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;
--- /dev/null
+/*
+ * 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;
+}
# 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
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 \
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))
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);
MAC_ADDR_DATA(sta->addr));
avl_delete(&stations, &sta->avl);
+ usteer_measurement_report_sta_cleanup(sta);
free(sta);
}
sta->avl.key = sta->addr;
avl_insert(&stations, &sta->avl);
INIT_LIST_HEAD(&sta->nodes);
+ INIT_LIST_HEAD(&sta->measurements);
return sta;
}
_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), \
struct usteer_node {
struct avl_node avl;
struct list_head sta_info;
+ struct list_head measurements;
enum usteer_node_type type;
uint32_t max_retry_band;
uint32_t seen_policy_timeout;
+ uint32_t measurement_report_timeout;
bool assoc_steering;
struct sta {
struct avl_node avl;
struct list_head nodes;
+ struct list_head measurements;
uint8_t seen_2ghz : 1;
uint8_t seen_5ghz : 1;
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;
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