Download raw body.
bgpd: introduce bin_of from malloc to size various things
Another diff from my bigger adj-rib-out rewrite.
This introduces a new set of functions to size various dynamic arrays in
bgpd. For now attributes and communities. I looked at sets but that code
needs some rework to better fit into this.
Happy to repaint any bikesheds in this madness :)
--
:wq Claudio
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
diff -u -p -r1.526 bgpd.h
--- bgpd.h 11 Dec 2025 12:18:27 -0000 1.526
+++ bgpd.h 16 Dec 2025 14:33:41 -0000
@@ -1674,6 +1674,9 @@ struct sockaddr *addr2sa(const struct bg
void sa2addr(struct sockaddr *, struct bgpd_addr *, uint16_t *);
const char *get_baudrate(unsigned long long, char *);
+unsigned int bin_of_attrs(unsigned int);
+unsigned int bin_of_communities(unsigned int);
+
/* flowspec.c */
int flowspec_valid(const uint8_t *, int, int);
int flowspec_cmp(const uint8_t *, int, const uint8_t *, int, int);
Index: rde_attr.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_attr.c,v
diff -u -p -r1.139 rde_attr.c
--- rde_attr.c 4 Nov 2025 14:43:22 -0000 1.139
+++ rde_attr.c 16 Dec 2025 13:41:48 -0000
@@ -97,7 +97,7 @@ attr_optadd(struct rde_aspath *asp, uint
{
uint8_t l;
struct attr *a, *t;
- void *p;
+ struct attr **p;
uint64_t h;
/* attribute allowed only once */
@@ -136,14 +136,15 @@ attr_optadd(struct rde_aspath *asp, uint
if (asp->others_len == UCHAR_MAX)
fatalx("attr_optadd: attribute overflow");
- asp->others_len++;
+ l = bin_of_attrs(asp->others_len + 1);
if ((p = reallocarray(asp->others,
asp->others_len, sizeof(struct attr *))) == NULL)
fatal("%s", __func__);
+ memset(&p[asp->others_len], 0, (l - asp->others_len) * sizeof(*p));
asp->others = p;
+ asp->others[asp->others_len] = a;
+ asp->others_len = l;
- /* l stores the size of others before resize */
- asp->others[l] = a;
return (0);
}
Index: rde_community.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_community.c,v
diff -u -p -r1.20 rde_community.c
--- rde_community.c 16 Dec 2025 12:08:11 -0000 1.20
+++ rde_community.c 16 Dec 2025 13:27:59 -0000
@@ -225,12 +225,13 @@ insert_community(struct rde_community *c
if (comm->nentries + 1 > comm->size) {
struct community *new;
- int newsize = comm->size + 8;
+ int newsize = bin_of_communities(comm->nentries + 1);
if ((new = reallocarray(comm->communities, newsize,
sizeof(*new))) == NULL)
fatal(__func__);
- memset(&new[comm->size], 0, sizeof(*new) * 8);
+ memset(&new[comm->size], 0,
+ sizeof(*new) * (newsize - comm->size));
comm->communities = new;
comm->size = newsize;
}
Index: util.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
diff -u -p -r1.96 util.c
--- util.c 23 Oct 2025 18:55:30 -0000 1.96
+++ util.c 16 Dec 2025 14:37:53 -0000
@@ -22,6 +22,7 @@
#include <arpa/inet.h>
#include <endian.h>
#include <errno.h>
+#include <limits.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
@@ -1295,3 +1296,45 @@ get_baudrate(unsigned long long baudrate
return (bbuf);
}
+
+/* internal functions needed for bucket sizing, stolen from omalloc.c */
+
+/* using built-in function version */
+__attribute__((const)) static inline unsigned int
+lb(unsigned int x)
+{
+ /* I need an extension just for integer-length (: */
+ return (sizeof(x) * CHAR_BIT - 1) - __builtin_clz(x);
+}
+
+/* https://pvk.ca/Blog/2015/06/27/linear-log-bucketing-fast-versatile-simple/
+ via Tony Finch */
+static inline unsigned int
+bin_of(unsigned int size, unsigned int linear, unsigned int subbin)
+{
+ unsigned int mask, rounded, rounded_size;
+ unsigned int n_bits, shift;
+
+ n_bits = lb(size | (1U << linear));
+ shift = n_bits - subbin;
+ mask = (1U << shift) - 1;
+ rounded = size + mask; /* XXX: overflow. */
+
+ rounded_size = rounded & ~mask;
+ return rounded_size;
+}
+
+unsigned int
+bin_of_attrs(unsigned int count)
+{
+ /* 4, 8, 12, ... 60, 64, 72, 80, ... */
+ return bin_of(count, 5, 3);
+}
+
+unsigned int
+bin_of_communities(unsigned int count)
+{
+ /* 8, 16, 24, ... 56, 64, 80, 96, ... */
+ return bin_of(count, 5, 2);
+}
+
bgpd: introduce bin_of from malloc to size various things