From: Jan Moskyto Matejka Date: Mon, 25 Apr 2016 08:39:18 +0000 (+0200) Subject: FIB: Added label allocation option X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6adf16ca1bc9333a9422f38a27796aa105c0637e;p=thirdparty%2Fbird.git FIB: Added label allocation option Why is this inside FIB and not at some layer before? Simply only this layer knows whether fib_get() just returns an existing record or inserts a new one. --- diff --git a/nest/route.h b/nest/route.h index 44e42b707..2a613d59e 100644 --- a/nest/route.h +++ b/nest/route.h @@ -9,6 +9,7 @@ #ifndef _BIRD_ROUTE_H_ #define _BIRD_ROUTE_H_ +#include "lib/idm.h" #include "lib/lists.h" #include "lib/resource.h" #include "lib/timer.h" @@ -54,6 +55,7 @@ typedef void (*fib_init_fn)(void *); struct fib { pool *fib_pool; /* Pool holding all our data */ slab *fib_slab; /* Slab holding all fib nodes */ + struct idm *idm; /* ID Map for allocations */ struct fib_node **hash_table; /* Node hash table */ uint hash_size; /* Number of hash table entries (a power of two) */ uint hash_order; /* Binary logarithm of hash_size */ diff --git a/nest/rt-fib.c b/nest/rt-fib.c index f81506bc6..fa1c8d2ed 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -95,6 +95,11 @@ fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offse { uint addr_length = net_addr_length[addr_type]; + if (addr_type == NET_MPLS) + { + f->idm = mb_alloc(p, sizeof(*f->idm)); + idm_init(f->idm, p, 64); + } if (!hash_order) hash_order = HASH_DEF_ORDER; f->fib_pool = p; @@ -238,7 +243,6 @@ static void fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) { ASSERT(f->addr_type == a->type); - switch (f->addr_type) { case NET_IP4: FIB_INSERT(f, a, e, ip4); return; @@ -252,6 +256,31 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) } } +net_addr * const fib_idm_alloc(struct fib *f, const net_addr *a) +{ + ASSERT(f->idm && (f->addr_type == NET_MPLS)); + + u32 label; + if (a) + label = idm_alloc(f->idm, ((net_addr_mpls *)a)->label, ((net_addr_mpls *)a)->label); + else + label = idm_alloc(f->idm, 16, (1<<20)-1); + + if (!label) + return NULL; + + static net_addr_union nu; + net_fill_mpls(&nu.n, label); + return &nu.n; +} + +void fib_idm_free(struct fib *f, struct fib_node *e) +{ + ASSERT(f->idm); + + u32 label = ((net_addr_mpls *)e->addr)->label; + idm_free(f->idm, label); +} /** * fib_get - find or create a FIB node @@ -264,10 +293,22 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) void * fib_get(struct fib *f, const net_addr *a) { - void *b = fib_find(f, a); - if (b) + void *b; + if (a && (b = fib_find(f, a))) return b; + ASSERT(a || f->idm); + if (f->idm) + { + const net_addr *ag = fib_idm_alloc(f, a); + if (!ag) + { + ASSERT(!a); + return NULL; + } + a = ag; + } + if (f->fib_slab) b = sl_alloc(f->fib_slab); else @@ -426,6 +467,9 @@ fib_delete(struct fib *f, void *E) else mb_free(E); + if (f->idm) + fib_idm_free(f, e); + if (f->entries-- < f->entries_min) fib_rehash(f, -HASH_LO_STEP); return;