Download raw body.
bgpd: rework bitmap code to use max elements instead of bits
The bitmap code currently tracks the maximum number of bits allowed.
This is a bit tricky since BITMAP_ROUNDUP() could actually overflow for
very big bitmaps (other bgpd code will break before hitting such big maps)
In anycase I think moving the max from bits to number of elements in the
array makes the code nicer.
On top of this add a bit of extra casts to BITMAP_SETPTR() and
BITMAP_GETPTR() to make 32bit archs happy and not warn about the
difference in size of uint64_t and a pointer value.
--
:wq Claudio
Index: bitmap.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bitmap.c,v
diff -u -p -r1.3 bitmap.c
--- bitmap.c 6 Mar 2026 13:10:14 -0000 1.3
+++ bitmap.c 7 May 2026 11:10:33 -0000
@@ -24,10 +24,10 @@
#include "bgpd.h"
#define BITMAP_BITS 64
-#define BITMAP_ALLOCBITS (4 * BITMAP_BITS)
-#define BITMAP_ROUNDUP(x, y) ((((x) + (y) - 1)/(y)) * (y))
-#define BITMAP_SETPTR(x) ((uint64_t)(x) | 0x1)
-#define BITMAP_GETPTR(x) (uint64_t *)((x) & ~0x1)
+#define BITMAP_ALLOCSIZE 4
+#define BITMAP_ROUNDUP(x, y) ((((x) + (y))/(y)) * (y))
+#define BITMAP_SETPTR(x) ((uint64_t)(uintptr_t)(x) | 0x1)
+#define BITMAP_GETPTR(x) (uint64_t *)((uintptr_t)(x) & ~0x1)
size_t bitmap_size;
uint64_t bitmap_cnt;
@@ -37,7 +37,7 @@ bitmap_getset(struct bitmap *map, uint64
{
if ((map->data[0] & 0x1) == 0) {
*ptr = map->data;
- *max = nitems(map->data) * BITMAP_BITS;
+ *max = nitems(map->data);
} else {
*ptr = BITMAP_GETPTR(map->data[0]);
*max = map->data[1];
@@ -52,31 +52,33 @@ bitmap_free(struct bitmap *map)
if (map->data[0] & 0x1) {
bitmap_getset(map, &ptr, &max);
- bitmap_size -= max / 8;
+ bitmap_size -= max * sizeof(uint64_t);
bitmap_cnt--;
free(ptr);
}
}
static int
-bitmap_resize(struct bitmap *map, uint32_t bid)
+bitmap_resize(struct bitmap *map, uint32_t elm)
{
uint64_t *ptr, *new;
- uint32_t elm, size, oldmax, newmax;
+ uint32_t oldmax, newmax;
bitmap_getset(map, &ptr, &oldmax);
/* get new map */
- newmax = BITMAP_ROUNDUP(bid + 1, BITMAP_ALLOCBITS);
- if ((new = malloc(newmax / 8)) == NULL)
+ newmax = BITMAP_ROUNDUP(elm, BITMAP_ALLOCSIZE);
+ if (newmax < oldmax) {
+ errno = ERANGE;
+ return -1;
+ }
+ if ((new = malloc(newmax * sizeof(*new))) == NULL)
return -1;
/* copy data over */
- size = oldmax / BITMAP_BITS;
- for (elm = 0; elm < size; elm++)
+ for (elm = 0; elm < oldmax; elm++)
new[elm] = ptr[elm];
- size = newmax / BITMAP_BITS;
- for ( ; elm < size; elm++)
+ for ( ; elm < newmax; elm++)
new[elm] = 0;
/* free old data */
@@ -85,7 +87,7 @@ bitmap_resize(struct bitmap *map, uint32
/* set new data */
map->data[0] = BITMAP_SETPTR(new);
map->data[1] = newmax;
- bitmap_size += newmax / 8;
+ bitmap_size += newmax * sizeof(*new);
bitmap_cnt++;
return 0;
@@ -102,21 +104,20 @@ bitmap_set(struct bitmap *map, uint32_t
uint32_t max, elm;
bitmap_getset(map, &ptr, &max);
+ elm = bid / BITMAP_BITS;
if (bid == 0) {
errno = EINVAL;
return -1;
}
- if (bid >= max) {
- if (bitmap_resize(map, bid) == -1)
+ if (elm >= max) {
+ if (bitmap_resize(map, elm) == -1)
return -1;
bitmap_getset(map, &ptr, &max);
}
- elm = bid / BITMAP_BITS;
bid %= BITMAP_BITS;
-
ptr[elm] |= (1ULL << bid);
return 0;
}
@@ -131,13 +132,12 @@ bitmap_test(struct bitmap *map, uint32_t
uint32_t max, elm;
bitmap_getset(map, &ptr, &max);
+ elm = bid / BITMAP_BITS;
- if (bid >= max || bid == 0)
+ if (elm >= max || bid == 0)
return 0;
- elm = bid / BITMAP_BITS;
bid %= BITMAP_BITS;
-
return (ptr[elm] & (1ULL << bid)) != 0;
}
@@ -151,13 +151,12 @@ bitmap_clear(struct bitmap *map, uint32_
uint32_t max, elm;
bitmap_getset(map, &ptr, &max);
+ elm = bid / BITMAP_BITS;
- if (bid >= max || bid == 0)
+ if (elm >= max || bid == 0)
return;
- elm = bid / BITMAP_BITS;
bid %= BITMAP_BITS;
-
ptr[elm] &= ~(1ULL << bid);
}
@@ -169,12 +168,11 @@ int
bitmap_empty(struct bitmap *map)
{
uint64_t *ptr, m;
- uint32_t elm, max, end;
+ uint32_t elm, max;
bitmap_getset(map, &ptr, &max);
- end = max / BITMAP_BITS;
- for (elm = 0; elm < end; elm++) {
+ for (elm = 0; elm < max; elm++) {
m = ptr[elm];
if (elm == 0)
m &= ~0x1; /* skip inline marker */
@@ -191,12 +189,11 @@ int
bitmap_id_get(struct bitmap *map, uint32_t *bid)
{
uint64_t *ptr, m;
- uint32_t elm, max, end;
+ uint32_t elm, max;
bitmap_getset(map, &ptr, &max);
- end = max / BITMAP_BITS;
- for (elm = 0; elm < end; elm++) {
+ for (elm = 0; elm < max; elm++) {
m = ~ptr[elm];
if (elm == 0)
m &= ~0x1; /* skip inline marker */
@@ -209,10 +206,10 @@ bitmap_id_get(struct bitmap *map, uint32
return 0;
}
- if (bitmap_set(map, max) == -1)
+ *bid = max * BITMAP_BITS;
+ if (bitmap_set(map, *bid) == -1)
return -1;
- *bid = max;
return 0;
}
bgpd: rework bitmap code to use max elements instead of bits