mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-21 22:07:03 +00:00
ID Map allows max and min limits
This commit is contained in:
parent
d04042f376
commit
160239d523
225
lib/idm.c
225
lib/idm.c
@ -29,35 +29,131 @@ idm_init(struct idm *m, pool *p, uint size)
|
|||||||
|
|
||||||
static inline int u32_cto(uint x) { return ffs(~x) - 1; }
|
static inline int u32_cto(uint x) { return ffs(~x) - 1; }
|
||||||
|
|
||||||
u32
|
static void
|
||||||
idm_alloc(struct idm *m)
|
idm_grow(struct idm *m, u32 size)
|
||||||
{
|
{
|
||||||
|
m->data = mb_realloc(m->data, size * sizeof(u32));
|
||||||
|
memset(m->data + m->size, 0, (size - m->size) * sizeof(u32));
|
||||||
|
m->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
idm_alloc_given(struct idm *m, u32 val)
|
||||||
|
{
|
||||||
|
uint i = val / 32, j = val % 32;
|
||||||
|
if (i >= m->size)
|
||||||
|
idm_grow(m, i+1);
|
||||||
|
|
||||||
|
if (m->data[i] & (1 << j))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
m->data[i] |= (1 << j);
|
||||||
|
m->used--;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new ID
|
||||||
|
* @m: the ID Map to be used
|
||||||
|
* @min: minimal value returned
|
||||||
|
* @max: maximal value returned
|
||||||
|
*
|
||||||
|
* Returns the allocated value. Returns 0 if allocation is impossible.
|
||||||
|
*/
|
||||||
|
u32
|
||||||
|
idm_alloc(struct idm *m, u32 min, u32 max)
|
||||||
|
{
|
||||||
|
uint mini = min / 32, maxi = max / 32;
|
||||||
|
|
||||||
|
u32 minmask = ~((1 << (min % 32)) - 1);
|
||||||
|
u32 maxmask = ((1ULL << ((max+1) % 32)) - 1);
|
||||||
|
|
||||||
|
u32 mask;
|
||||||
|
|
||||||
uint i, j;
|
uint i, j;
|
||||||
|
|
||||||
for (i = m->pos; i < m->size; i++)
|
/* Not even allocated data array at mini. */
|
||||||
if (m->data[i] != 0xffffffff)
|
if (mini >= m->size)
|
||||||
goto found;
|
|
||||||
|
|
||||||
/* If we are at least 7/8 full, expand */
|
|
||||||
if (m->used > (m->size * 28))
|
|
||||||
{
|
{
|
||||||
m->size *= 2;
|
i = mini;
|
||||||
m->data = mb_realloc(m->data, m->size * sizeof(u32));
|
idm_grow(m, mini+1);
|
||||||
memset(m->data + i, 0, (m->size - i) * sizeof(u32));
|
mask = minmask;
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < m->pos; i++)
|
/* Only one u32 contains all possible values. */
|
||||||
if (m->data[i] != 0xffffffff)
|
if (mini == maxi)
|
||||||
|
{
|
||||||
|
mask = (minmask & maxmask);
|
||||||
|
if ((m->data[mini] & mask) == (mask))
|
||||||
|
return 0;
|
||||||
|
i = mini;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a)
|
||||||
|
* m->pos
|
||||||
|
* v
|
||||||
|
* u32's in m->data: ..............................
|
||||||
|
* ^ ^
|
||||||
|
* mini maxi
|
||||||
|
*
|
||||||
|
* b)
|
||||||
|
* m->pos
|
||||||
|
* v
|
||||||
|
* u32's in m->data: ..............................
|
||||||
|
* ^ ^
|
||||||
|
* mini maxi
|
||||||
|
*
|
||||||
|
* c)
|
||||||
|
* m->pos
|
||||||
|
* v
|
||||||
|
* u32's in m->data: ..............................
|
||||||
|
* ^ ^
|
||||||
|
* mini maxi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Beginning at: mini+1 (a) or m->pos (b,c) m->pos
|
||||||
|
* End at last before: MIN(maxi, m->size) ... this skips loop at c)
|
||||||
|
*/
|
||||||
|
for (i = MAX(mini+1, m->pos); i < MIN(maxi, m->size); i++)
|
||||||
|
if (m->data[i] != (mask = 0xffffffff))
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
ASSERT(0);
|
/* if maxi points to an allocated value */
|
||||||
|
if (maxi < m->size)
|
||||||
|
if ((m->data[i = maxi] & maxmask) != (mask = maxmask))
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
/* If we have just hit m->size and we are at least 7/8 full, expand */
|
||||||
|
if ((i == m->size) && (m->used > (m->size * 28)))
|
||||||
|
{
|
||||||
|
idm_grow(m, m->size * 2);
|
||||||
|
mask = 0xffffffff;
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Trying i == mini (skipped before) */
|
||||||
|
if ((m->data[i = mini] & minmask) != (mask = minmask))
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
/* Beginning at mini+1 in all cases
|
||||||
|
* End before m->pos (a,b) or maxi (c), whatever comes earlier. This skips loop at a) */
|
||||||
|
|
||||||
|
for (i = mini+1; i < MIN(maxi, m->pos); i++)
|
||||||
|
if (m->data[i] != (mask = 0xffffffff))
|
||||||
|
goto found;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
found:
|
found:
|
||||||
ASSERT(i < 0x8000000);
|
if (i >= 0x8000000) // Too large value
|
||||||
|
return 0;
|
||||||
|
|
||||||
m->pos = i;
|
m->pos = i;
|
||||||
j = u32_cto(m->data[i]);
|
j = u32_cto(m->data[i] | ~mask);
|
||||||
|
|
||||||
m->data[i] |= (1 << j);
|
m->data[i] |= (1 << j);
|
||||||
m->used++;
|
m->used++;
|
||||||
@ -74,3 +170,100 @@ idm_free(struct idm *m, u32 id)
|
|||||||
m->data[i] &= ~(1 << j);
|
m->data[i] &= ~(1 << j);
|
||||||
m->used--;
|
m->used--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sysdep/unix/unix.h"
|
||||||
|
|
||||||
|
struct idm m;
|
||||||
|
|
||||||
|
static void idm_dump(struct idm *m)
|
||||||
|
{
|
||||||
|
int w = 0;
|
||||||
|
char b[90];
|
||||||
|
for (int i=0; i<m->size; i++) {
|
||||||
|
u32 val = m->data[i];
|
||||||
|
while (val) {
|
||||||
|
u32 n = ffs(val)-1;
|
||||||
|
w += sprintf(b + w, "%u,", i*32 + n);
|
||||||
|
if (w < 72) {
|
||||||
|
b[w++] = ' ';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b[w++] = '\n';
|
||||||
|
b[w] = 0;
|
||||||
|
debug(b);
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
val &= ~(1U<<n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
b[w++] = '\n';
|
||||||
|
b[w] = 0;
|
||||||
|
debug(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bitdump(u32 val)
|
||||||
|
{
|
||||||
|
for (int i=0;i<32;i++)
|
||||||
|
debug("%c", "01"[!!(val&(1<<i))]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump(const char *msg)
|
||||||
|
{
|
||||||
|
debug(msg);
|
||||||
|
debug("Used: %u, Pos: %u, Size: %u\n", m.used, m.pos, m.size);
|
||||||
|
idm_dump(&m);
|
||||||
|
#if 0
|
||||||
|
for (int i=0;i<m.size;i+=2) {
|
||||||
|
debug("%3d: ", i*32);
|
||||||
|
bitdump(m.data[i]);
|
||||||
|
bitdump(m.data[i+1]);
|
||||||
|
debug("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TA(min, max) debug("Alloc from (%u, %u): %u\n", min, max, idm_alloc(&m, min, max)); dump("")
|
||||||
|
#define TF(n) debug("Free %u\n", n); idm_free(&m, n); dump("")
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
log_init_debug(NULL);
|
||||||
|
resource_init();
|
||||||
|
idm_init(&m, &root_pool, 4);
|
||||||
|
|
||||||
|
TA(20, 40);
|
||||||
|
TA(20, 40);
|
||||||
|
TA(20, 40);
|
||||||
|
TA(20, 40);
|
||||||
|
TA(10, 30);
|
||||||
|
TA(10, 20);
|
||||||
|
TF(10);
|
||||||
|
TA(10, 20);
|
||||||
|
TF(11);
|
||||||
|
TA(65, 65);
|
||||||
|
debug("Alloc enough to auto-grow\n");
|
||||||
|
for (int i=0; i<105; i++)
|
||||||
|
idm_alloc(&m, 0, 200);
|
||||||
|
dump("");
|
||||||
|
TA(0, 200);
|
||||||
|
TA(0, 200);
|
||||||
|
|
||||||
|
TA(513, 513);
|
||||||
|
|
||||||
|
TA(1000, 2000);
|
||||||
|
TA(256, 257);
|
||||||
|
TA(256, 257);
|
||||||
|
TA(256, 257);
|
||||||
|
TF(1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@ -19,7 +19,7 @@ struct idm
|
|||||||
};
|
};
|
||||||
|
|
||||||
void idm_init(struct idm *m, pool *p, uint size);
|
void idm_init(struct idm *m, pool *p, uint size);
|
||||||
u32 idm_alloc(struct idm *m);
|
u32 idm_alloc(struct idm *m, u32 min, u32 max);
|
||||||
void idm_free(struct idm *m, u32 id);
|
void idm_free(struct idm *m, u32 id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,9 +113,11 @@ 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 = idm_alloc(&src_ids);
|
src->global_id = idm_alloc(&src_ids, 1, 0xffffffff);
|
||||||
src->uc = 0;
|
src->uc = 0;
|
||||||
|
|
||||||
|
ASSERT(src->global_id); /* Couldn't allocate new ID */
|
||||||
|
|
||||||
HASH_INSERT2(src_hash, RSH, rta_pool, src);
|
HASH_INSERT2(src_hash, RSH, rta_pool, src);
|
||||||
|
|
||||||
return src;
|
return src;
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
|
#include "lib/idm.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
|
||||||
#define HASH_DEF_ORDER 10
|
#define HASH_DEF_ORDER 10
|
||||||
|
@ -548,7 +548,10 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
|
|||||||
if (ospf_is_v3(p))
|
if (ospf_is_v3(p))
|
||||||
{
|
{
|
||||||
if (!nf->lsa_id)
|
if (!nf->lsa_id)
|
||||||
nf->lsa_id = idm_alloc(&p->idm);
|
nf->lsa_id = idm_alloc(&p->idm, 0, 0xffffffff);
|
||||||
|
|
||||||
|
if (!nf->lsa_id)
|
||||||
|
log(L_FATAL "%s: LSA ID allocation failed, using 0 as fallback.", p->p.name);
|
||||||
|
|
||||||
return nf->lsa_id;
|
return nf->lsa_id;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user