This adds the needed bits to send the flowspec rules to the RDE. The RDE just drops them on the ground for now.
-- :wq Claudio Index: bgpd.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.c,v retrieving revision 1.257 diff -u -p -r1.257 bgpd.c --- bgpd.c 14 Feb 2023 15:33:46 -0000 1.257 +++ bgpd.c 18 Apr 2023 15:15:36 -0000 @@ -598,6 +598,7 @@ send_config(struct bgpd_config *conf) struct roa *roa; struct aspa_set *aspa; struct rtr_config *rtr; + struct flowspec_config *f, *nf; reconfpending = 3; /* one per child */ @@ -655,6 +656,26 @@ send_config(struct bgpd_config *conf) /* networks go via kroute to the RDE */ kr_net_reload(conf->default_tableid, 0, &conf->networks); + + /* flowspec goes directly to the RDE, also remove old objects */ + RB_FOREACH_SAFE(f, flowspec_tree, &conf->flowspecs, nf) { + if (f->reconf_action != RECONF_DELETE) { + if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_ADD, 0, 0, -1, + f->flow, FLOWSPEC_SIZE + f->flow->len) == -1) + return (-1); + if (send_filterset(ibuf_rde, &f->attrset) == -1) + return (-1); + if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_DONE, 0, 0, -1, + NULL, 0) == -1) + return (-1); + } else { + if (imsg_compose(ibuf_rde, IMSG_FLOWSPEC_REMOVE, 0, 0, + -1, f->flow, FLOWSPEC_SIZE + f->flow->len) == -1) + return (-1); + RB_REMOVE(flowspec_tree, &conf->flowspecs, f); + flowspec_free(f); + } + } /* prefixsets for filters in the RDE */ while ((ps = SIMPLEQ_FIRST(&conf->prefixsets)) != NULL) { Index: bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.472 diff -u -p -r1.472 bgpd.h --- bgpd.h 18 Apr 2023 12:11:27 -0000 1.472 +++ bgpd.h 18 Apr 2023 15:15:36 -0000 @@ -526,7 +526,7 @@ struct network { struct flowspec { uint16_t len; uint8_t aid; - uint8_t pad; + uint8_t flags; uint8_t data[1]; }; #define FLOWSPEC_SIZE (offsetof(struct flowspec, data)) @@ -613,6 +613,9 @@ enum imsg_type { IMSG_NETWORK_REMOVE, IMSG_NETWORK_FLUSH, IMSG_NETWORK_DONE, + IMSG_FLOWSPEC_ADD, + IMSG_FLOWSPEC_DONE, + IMSG_FLOWSPEC_REMOVE, IMSG_FILTER_SET, IMSG_SOCKET_CONN, IMSG_SOCKET_CONN_CTL, Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.601 diff -u -p -r1.601 rde.c --- rde.c 13 Apr 2023 15:51:16 -0000 1.601 +++ rde.c 18 Apr 2023 15:18:19 -0000 @@ -102,6 +102,10 @@ void network_delete(struct network_con static void network_dump_upcall(struct rib_entry *, void *); static void network_flush_upcall(struct rib_entry *, void *); +void flowspec_add(struct flowspec *, struct filterstate *, + struct filter_set_head *); +void flowspec_delete(struct flowspec *); + void rde_shutdown(void); static int ovs_match(struct prefix *, uint32_t); static int avs_match(struct prefix *, uint32_t); @@ -719,6 +723,7 @@ rde_dispatch_imsg_parent(struct imsgbuf static struct rde_prefixset *last_prefixset; static struct as_set *last_as_set; static struct l3vpn *vpn; + static struct flowspec *curflow; struct imsg imsg; struct mrt xmrt; struct roa roa; @@ -817,6 +822,75 @@ rde_dispatch_imsg_parent(struct imsgbuf TAILQ_INIT(&netconf_p.attrset); network_delete(&netconf_p); break; + case IMSG_FLOWSPEC_ADD: + if (imsg.hdr.len - IMSG_HEADER_SIZE <= FLOWSPEC_SIZE) { + log_warnx("rde_dispatch: wrong imsg len"); + break; + } + if (curflow != NULL) { + log_warnx("rde_dispatch: " + "unexpected flowspec add"); + break; + } + curflow = malloc(imsg.hdr.len - IMSG_HEADER_SIZE); + if (curflow == NULL) + fatal(NULL); + memcpy(curflow, imsg.data, + imsg.hdr.len - IMSG_HEADER_SIZE); + if (curflow->len + FLOWSPEC_SIZE != + imsg.hdr.len - IMSG_HEADER_SIZE) { + free(curflow); + curflow = NULL; + log_warnx("rde_dispatch: wrong flowspec len"); + break; + } + break; + case IMSG_FLOWSPEC_DONE: + if (curflow == NULL) { + log_warnx("rde_dispatch: " + "unexpected flowspec done"); + break; + } + + rde_filterstate_init(&state); + asp = &state.aspath; + asp->aspath = aspath_get(NULL, 0); + asp->origin = ORIGIN_IGP; + asp->flags = F_ATTR_ORIGIN | F_ATTR_ASPATH | + F_ATTR_LOCALPREF | F_PREFIX_ANNOUNCED; + + flowspec_add(curflow, &state, &parent_set); + rde_filterstate_clean(&state); + filterset_free(&parent_set); + free(curflow); + curflow = NULL; + break; + case IMSG_FLOWSPEC_REMOVE: + if (imsg.hdr.len - IMSG_HEADER_SIZE <= FLOWSPEC_SIZE) { + log_warnx("rde_dispatch: wrong imsg len"); + break; + } + if (curflow != NULL) { + log_warnx("rde_dispatch: " + "unexpected flowspec remove"); + break; + } + curflow = malloc(imsg.hdr.len - IMSG_HEADER_SIZE); + if (curflow == NULL) + fatal(NULL); + memcpy(curflow, imsg.data, + imsg.hdr.len - IMSG_HEADER_SIZE); + if (curflow->len + FLOWSPEC_SIZE != + imsg.hdr.len - IMSG_HEADER_SIZE) { + free(curflow); + curflow = NULL; + log_warnx("rde_dispatch: wrong flowspec len"); + break; + } + flowspec_delete(curflow); + free(curflow); + curflow = NULL; + break; case IMSG_RECONF_CONF: if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(struct bgpd_config)) @@ -4487,6 +4561,20 @@ network_flush_upcall(struct rib_entry *r if (prefix_withdraw(rib_byid(RIB_ADJ_IN), peerself, 0, &addr, prefixlen) == 1) peerself->stats.prefix_cnt--; +} + +/* + * flowspec announcement stuff + */ +void +flowspec_add(struct flowspec *f, struct filterstate *state, + struct filter_set_head *attrset) +{ +} + +void +flowspec_delete(struct flowspec *f) +{ } /* clean up */