summaryrefslogtreecommitdiffstats
path: root/routing-table.h
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2015-08-20 04:39:16 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2015-10-07 03:26:31 +0200
commit9724a046fa90b7b6a6be6f2efbb9feffb7f67e1d (patch)
treea258f9743d6cd5620963bc3afa1ca2bf067fc682 /routing-table.h
downloadkernel-routing-table-art.tar.xz
kernel-routing-table-art.zip
Allotment routing table implementationart
Diffstat (limited to 'routing-table.h')
-rw-r--r--routing-table.h68
1 files changed, 68 insertions, 0 deletions
diff --git a/routing-table.h b/routing-table.h
new file mode 100644
index 0000000..184c735
--- /dev/null
+++ b/routing-table.h
@@ -0,0 +1,68 @@
+/* Copyright 2015 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */
+
+#ifndef ROUTINGTABLE_H
+#define ROUTINGTABLE_H
+
+#include <linux/spinlock.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+#define ART_MAXLVL 16 /* We currently use 16 levels for IPv6. */
+
+/*
+ * Root of the ART tables.
+ */
+struct art_root {
+ struct art_table *ar_root; /* First table */
+ uint8_t ar_bits[ART_MAXLVL]; /* Per level stride */
+ uint8_t ar_nlvl; /* Number of levels */
+ uint8_t ar_alen; /* Address length in bits */
+};
+
+struct routing_table {
+ struct art_root v4;
+ struct art_root v6;
+ rwlock_t lock;
+};
+
+int routing_table_init(struct routing_table *table);
+void routing_table_free(struct routing_table *table);
+int routing_table_insert_v4(struct routing_table *table, struct in_addr ip, uint8_t cidr, void *value);
+int routing_table_insert_v6(struct routing_table *table, struct in6_addr ip, uint8_t cidr, void *value);
+void *routing_table_lookup_v4(struct routing_table *table, struct in_addr ip);
+void *routing_table_lookup_v6(struct routing_table *table, struct in6_addr ip);
+int routing_table_remove_v4(struct routing_table *table, struct in_addr ip, uint8_t cidr);
+int routing_table_remove_v6(struct routing_table *table, struct in6_addr ip, uint8_t cidr);
+int routing_table_remove_by_value(struct routing_table *table, void *value);
+int routing_table_walk_ips(struct routing_table *table, void *ctx, int (*func)(void *ctx, void *value, union nf_inet_addr ip, uint8_t cidr, uint8_t ip_version));
+int routing_table_walk_ips_by_value(struct routing_table *table, void *ctx, void *value, int (*func)(void *ctx, union nf_inet_addr ip, uint8_t cidr, uint8_t ip_version));
+
+static inline void *routing_table_lookup_dst(struct routing_table *table, struct sk_buff *skb)
+{
+ switch (ip_hdr(skb)->version) {
+ case 4:
+ return routing_table_lookup_v4(table, *(struct in_addr *)&ip_hdr(skb)->daddr);
+ case 6:
+ return routing_table_lookup_v6(table, ipv6_hdr(skb)->daddr);
+ default:
+ return NULL;
+ }
+}
+
+static inline void *routing_table_lookup_src(struct routing_table *table, struct sk_buff *skb)
+{
+ switch (ip_hdr(skb)->version) {
+ case 4:
+ return routing_table_lookup_v4(table, *(struct in_addr *)&ip_hdr(skb)->saddr);
+ case 6:
+ return routing_table_lookup_v6(table, ipv6_hdr(skb)->saddr);
+ default:
+ return NULL;
+ }
+}
+
+#ifdef DEBUG
+void routing_table_selftest(void);
+#endif
+
+#endif