On Wed, Sep 19, 2018 at 08:50:41PM +0200, Denis Fondras wrote: > On Wed, Sep 19, 2018 at 10:15:22AM +0200, Claudio Jeker wrote: > > Switch the prefixset simpleq into an RB trie. This allows to spot > > duplicates in the parser and is a requirement for roa-sets where > > conflicts need to be specially handled. > > > > OK? > > I don't know if the case is relevant but > > prefix-set plop { > 192.0.2.0/24 prefixlen 25 > 192.0.2.0/25 > 192.0.2.128/25 > } > > do not yield duplicate.
They are no real duplicates. 192.0.2.0/24 prefixlen 25 is different from 192.0.2.0/25 these are different nodes in the tree even though the cover the same address range in the end. Duplicates will only trigger on exactly duplicate lines (same prefix and prefixlen bits). Hope this makes sense. -- :wq Claudio > > -- > > :wq Claudio > > > > Index: bgpd.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v > > retrieving revision 1.198 > > diff -u -p -r1.198 bgpd.c > > --- bgpd.c 9 Sep 2018 11:00:51 -0000 1.198 > > +++ bgpd.c 19 Sep 2018 06:34:11 -0000 > > @@ -437,7 +437,7 @@ reconfigure(char *conffile, struct bgpd_ > > struct rde_rib *rr; > > struct rdomain *rd; > > struct prefixset *ps; > > - struct prefixset_item *psi; > > + struct prefixset_item *psi, *npsi; > > > > if (reconfpending) { > > log_info("previous reload still running"); > > @@ -510,8 +510,8 @@ reconfigure(char *conffile, struct bgpd_ > > if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSET, 0, 0, -1, > > ps->name, sizeof(ps->name)) == -1) > > return (-1); > > - while ((psi = SIMPLEQ_FIRST(&ps->psitems)) != NULL) { > > - SIMPLEQ_REMOVE_HEAD(&ps->psitems, entry); > > + RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) { > > + RB_REMOVE(prefixset_tree, &ps->psitems, psi); > > if (imsg_compose(ibuf_rde, IMSG_RECONF_PREFIXSETITEM, 0, > > 0, -1, psi, sizeof(*psi)) == -1) > > return (-1); > > Index: bgpd.h > > =================================================================== > > RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v > > retrieving revision 1.340 > > diff -u -p -r1.340 bgpd.h > > --- bgpd.h 14 Sep 2018 10:22:11 -0000 1.340 > > +++ bgpd.h 19 Sep 2018 06:32:47 -0000 > > @@ -953,15 +953,15 @@ struct filter_set { > > }; > > > > struct prefixset_item { > > - struct filter_prefix p; > > - SIMPLEQ_ENTRY(prefixset_item) entry; > > + struct filter_prefix p; > > + RB_ENTRY(prefixset_item) entry; > > }; > > -SIMPLEQ_HEAD(prefixset_items_h, prefixset_item); > > +RB_HEAD(prefixset_tree, prefixset_item); > > > > struct prefixset { > > int sflags; > > char name[SET_NAME_LEN]; > > - struct prefixset_items_h psitems; > > + struct prefixset_tree psitems; > > SIMPLEQ_ENTRY(prefixset) entry; > > }; > > > > @@ -1085,6 +1085,8 @@ void filterlist_free(struct filter_head > > int host(const char *, struct bgpd_addr *, u_int8_t *); > > void copy_filterset(struct filter_set_head *, struct filter_set_head > > *); > > void expand_networks(struct bgpd_config *); > > +int prefixset_cmp(struct prefixset_item *, struct prefixset_item *); > > +RB_PROTOTYPE(prefixset_tree, prefixset_item, entry, prefixset_cmp); > > > > /* kroute.c */ > > int kr_init(void); > > Index: config.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/bgpd/config.c,v > > retrieving revision 1.73 > > diff -u -p -r1.73 config.c > > --- config.c 9 Sep 2018 11:00:51 -0000 1.73 > > +++ config.c 19 Sep 2018 06:35:49 -0000 > > @@ -120,16 +120,15 @@ void > > free_prefixsets(struct prefixset_head *psh) > > { > > struct prefixset *ps; > > - struct prefixset_item *psi; > > + struct prefixset_item *psi, *npsi; > > > > if (psh == NULL) > > return; > > > > while (!SIMPLEQ_EMPTY(psh)) { > > ps = SIMPLEQ_FIRST(psh); > > - while (!SIMPLEQ_EMPTY(&ps->psitems)) { > > - psi = SIMPLEQ_FIRST(&ps->psitems); > > - SIMPLEQ_REMOVE_HEAD(&ps->psitems, entry); > > + RB_FOREACH_SAFE(psi, prefixset_tree, &ps->psitems, npsi) { > > + RB_REMOVE(prefixset_tree, &ps->psitems, psi); > > free(psi); > > } > > SIMPLEQ_REMOVE_HEAD(psh, entry); > > @@ -529,7 +528,7 @@ expand_networks(struct bgpd_config *c) > > == NULL) > > fatal("%s: prefixset %s not found", __func__, > > n->net.psname); > > - SIMPLEQ_FOREACH(psi, &ps->psitems, entry) { > > + RB_FOREACH(psi, prefixset_tree, &ps->psitems) { > > if ((m = calloc(1, sizeof(struct network))) > > == NULL) > > fatal(NULL); > > @@ -546,3 +545,48 @@ expand_networks(struct bgpd_config *c) > > } > > } > > } > > + > > +int > > +prefixset_cmp(struct prefixset_item *a, struct prefixset_item *b) > > +{ > > + int i; > > + > > + if (a->p.addr.aid < b->p.addr.aid) > > + return (-1); > > + if (a->p.addr.aid > b->p.addr.aid) > > + return (1); > > + > > + switch (a->p.addr.aid) { > > + case AID_INET: > > + if (ntohl(a->p.addr.v4.s_addr) < ntohl(b->p.addr.v4.s_addr)) > > + return (-1); > > + if (ntohl(a->p.addr.v4.s_addr) > ntohl(b->p.addr.v4.s_addr)) > > + return (1); > > + break; > > + case AID_INET6: > > + i = memcmp(&a->p.addr.v6, &b->p.addr.v6, > > + sizeof(struct in6_addr)); > > + if (i > 0) > > + return (1); > > + if (i < 0) > > + return (-1); > > + break; > > + default: > > + fatalx("%s: unknown af", __func__); > > + } > > + if (a->p.len < b->p.len) > > + return (-1); > > + if (a->p.len > b->p.len) > > + return (1); > > + if (a->p.len_min < b->p.len_min) > > + return (-1); > > + if (a->p.len_min > b->p.len_min) > > + return (1); > > + if (a->p.len_max < b->p.len_max) > > + return (-1); > > + if (a->p.len_max > b->p.len_max) > > + return (1); > > + return (0); > > +} > > + > > +RB_GENERATE(prefixset_tree, prefixset_item, entry, prefixset_cmp); > > Index: parse.y > > =================================================================== > > RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v > > retrieving revision 1.353 > > diff -u -p -r1.353 parse.y > > --- parse.y 14 Sep 2018 10:22:11 -0000 1.353 > > +++ parse.y 19 Sep 2018 06:35:02 -0000 > > @@ -443,14 +443,37 @@ prefixset : PREFIXSET STRING '{' optnl > > } > > > > prefixset_l : prefixset_item { > > - SIMPLEQ_INSERT_TAIL(&curpset->psitems, $1, entry); > > + struct prefixset_item *psi; > > + psi = RB_INSERT(prefixset_tree, &curpset->psitems, $1); > > + if (psi != NULL) { > > + if (cmd_opts & BGPD_OPT_VERBOSE2) > > + log_warnx("warning: duplicate entry in " > > + "prefixset \"%s\" for %s/%u", > > + curpset->name, > > + log_addr(&$1->p.addr), $1->p.len); > > + free($1); > > + } > > } > > | prefixset_l comma prefixset_item { > > - SIMPLEQ_INSERT_TAIL(&curpset->psitems, $3, entry); > > + struct prefixset_item *psi; > > + psi = RB_INSERT(prefixset_tree, &curpset->psitems, $3); > > + if (psi != NULL) { > > + if (cmd_opts & BGPD_OPT_VERBOSE2) > > + log_warnx("warning: duplicate entry in " > > + "prefixset \"%s\" for %s/%u", > > + curpset->name, > > + log_addr(&$3->p.addr), $3->p.len); > > + free($3); > > + } > > } > > ; > > > > prefixset_item : prefix prefixlenop { > > + if ($2.op != OP_NONE && $2.op != OP_RANGE) { > > + yyerror("unsupported prefixlen operation in " > > + "prefix-set"); > > + YYERROR; > > + } > > if (($$ = calloc(1, sizeof(*$$))) == NULL) > > fatal(NULL); > > memcpy(&$$->p.addr, &$1.prefix, sizeof($$->p.addr)); > > @@ -4223,6 +4246,6 @@ new_prefix_set(char *name) > > name, sizeof(curpset->name) - 1); > > return -1; > > } > > - SIMPLEQ_INIT(&curpset->psitems); > > + RB_INIT(&curpset->psitems); > > return 0; > > } > > Index: printconf.c > > =================================================================== > > RCS file: /cvs/src/usr.sbin/bgpd/printconf.c,v > > retrieving revision 1.119 > > diff -u -p -r1.119 printconf.c > > --- printconf.c 13 Sep 2018 11:25:41 -0000 1.119 > > +++ printconf.c 19 Sep 2018 06:32:47 -0000 > > @@ -451,7 +451,7 @@ print_prefixsets(struct prefixset_head * > > SIMPLEQ_FOREACH(ps, psh, entry) { > > int count = 0; > > printf("prefix-set \"%s\" {", ps->name); > > - SIMPLEQ_FOREACH(psi, &ps->psitems, entry) { > > + RB_FOREACH(psi, prefixset_tree, &ps->psitems) { > > if (count++ % 2 == 0) > > printf("\n\t"); > > else > > >