Move ID allocator to a separate file and use it also in OSPF

This commit is contained in:
Ondrej Zajicek (work) 2015-12-29 15:34:48 +01:00
parent 9a70c8d6c3
commit 74c838a870
11 changed files with 126 additions and 71 deletions

View file

@ -7,8 +7,10 @@ sha1.h
birdlib.h birdlib.h
bitops.c bitops.c
bitops.h bitops.h
ip.h idm.c
idm.h
ip.c ip.c
ip.h
lists.c lists.c
lists.h lists.h
md5.c md5.c

76
lib/idm.c Normal file
View file

@ -0,0 +1,76 @@
/*
* BIRD Library -- ID Map
*
* (c) 2013--2015 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2013--2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <stdlib.h>
#include "nest/bird.h"
#include "lib/idm.h"
#include "lib/resource.h"
#include "lib/string.h"
void
idm_init(struct idm *m, pool *p, uint size)
{
m->pos = 0;
m->used = 1;
m->size = size;
m->data = mb_allocz(p, m->size * sizeof(u32));
/* ID 0 is reserved */
m->data[0] = 1;
}
static inline int u32_cto(uint x) { return ffs(~x) - 1; }
u32
idm_alloc(struct idm *m)
{
uint i, j;
for (i = m->pos; i < m->size; i++)
if (m->data[i] != 0xffffffff)
goto found;
/* If we are at least 7/8 full, expand */
if (m->used > (m->size * 28))
{
m->size *= 2;
m->data = mb_realloc(m->data, m->size * sizeof(u32));
memset(m->data + i, 0, (m->size - i) * sizeof(u32));
goto found;
}
for (i = 0; i < m->pos; i++)
if (m->data[i] != 0xffffffff)
goto found;
ASSERT(0);
found:
ASSERT(i < 0x8000000);
m->pos = i;
j = u32_cto(m->data[i]);
m->data[i] |= (1 << j);
m->used++;
return 32 * i + j;
}
void
idm_free(struct idm *m, u32 id)
{
uint i = id / 32;
uint j = id % 32;
ASSERT((i < m->size) && (m->data[i] & (1 << j)));
m->data[i] &= ~(1 << j);
m->used--;
}

25
lib/idm.h Normal file
View file

@ -0,0 +1,25 @@
/*
* BIRD Library -- ID Map
*
* (c) 2013--2015 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2013--2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_IDM_H_
#define _BIRD_IDM_H_
struct idm
{
u32 *data;
u32 pos;
u32 used;
u32 size;
};
void idm_init(struct idm *m, pool *p, uint size);
u32 idm_alloc(struct idm *m);
void idm_free(struct idm *m, u32 id);
#endif

View file

@ -36,7 +36,6 @@ struct fib_node {
struct fib_node *next; /* Next in hash chain */ struct fib_node *next; /* Next in hash chain */
struct fib_iterator *readers; /* List of readers of this node */ struct fib_iterator *readers; /* List of readers of this node */
byte flags; /* User-defined, will be removed */ byte flags; /* User-defined, will be removed */
u32 uid; /* Unique ID based on hash, will be removed */
net_addr addr[0]; net_addr addr[0];
}; };

View file

@ -52,6 +52,7 @@
#include "nest/attrs.h" #include "nest/attrs.h"
#include "lib/alloca.h" #include "lib/alloca.h"
#include "lib/hash.h" #include "lib/hash.h"
#include "lib/idm.h"
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/string.h" #include "lib/string.h"
@ -61,9 +62,7 @@ static slab *rta_slab;
static slab *mpnh_slab; static slab *mpnh_slab;
static slab *rte_src_slab; static slab *rte_src_slab;
/* rte source ID bitmap */ static struct idm src_ids;
static u32 *src_ids;
static u32 src_id_size, src_id_used, src_id_pos;
#define SRC_ID_INIT_SIZE 4 #define SRC_ID_INIT_SIZE 4
/* rte source hash */ /* rte source hash */
@ -87,64 +86,11 @@ rte_src_init(void)
{ {
rte_src_slab = sl_new(rta_pool, sizeof(struct rte_src)); rte_src_slab = sl_new(rta_pool, sizeof(struct rte_src));
src_id_pos = 0; idm_init(&src_ids, rta_pool, SRC_ID_INIT_SIZE);
src_id_size = SRC_ID_INIT_SIZE;
src_ids = mb_allocz(rta_pool, src_id_size * sizeof(u32));
/* ID 0 is reserved */
src_ids[0] = 1;
src_id_used = 1;
HASH_INIT(src_hash, rta_pool, RSH_INIT_ORDER); HASH_INIT(src_hash, rta_pool, RSH_INIT_ORDER);
} }
static inline int u32_cto(uint x) { return ffs(~x) - 1; }
static inline u32
rte_src_alloc_id(void)
{
int i, j;
for (i = src_id_pos; i < src_id_size; i++)
if (src_ids[i] != 0xffffffff)
goto found;
/* If we are at least 7/8 full, expand */
if (src_id_used > (src_id_size * 28))
{
src_id_size *= 2;
src_ids = mb_realloc(src_ids, src_id_size * sizeof(u32));
bzero(src_ids + i, (src_id_size - i) * sizeof(u32));
goto found;
}
for (i = 0; i < src_id_pos; i++)
if (src_ids[i] != 0xffffffff)
goto found;
ASSERT(0);
found:
ASSERT(i < 0x8000000);
src_id_pos = i;
j = u32_cto(src_ids[i]);
src_ids[i] |= (1 << j);
src_id_used++;
return 32 * i + j;
}
static inline void
rte_src_free_id(u32 id)
{
int i = id / 32;
int j = id % 32;
ASSERT((i < src_id_size) && (src_ids[i] & (1 << j)));
src_ids[i] &= ~(1 << j);
src_id_used--;
}
HASH_DEFINE_REHASH_FN(RSH, struct rte_src) HASH_DEFINE_REHASH_FN(RSH, struct rte_src)
@ -165,7 +111,7 @@ rt_get_source(struct proto *p, u32 id)
src = sl_alloc(rte_src_slab); src = sl_alloc(rte_src_slab);
src->proto = p; src->proto = p;
src->private_id = id; src->private_id = id;
src->global_id = rte_src_alloc_id(); src->global_id = idm_alloc(&src_ids);
src->uc = 0; src->uc = 0;
HASH_INSERT2(src_hash, RSH, rta_pool, src); HASH_INSERT2(src_hash, RSH, rta_pool, src);
@ -181,7 +127,7 @@ rt_prune_sources(void)
if (src->uc == 0) if (src->uc == 0)
{ {
HASH_DO_REMOVE(src_hash, RSH, sp); HASH_DO_REMOVE(src_hash, RSH, sp);
rte_src_free_id(src->global_id); idm_free(&src_ids, src->global_id);
sl_free(rte_src_slab, src); sl_free(rte_src_slab, src);
} }
} }

View file

@ -253,7 +253,6 @@ fib_get(struct fib *f, const net_addr *a)
struct fib_node *e = fib_user_to_node(f, b); struct fib_node *e = fib_user_to_node(f, b);
e->readers = NULL; e->readers = NULL;
e->flags = 0; e->flags = 0;
e->uid = 0;
fib_insert(f, a, e); fib_insert(f, a, e);
memset(b, 0, f->node_offset); memset(b, 0, f->node_offset);

View file

@ -240,6 +240,8 @@ ospf_start(struct proto *P)
init_list(&(p->area_list)); init_list(&(p->area_list));
fib_init(&p->rtf, P->pool, p->ospf2 ? NET_IP4 : NET_IP6, fib_init(&p->rtf, P->pool, p->ospf2 ? NET_IP4 : NET_IP6,
sizeof(ort), OFFSETOF(ort, fn), 0, NULL); sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
if (ospf_is_v3(p))
idm_init(&p->idm, P->pool, 16);
p->areano = 0; p->areano = 0;
p->gr = ospf_top_new(p, P->pool); p->gr = ospf_top_new(p, P->pool);
s_init_list(&(p->lsal)); s_init_list(&(p->lsal));

View file

@ -14,7 +14,7 @@
#include "nest/bird.h" #include "nest/bird.h"
#include "lib/checksum.h" #include "lib/checksum.h"
#include "lib/ip.h" #include "lib/idm.h"
#include "lib/lists.h" #include "lib/lists.h"
#include "lib/slists.h" #include "lib/slists.h"
#include "lib/socket.h" #include "lib/socket.h"
@ -79,7 +79,6 @@
#define OSPF_VLINK_ID_OFFSET 0x80000000 #define OSPF_VLINK_ID_OFFSET 0x80000000
struct ospf_config struct ospf_config
{ {
struct proto_config c; struct proto_config c;
@ -215,6 +214,7 @@ struct ospf_proto
int areano; /* Number of area I belong to */ int areano; /* Number of area I belong to */
int padj; /* Number of neighbors in Exchange or Loading state */ int padj; /* Number of neighbors in Exchange or Loading state */
struct fib rtf; /* Routing table */ struct fib rtf; /* Routing table */
struct idm idm; /* OSPFv3 LSA ID map */
byte ospf2; /* OSPF v2 or v3 */ byte ospf2; /* OSPF v2 or v3 */
byte rfc1583; /* RFC1583 compatibility */ byte rfc1583; /* RFC1583 compatibility */
byte stub_router; /* Do not forward transit traffic */ byte stub_router; /* Do not forward transit traffic */

View file

@ -2005,6 +2005,9 @@ again1:
/* Remove unused rt entry, some special entries are persistent */ /* Remove unused rt entry, some special entries are persistent */
if (!nf->n.type && !nf->external_rte && !nf->area_net) if (!nf->n.type && !nf->external_rte && !nf->area_net)
{ {
if (nf->lsa_id)
idm_free(&p->idm, nf->lsa_id);
FIB_ITERATE_PUT(&fit); FIB_ITERATE_PUT(&fit);
fib_delete(fib, nf); fib_delete(fib, nf);
goto again1; goto again1;

View file

@ -81,6 +81,7 @@ typedef struct ort
orta n; orta n;
u32 old_metric1, old_metric2, old_tag, old_rid; u32 old_metric1, old_metric2, old_tag, old_rid;
rta *old_rta; rta *old_rta;
u32 lsa_id;
u8 external_rte; u8 external_rte;
u8 area_net; u8 area_net;

View file

@ -513,8 +513,7 @@ ospf_update_lsadb(struct ospf_proto *p)
} }
} }
static u32
static inline u32
ort_to_lsaid(struct ospf_proto *p, ort *nf) ort_to_lsaid(struct ospf_proto *p, ort *nf)
{ {
/* /*
@ -542,14 +541,17 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
* network appeared, we choose a different way. * network appeared, we choose a different way.
* *
* In OSPFv3, it is simpler. There is not a requirement for membership of the * In OSPFv3, it is simpler. There is not a requirement for membership of the
* result in the input network, so we just use a hash-based unique ID of a * result in the input network, so we just allocate a unique ID from ID map
* routing table entry for a route that originated given LSA. For ext-LSA, it * and store it in nf->lsa_id for further reference.
* is an imported route in the nest's routing table (p->table). For summary-LSA,
* it is a 'source' route in the protocol internal routing table (p->rtf).
*/ */
if (ospf_is_v3(p)) if (ospf_is_v3(p))
return nf->fn.uid; {
if (!nf->lsa_id)
nf->lsa_id = idm_alloc(&p->idm);
return nf->lsa_id;
}
net_addr_ip4 *net = (void *) nf->fn.addr; net_addr_ip4 *net = (void *) nf->fn.addr;
u32 id = ip4_to_u32(net->prefix); u32 id = ip4_to_u32(net->prefix);