Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: basic stats for bitmaps
To:
tech@openbsd.org
Date:
Wed, 4 Mar 2026 17:54:43 +0100

Download raw body.

Thread
  • Claudio Jeker:

    bgpd: basic stats for bitmaps

This adds some stats for the use of bitmaps.

Only account for the extended bitmaps that allocate extra memory.
So the count may be much lower since up to 127 bits the map uses
the struct itself for storage.

It would be nice to also account for the embedded bitmaps but the API
makes it hard to correctly do the accounting. Also it is unclear if that
will gain us much more information.

-- 
:wq Claudio

Index: bgpctl/output.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
diff -u -p -r1.70 output.c
--- bgpctl/output.c	2 Mar 2026 12:09:10 -0000	1.70
+++ bgpctl/output.c	2 Mar 2026 13:45:14 -0000
@@ -1112,6 +1112,8 @@ show_rib_mem(struct rde_memstats *stats)
 	printf("%10lld pending prefix entries using %s of memory\n",
 	    stats->pend_prefix_cnt, fmt_mem(stats->pend_prefix_cnt *
 	    sizeof(struct pend_prefix)));
+	printf("%10lld extended bitmaps using %s of memory\n",
+	    stats->bitmap_cnt, fmt_mem(stats->bitmap_size));
 	printf("%10lld filters using %s of memory\n",
 	    stats->filter_cnt, fmt_mem(stats->filter_size));
 	printf("\t   and holding %lld references\n",
@@ -1136,7 +1138,7 @@ show_rib_mem(struct rde_memstats *stats)
 	    stats->rib_cnt * sizeof(struct rib_entry) +
 	    stats->path_cnt * sizeof(struct rde_aspath) +
 	    stats->aspath_size + stats->attr_cnt * sizeof(struct attr) +
-	    stats->attr_data));
+	    stats->attr_data) + stats->bitmap_size);
 	printf("Sets and filters using %s of memory\n",
 	    fmt_mem(stats->aset_size + stats->pset_size + stats->aspa_size +
 	    stats->filter_set_size));
Index: bgpctl/output_json.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output_json.c,v
diff -u -p -r1.61 output_json.c
--- bgpctl/output_json.c	2 Mar 2026 12:09:10 -0000	1.61
+++ bgpctl/output_json.c	2 Mar 2026 13:46:04 -0000
@@ -937,6 +937,8 @@ json_rib_mem(struct rde_memstats *stats)
 	    stats->attr_cnt * sizeof(struct attr), stats->attr_refs);
 	json_rib_mem_element("attributes", stats->attr_dcnt,
 	    stats->attr_data, UINT64_MAX);
+	json_rib_mem_element("bitmaps", stats->bitmap_cnt,
+	    stats->bitmap_size, UINT64_MAX);
 	json_rib_mem_element("total", UINT64_MAX,
 	    pts + stats->prefix_cnt * sizeof(struct prefix) +
 	    stats->adjout_prefix_cnt * sizeof(struct adjout_prefix) +
@@ -946,7 +948,7 @@ json_rib_mem(struct rde_memstats *stats)
 	    stats->rib_cnt * sizeof(struct rib_entry) +
 	    stats->path_cnt * sizeof(struct rde_aspath) +
 	    stats->aspath_size + stats->attr_cnt * sizeof(struct attr) +
-	    stats->attr_data, UINT64_MAX);
+	    stats->attr_data + stats->bitmap_size, UINT64_MAX);
 	json_do_end();
 
 	json_do_object("filters", 0);
Index: bgpctl/output_ometric.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/output_ometric.c,v
diff -u -p -r1.25 output_ometric.c
--- bgpctl/output_ometric.c	2 Mar 2026 12:09:10 -0000	1.25
+++ bgpctl/output_ometric.c	2 Mar 2026 13:46:42 -0000
@@ -334,6 +334,8 @@ ometric_rib_mem(struct rde_memstats *sta
 	    stats->attr_cnt * sizeof(struct attr), stats->attr_refs);
 	ometric_rib_mem_element("attributes", stats->attr_dcnt,
 	    stats->attr_data, UINT64_MAX);
+	ometric_rib_mem_element("bitmap", stats->bitmap_cnt,
+	    stats->bitmap_size, UINT64_MAX);
 
 	ometric_rib_mem_element("total", UINT64_MAX,
 	    pts + stats->prefix_cnt * sizeof(struct prefix) +
@@ -344,7 +346,7 @@ ometric_rib_mem(struct rde_memstats *sta
 	    stats->rib_cnt * sizeof(struct rib_entry) +
 	    stats->path_cnt * sizeof(struct rde_aspath) +
 	    stats->aspath_size + stats->attr_cnt * sizeof(struct attr) +
-	    stats->attr_data, UINT64_MAX);
+	    stats->attr_data + stats->bitmap_size, UINT64_MAX);
 
 	ometric_rib_mem_element("filter", stats->filter_cnt,
 	    stats->filter_size, stats->filter_refs);
Index: bgpd/bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
diff -u -p -r1.534 bgpd.h
--- bgpd/bgpd.h	2 Mar 2026 12:08:30 -0000	1.534
+++ bgpd/bgpd.h	2 Mar 2026 13:30:15 -0000
@@ -1425,6 +1425,8 @@ struct rde_memstats {
 	long long	pset_size;
 	long long	aspa_cnt;
 	long long	aspa_size;
+	long long	bitmap_cnt;
+	long long	bitmap_size;
 	long long	filter_cnt;
 	long long	filter_size;
 	long long	filter_refs;
Index: bgpd/bitmap.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bitmap.c,v
diff -u -p -r1.1 bitmap.c
--- bgpd/bitmap.c	11 Dec 2025 12:18:27 -0000	1.1
+++ bgpd/bitmap.c	2 Mar 2026 13:31:52 -0000
@@ -29,6 +29,9 @@
 #define BITMAP_SETPTR(x)	((uint64_t)(x) | 0x1)
 #define BITMAP_GETPTR(x)	(uint64_t *)((x) & ~0x1)
 
+size_t bitmap_size;
+uint64_t bitmap_cnt;
+
 static inline void
 bitmap_getset(struct bitmap *map, uint64_t **ptr, uint32_t *max)
 {
@@ -41,13 +44,28 @@ bitmap_getset(struct bitmap *map, uint64
 	}
 }
 
+static void
+bitmap_free(struct bitmap *map)
+{
+	uint64_t *ptr;
+	uint32_t  max;
+
+	if (map->data[0] & 0x1) {
+		bitmap_getset(map, &ptr, &max);
+		bitmap_size -= max / 8;
+		bitmap_cnt--;
+		free(ptr);
+	}
+
+}
+
 static int
 bitmap_resize(struct bitmap *map, uint32_t bid)
 {
 	uint64_t *ptr, *new;
-	uint32_t elm, max, newmax;
+	uint32_t elm, size, oldmax, newmax;
 
-	bitmap_getset(map, &ptr, &max);
+	bitmap_getset(map, &ptr, &oldmax);
 
 	/* get new map */
 	newmax = BITMAP_ROUNDUP(bid + 1, BITMAP_ALLOCBITS);
@@ -55,19 +73,21 @@ bitmap_resize(struct bitmap *map, uint32
 		return -1;
 
 	/* copy data over */
-	max /= BITMAP_BITS;
-	for (elm = 0; elm < max; elm++)
+	size = oldmax / BITMAP_BITS;
+	for (elm = 0; elm < size; elm++)
 		new[elm] = ptr[elm];
-	max = newmax / BITMAP_BITS;
-	for ( ; elm < max; elm++)
+	size = newmax / BITMAP_BITS;
+	for ( ; elm < size; elm++)
 		new[elm] = 0;
 
 	/* free old data */
-	if (map->data[0] & 0x1)
-		free(BITMAP_GETPTR(map->data[0]));
+	bitmap_free(map);
 
+	/* set new data */
 	map->data[0] = BITMAP_SETPTR(new);
 	map->data[1] = newmax;
+	bitmap_size += newmax / 8;
+	bitmap_cnt++;
 
 	return 0;
 }
@@ -222,8 +242,6 @@ bitmap_init(struct bitmap *map)
 void
 bitmap_reset(struct bitmap *map)
 {
-	if (map->data[0] & 0x1)
-		free(BITMAP_GETPTR(map->data[0]));
-
+	bitmap_free(map);
 	bitmap_init(map);
 }