After prefix-set and as-set I'm looking at adding roa-set. roa-sets are kind of a mix of a prefix-set and a as-set and therefor this diff extends as-set code to allow for this.
Extend as_set to allow for different sized objects to be added. The only requirement is that the first value of the struct is a 32bit ID which is used in the bsearch. This allows to add more than just as numbers to a set. as_set_match now returns a pointer to this data or NULL if not found. -- :wq Claudio PS: the diff is against /usr/src since it includes diff for bgpctl and regress as well Index: usr.sbin/bgpd/bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.339 diff -u -p -r1.339 bgpd.h --- usr.sbin/bgpd/bgpd.h 10 Sep 2018 11:01:15 -0000 1.339 +++ usr.sbin/bgpd/bgpd.h 13 Sep 2018 09:29:25 -0000 @@ -1171,10 +1171,11 @@ void as_sets_print(struct as_set_head int as_sets_send(struct imsgbuf *, struct as_set_head *); void as_sets_mark_dirty(struct as_set_head *, struct as_set_head *); -struct as_set *as_set_new(const char *, size_t); -int as_set_add(struct as_set *, u_int32_t *, size_t); +struct as_set *as_set_new(const char *, size_t, size_t); +void as_set_free(struct as_set *); +int as_set_add(struct as_set *, void *, size_t); void as_set_prep(struct as_set *); -int as_set_match(const struct as_set *, u_int32_t); +void *as_set_match(const struct as_set *, u_int32_t); int as_set_equal(const struct as_set *, const struct as_set *); int as_set_dirty(const struct as_set *); Index: usr.sbin/bgpd/parse.y =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v retrieving revision 1.350 diff -u -p -r1.350 parse.y --- usr.sbin/bgpd/parse.y 10 Sep 2018 11:09:25 -0000 1.350 +++ usr.sbin/bgpd/parse.y 13 Sep 2018 09:30:54 -0000 @@ -402,15 +403,19 @@ include : INCLUDE STRING { ; as_set : ASSET STRING '{' optnl { - if (new_as_set($2) != 0) + if (new_as_set($2) != 0) { + free($2); YYERROR; + } free($2); } as_set_l optnl '}' { done_as_set(); } | ASSET STRING '{' optnl '}' { - if (new_as_set($2) != 0) + if (new_as_set($2) != 0) { + free($2); YYERROR; + } free($2); } @@ -4186,7 +4183,7 @@ new_as_set(char *name) return -1; } - aset = as_set_new(name, 0); + aset = as_set_new(name, 0, sizeof(u_int32_t)); if (aset == NULL) fatal(NULL); as_sets_insert(conf->as_sets, aset); Index: usr.sbin/bgpd/rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.422 diff -u -p -r1.422 rde.c --- usr.sbin/bgpd/rde.c 9 Sep 2018 15:02:26 -0000 1.422 +++ usr.sbin/bgpd/rde.c 13 Sep 2018 09:29:25 -0000 @@ -908,7 +908,8 @@ rde_dispatch_imsg_parent(struct imsgbuf name = (char *)imsg.data + sizeof(nmemb); if (as_sets_lookup(as_sets_tmp, name) != NULL) fatalx("duplicate as-set %s", name); - last_as_set = as_set_new(name, nmemb); + last_as_set = as_set_new(name, nmemb, + sizeof(u_int32_t)); break; case IMSG_RECONF_AS_SET_ITEMS: nmemb = imsg.hdr.len - IMSG_HEADER_SIZE; Index: usr.sbin/bgpd/rde_sets.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_sets.c,v retrieving revision 1.3 diff -u -p -r1.3 rde_sets.c --- usr.sbin/bgpd/rde_sets.c 10 Sep 2018 11:01:15 -0000 1.3 +++ usr.sbin/bgpd/rde_sets.c 13 Sep 2018 09:29:25 -0000 @@ -29,9 +29,10 @@ struct as_set { char name[SET_NAME_LEN]; - u_int32_t *set; + void *set; SIMPLEQ_ENTRY(as_set) entry; size_t nmemb; + size_t size; size_t max; int dirty; }; @@ -54,12 +55,6 @@ as_sets_lookup(struct as_set_head *as_se return NULL; } -static void -as_set_free(struct as_set *aset) -{ - free(aset->set); - free(aset); -} void as_sets_free(struct as_set_head *as_sets) @@ -92,7 +87,8 @@ as_sets_print(struct as_set_head *as_set printf("\n\t"); len = 8; } - len += printf("%u ", aset->set[i]); + len += printf("%u ", *(u_int32_t *) + ((u_int8_t *)aset->set + i * aset->size)); } printf("\n}\n\n"); } @@ -120,7 +116,8 @@ as_sets_send(struct imsgbuf *ibuf, struc l = (aset->nmemb - i > 1024 ? 1024 : aset->nmemb - i); if (imsg_compose(ibuf, IMSG_RECONF_AS_SET_ITEMS, 0, 0, - -1, aset->set + i, l * sizeof(*aset->set)) == -1) + -1, (u_int8_t *)aset->set + i * aset->size, + l * aset->size) == -1) return -1; } @@ -144,7 +141,7 @@ as_sets_mark_dirty(struct as_set_head *o } struct as_set * -as_set_new(const char *name, size_t nmemb) +as_set_new(const char *name, size_t nmemb, size_t size) { struct as_set *aset; size_t len; @@ -157,10 +154,11 @@ as_set_new(const char *name, size_t nmem assert(len < sizeof(aset->name)); if (nmemb == 0) - nmemb = 16; + nmemb = 4; + aset->size = size; aset->max = nmemb; - aset->set = calloc(nmemb, sizeof(*aset->set)); + aset->set = calloc(nmemb, aset->size); if (aset->set == NULL) { free(aset); return NULL; @@ -169,8 +167,17 @@ as_set_new(const char *name, size_t nmem return aset; } +void +as_set_free(struct as_set *aset) +{ + if (aset == NULL) + return; + free(aset->set); + free(aset); +} + int -as_set_add(struct as_set *aset, u_int32_t *elms, size_t nelms) +as_set_add(struct as_set *aset, void *elms, size_t nelms) { if (aset->max < nelms || aset->max - nelms < aset->nmemb) { u_int32_t *s; @@ -183,14 +190,15 @@ as_set_add(struct as_set *aset, u_int32_ for (new_size = aset->max; new_size < aset->nmemb + nelms; ) new_size += (new_size < 4096 ? new_size : 4096); - s = reallocarray(aset->set, new_size, sizeof(*aset->set)); + s = reallocarray(aset->set, new_size, aset->size); if (s == NULL) return -1; aset->set = s; aset->max = new_size; } - memcpy(aset->set + aset->nmemb, elms, nelms * sizeof(*elms)); + memcpy((u_int8_t *)aset->set + aset->nmemb * aset->size, elms, + nelms * aset->size); aset->nmemb += nelms; return 0; @@ -212,16 +220,17 @@ as_set_cmp(const void *ap, const void *b void as_set_prep(struct as_set *aset) { - qsort(aset->set, aset->nmemb, sizeof(*aset->set), as_set_cmp); + if (aset == NULL) + return; + qsort(aset->set, aset->nmemb, aset->size, as_set_cmp); } -int +void * as_set_match(const struct as_set *a, u_int32_t asnum) { - if (bsearch(&asnum, a->set, a->nmemb, sizeof(asnum), as_set_cmp)) - return 1; - else - return 0; + if (a == NULL) + return NULL; + return bsearch(&asnum, a->set, a->nmemb, a->size, as_set_cmp); } int @@ -229,7 +238,7 @@ as_set_equal(const struct as_set *a, con { if (a->nmemb != b->nmemb) return 0; - if (memcmp(a->set, b->set, a->nmemb * sizeof(*a->set)) != 0) + if (memcmp(a->set, b->set, a->nmemb * a->size) != 0) return 0; return 1; } Index: usr.sbin/bgpd/util.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/util.c,v retrieving revision 1.34 diff -u -p -r1.34 util.c --- usr.sbin/bgpd/util.c 7 Sep 2018 05:43:33 -0000 1.34 +++ usr.sbin/bgpd/util.c 13 Sep 2018 09:29:25 -0000 @@ -320,7 +320,7 @@ as_compare(struct filter_as *f, u_int32_ if (f->flags & AS_FLAG_AS_SET_NAME) /* should not happen */ return (0); if (f->flags & AS_FLAG_AS_SET) - return (as_set_match(f->aset, as)); + return (as_set_match(f->aset, as) != NULL); if (f->flags & AS_FLAG_NEIGHBORAS) match = neighas; Index: usr.sbin/bgpctl/bgpctl.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v retrieving revision 1.215 diff -u -p -r1.215 bgpctl.c --- usr.sbin/bgpctl/bgpctl.c 9 Sep 2018 12:53:41 -0000 1.215 +++ usr.sbin/bgpctl/bgpctl.c 13 Sep 2018 09:33:17 -0000 @@ -2656,8 +2656,8 @@ msg_type(u_int8_t type) return (msgtypenames[type]); } -int +void * as_set_match(const struct as_set *a, u_int32_t asnum) { - return (0); + return (NULL); } Index: regress/usr.sbin/bgpd/unittests/rde_sets_test.c =================================================================== RCS file: /cvs/src/regress/usr.sbin/bgpd/unittests/rde_sets_test.c,v retrieving revision 1.2 diff -u -p -r1.2 rde_sets_test.c --- regress/usr.sbin/bgpd/unittests/rde_sets_test.c 7 Sep 2018 09:31:14 -0000 1.2 +++ regress/usr.sbin/bgpd/unittests/rde_sets_test.c 13 Sep 2018 09:32:41 -0000 @@ -33,7 +33,7 @@ build_set(const char *name, u_int32_t *m { struct as_set *a; - a = as_set_new(name, initial); + a = as_set_new(name, initial, sizeof(*mem)); if (a == NULL) err(1, "as_set_new %s", name); if (as_set_add(a, mem, nmemb) != 0) @@ -46,18 +46,18 @@ build_set(const char *name, u_int32_t *m int main(int argc, char **argv) { - struct as_set *a, *aa, *b, *c; + struct as_set *a, *aa, *b, *c, *empty; size_t i; a = build_set("a", va, sizeof(va) / sizeof(va[0]), sizeof(va) / sizeof(va[0])); - aa = build_set("aa", vaa, sizeof(vaa) / sizeof(vaa[0]), 0); - b = build_set("b", vb, sizeof(vb) / sizeof(vb[0]), 1); - c = build_set("c", vc, sizeof(vc) / sizeof(vc[0]), 1); + empty = build_set("empty", NULL, 0, 0); + if (!as_set_equal(a, a)) + errx(1, "as_set_equal(a, a) non equal"); if (!as_set_equal(a, aa)) errx(1, "as_set_equal(a, aa) non equal"); if (as_set_equal(a, b)) @@ -75,6 +75,17 @@ main(int argc, char **argv) if (as_set_match(c, 7)) errx(1, "as_set_match(c, %u) matched but should not", 7); + if (!as_set_equal(empty, empty)) + errx(1, "as_set_equal(empty, empty) non equal"); + if (as_set_match(empty, 42)) + errx(1, "as_set_match(empty, %u) matched but should not", 42); + + as_set_free(a); + as_set_free(aa); + as_set_free(b); + as_set_free(c); + as_set_free(empty); + printf("OK\n"); return 0; }