From 8be33b596b36971abd5cbbb9d56712d579887eac Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 6 Jul 2021 19:14:36 +0200 Subject: [PATCH] remote: track remote hosts as a separate data structure Will be used to track host info Signed-off-by: Felix Fietkau --- local_node.c | 2 +- node.h | 17 ++++++++++--- remote.c | 69 ++++++++++++++++++++++++++++++++++++++-------------- ubus.c | 4 +-- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/local_node.c b/local_node.c index 1e52d8f..97cb716 100644 --- a/local_node.c +++ b/local_node.c @@ -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 a4c58d8..7e708b7 100644 --- 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 diff --git a/remote.c b/remote.c index 447ac11..64375be 100644 --- 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 ea99fc9..f38ce53 100644 --- 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);