summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--interface-ip.c27
-rw-r--r--interface-ip.h7
-rw-r--r--utils.c20
-rw-r--r--utils.h11
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);