From 05e910cec691f8333383a746876015e99ff088db Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 2 Oct 2011 19:22:08 +0200 Subject: [PATCH] make versioned lists more flexible by using an external comparator --- interface-ip.c | 27 ++++++++++++++++++++++----- interface-ip.h | 7 +++++-- utils.c | 20 +++++++------------- utils.h | 11 ++++------- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/interface-ip.c b/interface-ip.c index 2e2e9d8..0845169 100644 --- a/interface-ip.c +++ b/interface-ip.c @@ -10,6 +10,24 @@ #include "ubus.h" #include "system.h" +static int +addr_cmp(const void *k1, const void *k2, void *ptr) +{ + const struct device_addr *a1 = k1, *a2 = k2; + + return memcmp(&a1->mask, &a2->mask, + sizeof(*a1) - offsetof(struct device_addr, mask)); +} + +static int +route_cmp(const void *k1, const void *k2, void *ptr) +{ + const struct device_route *r1 = k1, *r2 = k2; + + return memcmp(&r1->mask, &r2->mask, + sizeof(*r1) - offsetof(struct device_route, mask)); +} + static void interface_update_proto_addr(struct vlist_tree *tree, struct vlist_node *node_new, @@ -65,9 +83,8 @@ interface_update_proto_route(struct vlist_tree *tree, void interface_ip_init(struct interface *iface) { - vlist_init(&iface->proto_route, interface_update_proto_route, - struct device_route, node, mask, addr); - vlist_init(&iface->proto_addr, interface_update_proto_addr, - struct device_addr, node, mask, addr); + vlist_init(&iface->proto_route, route_cmp, interface_update_proto_route, + struct device_route, node); + vlist_init(&iface->proto_addr, addr_cmp, interface_update_proto_addr, + struct device_addr, node); } - diff --git a/interface-ip.h b/interface-ip.h index ba7b6c8..057f0d0 100644 --- a/interface-ip.h +++ b/interface-ip.h @@ -24,6 +24,7 @@ struct device_addr { enum device_addr_flags flags; + /* must be last */ unsigned int mask; union if_addr addr; }; @@ -34,10 +35,12 @@ struct device_route { enum device_addr_flags flags; bool keep; - unsigned int mask; - union if_addr addr; union if_addr nexthop; struct device *device; + + /* must be last */ + unsigned int mask; + union if_addr addr; }; void interface_ip_init(struct interface *iface); diff --git a/utils.c b/utils.c index 15f0525..42d3176 100644 --- a/utils.c +++ b/utils.c @@ -7,22 +7,15 @@ avl_strcmp(const void *k1, const void *k2, void *ptr) return strcmp(k1, k2); } -static int -vlist_cmp(const void *k1, const void *k2, void *ptr) -{ - struct vlist_tree *vl = ptr; - return memcmp(k1, k2, vl->data_len); -} - void -__vlist_init(struct vlist_tree *tree, vlist_update_cb update, int offset, int len) +__vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, + vlist_update_cb update, int offset) { - tree->data_offset = offset; - tree->data_len = len; + tree->node_offset = offset; tree->update = update; tree->version = 1; - avl_init(&tree->avl, vlist_cmp, 0, tree); + avl_init(&tree->avl, cmp, 0, tree); } void @@ -37,11 +30,12 @@ vlist_add(struct vlist_tree *tree, struct vlist_node *node) { struct vlist_node *old_node = NULL; struct avl_node *anode; + void *key = (char *) node - tree->node_offset; - node->avl.key = (char *) node + tree->data_offset; + node->avl.key = key; node->version = tree->version; - anode = avl_find(&tree->avl, (char *) node + tree->data_offset); + anode = avl_find(&tree->avl, key); if (anode) { old_node = container_of(anode, struct vlist_node, avl); avl_delete(&tree->avl, anode); diff --git a/utils.h b/utils.h index e872dc5..c8101e7 100644 --- a/utils.h +++ b/utils.h @@ -27,9 +27,7 @@ struct vlist_tree { struct avl_tree avl; vlist_update_cb update; - - int data_offset; - int data_len; + int node_offset; int version; }; @@ -39,11 +37,10 @@ struct vlist_node { int version; }; -void __vlist_init(struct vlist_tree *tree, vlist_update_cb update, int offset, int len); +void __vlist_init(struct vlist_tree *tree, avl_tree_comp cmp, vlist_update_cb update, int offset); -#define vlist_init(tree, update, type, vlist, first, last) \ - __vlist_init(tree, update, offsetof(type, first) - offsetof(type, vlist), \ - offsetof(type, last) - offsetof(type, first) + sizeof(((type *) 0)->last)) +#define vlist_init(tree, cmp, update, type, node) \ + __vlist_init(tree, cmp, update, offsetof(type, node)) void vlist_add(struct vlist_tree *tree, struct vlist_node *node); void vlist_delete(struct vlist_tree *tree, struct vlist_node *node); -- 2.25.1