0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

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.
This commit is contained in:
Jan Moskyto Matejka 2016-04-25 10:39:18 +02:00
parent 160239d523
commit 6adf16ca1b
2 changed files with 49 additions and 3 deletions

View File

@ -9,6 +9,7 @@
#ifndef _BIRD_ROUTE_H_ #ifndef _BIRD_ROUTE_H_
#define _BIRD_ROUTE_H_ #define _BIRD_ROUTE_H_
#include "lib/idm.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/timer.h" #include "lib/timer.h"
@ -54,6 +55,7 @@ typedef void (*fib_init_fn)(void *);
struct fib { struct fib {
pool *fib_pool; /* Pool holding all our data */ pool *fib_pool; /* Pool holding all our data */
slab *fib_slab; /* Slab holding all fib nodes */ slab *fib_slab; /* Slab holding all fib nodes */
struct idm *idm; /* ID Map for allocations */
struct fib_node **hash_table; /* Node hash table */ struct fib_node **hash_table; /* Node hash table */
uint hash_size; /* Number of hash table entries (a power of two) */ uint hash_size; /* Number of hash table entries (a power of two) */
uint hash_order; /* Binary logarithm of hash_size */ uint hash_order; /* Binary logarithm of hash_size */

View File

@ -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]; 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) if (!hash_order)
hash_order = HASH_DEF_ORDER; hash_order = HASH_DEF_ORDER;
f->fib_pool = p; f->fib_pool = p;
@ -238,7 +243,6 @@ static void
fib_insert(struct fib *f, const net_addr *a, struct fib_node *e) fib_insert(struct fib *f, const net_addr *a, struct fib_node *e)
{ {
ASSERT(f->addr_type == a->type); ASSERT(f->addr_type == a->type);
switch (f->addr_type) switch (f->addr_type)
{ {
case NET_IP4: FIB_INSERT(f, a, e, ip4); return; 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 * 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 * void *
fib_get(struct fib *f, const net_addr *a) fib_get(struct fib *f, const net_addr *a)
{ {
void *b = fib_find(f, a); void *b;
if (b) if (a && (b = fib_find(f, a)))
return b; 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) if (f->fib_slab)
b = sl_alloc(f->fib_slab); b = sl_alloc(f->fib_slab);
else else
@ -426,6 +467,9 @@ fib_delete(struct fib *f, void *E)
else else
mb_free(E); mb_free(E);
if (f->idm)
fib_idm_free(f, e);
if (f->entries-- < f->entries_min) if (f->entries-- < f->entries_min)
fib_rehash(f, -HASH_LO_STEP); fib_rehash(f, -HASH_LO_STEP);
return; return;