]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
FIB: Added label allocation option
authorJan Moskyto Matejka <mq@ucw.cz>
Mon, 25 Apr 2016 08:39:18 +0000 (10:39 +0200)
committerJan Moskyto Matejka <mq@ucw.cz>
Mon, 25 Apr 2016 08:39:18 +0000 (10:39 +0200)
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.

nest/route.h
nest/rt-fib.c

index 44e42b70793809818e213d6ec4c4591f362b31ff..2a613d59e4aa6d1961f2d523c575dd244dc52480 100644 (file)
@@ -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 */
index f81506bc665b0c0dee35586c335294a67e54bb6a..fa1c8d2ed1632185c2e0bce995b2d28d67df4c0c 100644 (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];
 
+  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;