0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

Lib: Extend MPLS label allocator bitmap

Add function lmap_last_one_in_range() for finding the last active label
in a label range.
This commit is contained in:
Ondrej Zajicek 2023-09-18 14:12:22 +02:00
parent bcff3ae79a
commit e338c4b63c
3 changed files with 88 additions and 0 deletions

View File

@ -398,6 +398,81 @@ lmap_first_zero_in_range(struct lmap *b, uint lo, uint hi)
return hi; return hi;
} }
static inline int
b1024_last_one(u32 *p)
{
for (int i = 31; i >= 0; i--)
if (p[i])
return 32*i + (31 - u32_clz(p[i]));
return 1024;
}
static uint
b1024_last_one_in_range(u32 *p, uint lo, uint hi)
{
uint lo0 = lo >> 5;
uint lo1 = lo & 0x1f;
uint hi0 = hi >> 5;
uint hi1 = hi & 0x1f;
u32 mask = (1u << hi1) - 1;
u32 val;
for (int i = hi0; i > (int) lo0; i--)
{
val = p[i] & mask;
mask = ~0;
if (val)
return 32*i + (31 - u32_clz(val));
}
{
mask &= ~((1u << lo1) - 1);
val = p[lo0] & mask;
if (val)
return 32*lo0 + (31 - u32_clz(val));
}
return hi;
}
uint
lmap_last_one_in_range(struct lmap *b, uint lo, uint hi)
{
uint lo0 = lo >> 10;
uint lo1 = lo & 0x3ff;
uint hi0 = hi >> 10;
uint hi1 = hi & 0x3ff;
if (hi1 && (hi0 < b->size) && b->data[hi0])
{
uint min = (lo0 == hi0) ? lo1 : 0;
uint n0 = hi0;
uint n1 = b1024_last_one_in_range(b->data[n0], min, hi1);
if (n1 < hi1)
return (n0 << 10) + n1;
}
for (int i = (int)MIN(hi0, b->size) - 1; i >= (int) lo0; i--)
{
if (! b->data[i])
continue;
uint n0 = i;
uint n1 = b1024_last_one(b->data[n0]);
if ((n0 == lo0) && (n1 < lo1))
return hi;
return (n0 << 10) + n1;
}
return hi;
}
void void
lmap_check(struct lmap *b) lmap_check(struct lmap *b)
{ {

View File

@ -79,6 +79,7 @@ void lmap_set(struct lmap *b, uint n);
void lmap_clear(struct lmap *b, uint n); void lmap_clear(struct lmap *b, uint n);
uint lmap_first_zero(struct lmap *b); uint lmap_first_zero(struct lmap *b);
uint lmap_first_zero_in_range(struct lmap *b, uint lo, uint hi); uint lmap_first_zero_in_range(struct lmap *b, uint lo, uint hi);
uint lmap_last_one_in_range(struct lmap *b, uint lo, uint hi);
void lmap_check(struct lmap *b); void lmap_check(struct lmap *b);
#endif #endif

View File

@ -216,6 +216,18 @@ t_lmap_set_clear_fill(void)
lmap_clear(&b, n); lmap_clear(&b, n);
expected[n] = 0; expected[n] = 0;
} }
{
n = lmap_last_one_in_range(&b, lo, hi);
bt_assert(n >= lo);
bt_assert(n <= hi);
for (last = n + 1; last < hi; last++)
bt_assert(!expected[last]);
if (n < hi)
bt_assert(expected[n]);
}
} }
uint cnt = 0; uint cnt = 0;