remote: track remote hosts as a separate data structure
authorFelix Fietkau <nbd@nbd.name>
Tue, 6 Jul 2021 17:14:36 +0000 (19:14 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 6 Jul 2021 17:14:40 +0000 (19:14 +0200)
Will be used to track host info

Signed-off-by: Felix Fietkau <nbd@nbd.name>
local_node.c
node.h
remote.c
ubus.c

index 1e52d8f7bf7f6c070d50328fb3bd488ab30182e5..97cb716e8c4aafc51c89a87b05a705d32da78082 100644 (file)
@@ -291,7 +291,7 @@ usteer_local_node_prepare_rrm_set(struct usteer_local_node *ln)
        c = blobmsg_open_array(&b, "list");
        for_each_local_node(node)
                usteer_add_rrm_data(ln, node);
-       avl_for_each_element(&remote_nodes, rn, avl)
+       for_each_remote_node(rn)
                usteer_add_rrm_data(ln, &rn->node);
        blobmsg_close_array(&b, c);
 }
diff --git a/node.h b/node.h
index a4c58d8f9e050baccff64071425ba4ef271e20d7..7e708b7c99c055572854ee05a9e60c49df1e8d4e 100644 (file)
--- a/node.h
+++ b/node.h
@@ -65,22 +65,33 @@ struct usteer_local_node {
 };
 
 struct interface;
-struct usteer_remote_node {
+
+struct usteer_remote_host {
        struct avl_node avl;
+
+       struct list_head nodes;
+       char *addr;
+};
+
+struct usteer_remote_node {
+       struct list_head list;
+       struct list_head host_list;
        const char *name;
 
+       struct usteer_remote_host *host;
        struct usteer_node node;
-       struct interface *iface;
 
        int check;
 };
 
 extern struct avl_tree local_nodes;
-extern struct avl_tree remote_nodes;
+extern struct list_head remote_nodes;
 
 #define for_each_local_node(node)                      \
        avl_for_each_element(&local_nodes, node, avl)   \
                if (!node->disabled)
 
+#define for_each_remote_node(rn)                       \
+       list_for_each_entry(rn, &remote_nodes, list)
 
 #endif
index 447ac11bb914fff7f442f1a0a683cb0120db4f04..64375be84fe5fade083f8252dc7f6643c249aef3 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -50,7 +50,7 @@ interfaces_update_cb(struct vlist_tree *tree,
                     struct vlist_node *node_new,
                     struct vlist_node *node_old);
 
-static int remote_node_cmp(const void *k1, const void *k2, void *ptr)
+static int remote_host_cmp(const void *k1, const void *k2, void *ptr)
 {
        unsigned long v1 = (unsigned long) k1;
        unsigned long v2 = (unsigned long) k2;
@@ -59,7 +59,8 @@ static int remote_node_cmp(const void *k1, const void *k2, void *ptr)
 }
 
 static VLIST_TREE(interfaces, avl_strcmp, interfaces_update_cb, true, true);
-AVL_TREE(remote_nodes, remote_node_cmp, true, NULL);
+LIST_HEAD(remote_nodes);
+static AVL_TREE(remote_hosts, remote_host_cmp, false, NULL);
 
 static const char *
 interface_name(struct interface *iface)
@@ -183,42 +184,72 @@ interface_add_station(struct usteer_remote_node *node, struct blob_attr *data)
 static void
 remote_node_free(struct usteer_remote_node *node)
 {
-       avl_delete(&remote_nodes, &node->avl);
+       struct usteer_remote_host *host = node->host;
+
+       list_del(&node->list);
+       list_del(&node->host_list);
        usteer_sta_node_cleanup(&node->node);
        free(node);
+
+       if (!list_empty(&host->nodes))
+               return;
+
+       avl_delete(&remote_hosts, &host->avl);
+       free(host);
+}
+
+static struct usteer_remote_host *
+interface_get_host(const char *addr, unsigned long id)
+{
+       struct usteer_remote_host *host;
+
+       host = avl_find_element(&remote_hosts, (void *)id, host, avl);
+       if (host)
+               goto out;
+
+       host = calloc(1, sizeof(*host));
+       host->avl.key = (void *)id;
+       INIT_LIST_HEAD(&host->nodes);
+       avl_insert(&remote_hosts, &host->avl);
+
+out:
+       if (host->addr && strcmp(host->addr, addr) != 0)
+               return host;
+
+       free(host->addr);
+       host->addr = strdup(addr);
+
+       return host;
 }
 
 static struct usteer_remote_node *
-interface_get_node(const char *addr, unsigned long id, const char *name)
+interface_get_node(struct usteer_remote_host *host, const char *name)
 {
        struct usteer_remote_node *node;
-       int addr_len = strlen(addr);
+       int addr_len = strlen(host->addr);
        char *buf;
 
-       node = avl_find_element(&remote_nodes, (void *) id, node, avl);
-       while (node && node->avl.key == (void *) id) {
+       list_for_each_entry(node, &host->nodes, host_list)
                if (!strcmp(node->name, name))
                        return node;
 
-               node = avl_next_element(node, avl);
-       }
-
        node = calloc_a(sizeof(*node), &buf, addr_len + 1 + strlen(name) + 1);
-       node->avl.key = (void *) id;
        node->node.type = NODE_TYPE_REMOTE;
 
-       sprintf(buf, "%s#%s", addr, name);
+       sprintf(buf, "%s#%s", host->addr, name);
        node->node.avl.key = buf;
        node->name = buf + addr_len + 1;
+       node->host = host;
        INIT_LIST_HEAD(&node->node.sta_info);
 
-       avl_insert(&remote_nodes, &node->avl);
+       list_add_tail(&node->list, &remote_nodes);
+       list_add_tail(&node->host_list, &host->nodes);
 
        return node;
 }
 
 static void
-interface_add_node(struct interface *iface, const char *addr, unsigned long id, struct blob_attr *data)
+interface_add_node(struct usteer_remote_host *host, struct blob_attr *data)
 {
        struct usteer_remote_node *node;
        struct apmsg_node msg;
@@ -230,14 +261,13 @@ interface_add_node(struct interface *iface, const char *addr, unsigned long id,
                return;
        }
 
-       node = interface_get_node(addr, id, msg.name);
+       node = interface_get_node(host, msg.name);
        node->check = 0;
        node->node.freq = msg.freq;
        node->node.n_assoc = msg.n_assoc;
        node->node.max_assoc = msg.max_assoc;
        node->node.noise = msg.noise;
        node->node.load = msg.load;
-       node->iface = iface;
        snprintf(node->node.ssid, sizeof(node->node.ssid), "%s", msg.ssid);
        usteer_node_set_blob(&node->node.rrm_nr, msg.rrm_nr);
        usteer_node_set_blob(&node->node.node_info, msg.node_info);
@@ -249,6 +279,7 @@ interface_add_node(struct interface *iface, const char *addr, unsigned long id,
 static void
 interface_recv_msg(struct interface *iface, struct in_addr *addr, void *buf, int len)
 {
+       struct usteer_remote_host *host;
        char addr_str[INET_ADDRSTRLEN];
        struct blob_attr *data = buf;
        struct apmsg msg;
@@ -273,8 +304,10 @@ interface_recv_msg(struct interface *iface, struct in_addr *addr, void *buf, int
 
        inet_ntop(AF_INET, addr, addr_str, sizeof(addr_str));
 
+       host = interface_get_host(addr_str, msg.id);
+
        blob_for_each_attr(cur, msg.nodes, rem)
-               interface_add_node(iface, addr_str, msg.id, cur);
+               interface_add_node(host, cur);
 }
 
 static struct interface *
@@ -447,7 +480,7 @@ usteer_check_timeout(void)
        struct usteer_remote_node *node, *tmp;
        int timeout = config.remote_node_timeout / config.remote_update_interval;
 
-       avl_for_each_element_safe(&remote_nodes, node, avl, tmp) {
+       list_for_each_entry_safe(node, tmp, &remote_nodes, list) {
                if (node->check++ > timeout)
                        remote_node_free(node);
        }
diff --git a/ubus.c b/ubus.c
index ea99fc9f3cbe9b3194a5abeefce4123aee00842b..f38ce5368dfa0a39df3a6fef1f26200eabdbcef3 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -315,7 +315,7 @@ usteer_ubus_remote_info(struct ubus_context *ctx, struct ubus_object *obj,
 
        blob_buf_init(&b, 0);
 
-       avl_for_each_element(&remote_nodes, rn, avl)
+       for_each_remote_node(rn)
                usteer_dump_node(&rn->node);
 
        ubus_send_reply(ctx, req, b.head);
@@ -458,7 +458,7 @@ int usteer_ubus_notify_client_disassoc(struct sta_info *si)
        c = blobmsg_open_array(&b, "neighbors");
        for_each_local_node(node)
                usteer_add_nr_entry(si->node, node);
-       avl_for_each_element(&remote_nodes, rn, avl)
+       for_each_remote_node(rn)
                usteer_add_nr_entry(si->node, &rn->node);
        blobmsg_close_array(&b, c);
        return ubus_invoke(ubus_ctx, ln->obj_id, "wnm_disassoc_imminent", b.head, NULL, 0, 100);