reads ok, benno@
Claudio Jeker([email protected]) on 2020.12.29 10:33:53 +0100:
> On Thu, Dec 10, 2020 at 02:42:49PM +0100, Claudio Jeker wrote:
> > On Thu, Dec 03, 2020 at 10:59:29PM +0100, Claudio Jeker wrote:
> > > The use of roa-set, prefix-set and as-set is fairly common in bgpd.
> > > Still sometimes it is not exactly clear how old the data in those tables
> > > is. This diff is a first step at inproving inspection by adding
> > > bgpctl show sets
> > >
> > > Sample output is:
> > > Type Name #IPv4 #Ipv6 #ASnum Last
> > > Change
> > > ROA RPKI ROA 158810 26257 -
> > > 00:00:07
> > > ASNUM asns_AS15600 - - 26
> > > 01:19:10
> > > PREFIX p4_AS21040 8 0 -
> > > 01:19:10
> > >
> > > I just did a bgpctl reload with a new roa table (generated by rpki-client)
> > > but the as-set and prefix-set did not change during this reload.
> > > The output also includes the number of entries in the tables but in the
> > > case of roa-set the number of unique prefixes is counted. So the number is
> > > a bit under the count from rpki-client because e.g.
> > > 1.32.219.0/24 source-as 4842
> > > 1.32.219.0/24 source-as 138570
> > > are counted as 1 right now (instead of 2 prefixes).
> > >
> > > More statistics can be added if their calculation is easy.
> >
> > Am I the only one interested in knowing how old my set data is?
>
> Any feedback on this? This should help people to detect issues where
> rpki-client or bgpq3 fail to produce updates.
>
> --
> :wq Claudio
>
> PS: apply diff in /usr/src/usr.sbin
>
> Index: bgpctl/bgpctl.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
> retrieving revision 1.263
> diff -u -p -r1.263 bgpctl.c
> --- bgpctl/bgpctl.c 10 May 2020 13:38:46 -0000 1.263
> +++ bgpctl/bgpctl.c 3 Dec 2020 20:17:14 -0000
> @@ -213,6 +213,9 @@ main(int argc, char *argv[])
> case SHOW_INTERFACE:
> imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, NULL, 0);
> break;
> + case SHOW_SET:
> + imsg_compose(ibuf, IMSG_CTL_SHOW_SET, 0, 0, -1, NULL, 0);
> + break;
> case SHOW_NEIGHBOR:
> case SHOW_NEIGHBOR_TIMERS:
> case SHOW_NEIGHBOR_TERSE:
> @@ -393,6 +396,7 @@ show(struct imsg *imsg, struct parse_res
> struct ctl_timer *t;
> struct ctl_show_interface *iface;
> struct ctl_show_nexthop *nh;
> + struct ctl_show_set *set;
> struct kroute_full *kf;
> struct ktable *kt;
> struct ctl_show_rib rib;
> @@ -466,6 +470,10 @@ show(struct imsg *imsg, struct parse_res
> memcpy(&hash, imsg->data, sizeof(hash));
> output->rib_hash(&hash);
> break;
> + case IMSG_CTL_SHOW_SET:
> + set = imsg->data;
> + output->set(set);
> + break;
> case IMSG_CTL_RESULT:
> if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(rescode)) {
> warnx("got IMSG_CTL_RESULT with wrong len");
> @@ -974,6 +982,23 @@ fmt_ext_community(u_int8_t *data)
> log_ext_subtype(type, subtype),
> (unsigned long long)be64toh(ext));
> return buf;
> + }
> +}
> +
> +const char *
> +fmt_set_type(struct ctl_show_set *set)
> +{
> + switch (set->type) {
> + case ROA_SET:
> + return "ROA";
> + case PREFIX_SET:
> + return "PREFIX";
> + case ORIGIN_SET:
> + return "ORIGIN";
> + case ASNUM_SET:
> + return "ASNUM";
> + default:
> + return "BULA";
> }
> }
>
> Index: bgpctl/bgpctl.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.h,v
> retrieving revision 1.7
> diff -u -p -r1.7 bgpctl.h
> --- bgpctl/bgpctl.h 2 May 2020 14:33:33 -0000 1.7
> +++ bgpctl/bgpctl.h 3 Dec 2020 20:12:34 -0000
> @@ -30,6 +30,7 @@ struct output {
> struct parse_result *);
> void (*rib_hash)(struct rde_hashstats *);
> void (*rib_mem)(struct rde_memstats *);
> + void (*set)(struct ctl_show_set *);
> void (*result)(u_int);
> void (*tail)(void);
> };
> @@ -53,3 +54,4 @@ const char *fmt_attr(u_int8_t, int);
> const char *fmt_community(u_int16_t, u_int16_t);
> const char *fmt_large_community(u_int32_t, u_int32_t, u_int32_t);
> const char *fmt_ext_community(u_int8_t *);
> +const char *fmt_set_type(struct ctl_show_set *);
> Index: bgpctl/output.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/output.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 output.c
> --- bgpctl/output.c 21 Oct 2020 06:52:45 -0000 1.10
> +++ bgpctl/output.c 3 Dec 2020 20:53:36 -0000
> @@ -77,6 +77,10 @@ show_head(struct parse_result *res)
> "flags", "ovs", "destination", "gateway", "lpref", "med",
> "aspath origin");
> break;
> + case SHOW_SET:
> + printf("%-6s %-34s %7s %7s %6s %11s\n", "Type", "Name",
> + "#IPv4", "#IPv6", "#ASnum", "Last Change");
> + break;
> case NETWORK_SHOW:
> printf("flags: S = Static\n");
> printf("flags prio destination gateway\n");
> @@ -958,6 +962,22 @@ show_rib_hash(struct rde_hashstats *hash
> }
>
> static void
> +show_rib_set(struct ctl_show_set *set)
> +{
> + char buf[64];
> +
> + if (set->type == ASNUM_SET)
> + snprintf(buf, sizeof(buf), "%7s %7s %6zu",
> + "-", "-", set->as_cnt);
> + else
> + snprintf(buf, sizeof(buf), "%7zu %7zu %6s",
> + set->v4_cnt, set->v6_cnt, "-");
> +
> + printf("%-6s %-34s %s %11s\n", fmt_set_type(set), set->name,
> + buf, fmt_monotime(set->lastchange));
> +}
> +
> +static void
> show_result(u_int rescode)
> {
> if (rescode == 0)
> @@ -988,6 +1008,7 @@ const struct output show_output = {
> .rib = show_rib,
> .rib_mem = show_rib_mem,
> .rib_hash = show_rib_hash,
> + .set = show_rib_set,
> .result = show_result,
> .tail = show_tail
> };
> Index: bgpctl/output_json.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/output_json.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 output_json.c
> --- bgpctl/output_json.c 21 Oct 2020 06:52:45 -0000 1.4
> +++ bgpctl/output_json.c 3 Dec 2020 20:16:25 -0000
> @@ -919,6 +919,24 @@ json_rib_hash(struct rde_hashstats *hash
> }
>
> static void
> +json_rib_set(struct ctl_show_set *set)
> +{
> + json_do_array("sets");
> +
> + json_do_object("set");
> + json_do_printf("name", "%s", set->name);
> + json_do_printf("type", "%s", fmt_set_type(set));
> + json_do_printf("last_change", "%s", fmt_monotime(set->lastchange));
> + if (set->type == ASNUM_SET) {
> + json_do_uint("num_ASnum", set->as_cnt);
> + } else {
> + json_do_uint("num_IPv4", set->v4_cnt);
> + json_do_uint("num_IPv6", set->v6_cnt);
> + }
> + json_do_end();
> +}
> +
> +static void
> json_result(u_int rescode)
> {
> if (rescode == 0)
> @@ -952,6 +970,7 @@ const struct output json_output = {
> .rib = json_rib,
> .rib_mem = json_rib_mem,
> .rib_hash = json_rib_hash,
> + .set = json_rib_set,
> .result = json_result,
> .tail = json_tail
> };
> Index: bgpctl/parser.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
> retrieving revision 1.104
> diff -u -p -r1.104 parser.c
> --- bgpctl/parser.c 12 May 2020 13:26:02 -0000 1.104
> +++ bgpctl/parser.c 3 Dec 2020 16:52:10 -0000
> @@ -136,6 +136,7 @@ static const struct token t_show[] = {
> { KEYWORD, "tables", SHOW_FIB_TABLES, NULL},
> { KEYWORD, "ip", NONE, t_show_ip},
> { KEYWORD, "summary", SHOW_SUMMARY, t_show_summary},
> + { KEYWORD, "sets", SHOW_SET, NULL},
> { KEYWORD, "mrt", SHOW_MRT, t_show_mrt},
> { ENDTOKEN, "", NONE, NULL}
> };
> Index: bgpctl/parser.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpctl/parser.h,v
> retrieving revision 1.38
> diff -u -p -r1.38 parser.h
> --- bgpctl/parser.h 10 May 2020 13:38:46 -0000 1.38
> +++ bgpctl/parser.h 3 Dec 2020 16:52:22 -0000
> @@ -32,6 +32,7 @@ enum actions {
> SHOW_FIB_TABLES,
> SHOW_RIB,
> SHOW_MRT,
> + SHOW_SET,
> SHOW_RIB_MEM,
> SHOW_NEXTHOP,
> SHOW_INTERFACE,
> Index: bgpd/bgpd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
> retrieving revision 1.406
> diff -u -p -r1.406 bgpd.h
> --- bgpd/bgpd.h 23 Dec 2020 13:20:47 -0000 1.406
> +++ bgpd/bgpd.h 23 Dec 2020 14:20:47 -0000
> @@ -254,12 +254,15 @@ struct trie_head {
> struct tentry_v6 *root_v6;
> int match_default_v4;
> int match_default_v6;
> + size_t v4_cnt;
> + size_t v6_cnt;
> };
>
> struct rde_prefixset {
> char name[SET_NAME_LEN];
> struct trie_head th;
> SIMPLEQ_ENTRY(rde_prefixset) entry;
> + time_t lastchange;
> int dirty;
> };
> SIMPLEQ_HEAD(rde_prefixset_head, rde_prefixset);
> @@ -465,6 +468,7 @@ enum imsg_type {
> IMSG_CTL_SHOW_TIMER,
> IMSG_CTL_LOG_VERBOSE,
> IMSG_CTL_SHOW_FIB_TABLES,
> + IMSG_CTL_SHOW_SET,
> IMSG_CTL_TERMINATE,
> IMSG_NETWORK_ADD,
> IMSG_NETWORK_ASPATH,
> @@ -696,6 +700,20 @@ struct ctl_show_nexthop {
> u_int8_t krvalid;
> };
>
> +struct ctl_show_set {
> + char name[SET_NAME_LEN];
> + time_t lastchange;
> + size_t v4_cnt;
> + size_t v6_cnt;
> + size_t as_cnt;
> + enum {
> + ASNUM_SET,
> + PREFIX_SET,
> + ORIGIN_SET,
> + ROA_SET,
> + } type;
> +};
> +
> struct ctl_neighbor {
> struct bgpd_addr addr;
> char descr[PEER_DESCR_LEN];
> @@ -1049,6 +1067,7 @@ struct as_set {
> char name[SET_NAME_LEN];
> SIMPLEQ_ENTRY(as_set) entry;
> struct set_table *set;
> + time_t lastchange;
> int dirty;
> };
>
> @@ -1283,6 +1302,7 @@ void set_prep(struct set_table *);
> void *set_match(const struct set_table *, u_int32_t);
> int set_equal(const struct set_table *,
> const struct set_table *);
> +size_t set_nmemb(const struct set_table *);
>
> /* rde_trie.c */
> int trie_add(struct trie_head *, struct bgpd_addr *, u_int8_t, u_int8_t,
> Index: bgpd/control.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/control.c,v
> retrieving revision 1.102
> diff -u -p -r1.102 control.c
> --- bgpd/control.c 11 Dec 2020 12:00:01 -0000 1.102
> +++ bgpd/control.c 13 Dec 2020 14:12:20 -0000
> @@ -280,6 +280,7 @@ control_dispatch_msg(struct pollfd *pfd,
> case IMSG_CTL_SHOW_NETWORK:
> case IMSG_CTL_SHOW_RIB:
> case IMSG_CTL_SHOW_RIB_PREFIX:
> + case IMSG_CTL_SHOW_SET:
> break;
> default:
> /* clear imsg type to prevent processing */
> @@ -498,6 +499,7 @@ control_dispatch_msg(struct pollfd *pfd,
> c->terminate = 1;
> /* FALLTHROUGH */
> case IMSG_CTL_SHOW_RIB_MEM:
> + case IMSG_CTL_SHOW_SET:
> c->ibuf.pid = imsg.hdr.pid;
> imsg_ctl_rde(imsg.hdr.type, imsg.hdr.pid,
> imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
> Index: bgpd/rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
> retrieving revision 1.507
> diff -u -p -r1.507 rde.c
> --- bgpd/rde.c 4 Dec 2020 11:57:13 -0000 1.507
> +++ bgpd/rde.c 7 Dec 2020 14:14:39 -0000
> @@ -345,12 +345,15 @@ rde_dispatch_imsg_session(struct imsgbuf
> struct imsg imsg;
> struct peer p;
> struct peer_config pconf;
> + struct ctl_show_set cset;
> struct ctl_show_rib csr;
> struct ctl_show_rib_request req;
> struct rde_peer *peer;
> struct rde_aspath *asp;
> struct rde_hashstats rdehash;
> struct filter_set *s;
> + struct as_set *aset;
> + struct rde_prefixset *pset;
> u_int8_t *asdata;
> ssize_t n;
> size_t aslen;
> @@ -572,6 +575,53 @@ badnetdel:
> imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, imsg.hdr.pid,
> -1, NULL, 0);
> break;
> + case IMSG_CTL_SHOW_SET:
> + /* first roa set */
> + pset = &conf->rde_roa;
> + memset(&cset, 0, sizeof(cset));
> + cset.type = ROA_SET;
> + strlcpy(cset.name, "RPKI ROA", sizeof(cset.name));
> + cset.lastchange = pset->lastchange;
> + cset.v4_cnt = pset->th.v4_cnt;
> + cset.v6_cnt = pset->th.v6_cnt;
> + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_SET, 0,
> + imsg.hdr.pid, -1, &cset, sizeof(cset));
> +
> + SIMPLEQ_FOREACH(aset, &conf->as_sets, entry) {
> + memset(&cset, 0, sizeof(cset));
> + cset.type = ASNUM_SET;
> + strlcpy(cset.name, aset->name,
> + sizeof(cset.name));
> + cset.lastchange = aset->lastchange;
> + cset.as_cnt = set_nmemb(aset->set);
> + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_SET, 0,
> + imsg.hdr.pid, -1, &cset, sizeof(cset));
> + }
> + SIMPLEQ_FOREACH(pset, &conf->rde_prefixsets, entry) {
> + memset(&cset, 0, sizeof(cset));
> + cset.type = PREFIX_SET;
> + strlcpy(cset.name, pset->name,
> + sizeof(cset.name));
> + cset.lastchange = pset->lastchange;
> + cset.v4_cnt = pset->th.v4_cnt;
> + cset.v6_cnt = pset->th.v6_cnt;
> + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_SET, 0,
> + imsg.hdr.pid, -1, &cset, sizeof(cset));
> + }
> + SIMPLEQ_FOREACH(pset, &conf->rde_originsets, entry) {
> + memset(&cset, 0, sizeof(cset));
> + cset.type = ORIGIN_SET;
> + strlcpy(cset.name, pset->name,
> + sizeof(cset.name));
> + cset.lastchange = pset->lastchange;
> + cset.v4_cnt = pset->th.v4_cnt;
> + cset.v6_cnt = pset->th.v6_cnt;
> + imsg_compose(ibuf_se_ctl, IMSG_CTL_SHOW_SET, 0,
> + imsg.hdr.pid, -1, &cset, sizeof(cset));
> + }
> + imsg_compose(ibuf_se_ctl, IMSG_CTL_END, 0, imsg.hdr.pid,
> + -1, NULL, 0);
> + break;
> case IMSG_CTL_LOG_VERBOSE:
> /* already checked by SE */
> memcpy(&verbose, imsg.data, sizeof(verbose));
> @@ -3115,6 +3165,7 @@ rde_reload_done(void)
> SIMPLEQ_CONCAT(&conf->as_sets, &nconf->as_sets);
>
> conf->rde_roa = nconf->rde_roa;
> + conf->rde_roa.lastchange = roa_old.lastchange;
> memset(&nconf->rde_roa, 0, sizeof(nconf->rde_roa));
>
> /* apply new set of l3vpn, sync will be done later */
> @@ -3138,8 +3189,10 @@ rde_reload_done(void)
> if (trie_equal(&conf->rde_roa.th, &roa_old.th) == 0) {
> log_debug("roa change: reloading Adj-RIB-In");
> conf->rde_roa.dirty = 1;
> + conf->rde_roa.lastchange = getmonotime();
> reload++; /* run softreconf in */
> }
> +
> trie_free(&roa_old.th); /* old roa no longer needed */
>
> rde_mark_prefixsets_dirty(&prefixsets_old, &conf->rde_prefixsets);
> @@ -3870,9 +3923,13 @@ rde_mark_prefixsets_dirty(struct rde_pre
> if ((psold == NULL) ||
> (old = rde_find_prefixset(new->name, psold)) == NULL) {
> new->dirty = 1;
> + new->lastchange = getmonotime();
> } else {
> - if (trie_equal(&new->th, &old->th) == 0)
> + if (trie_equal(&new->th, &old->th) == 0) {
> new->dirty = 1;
> + new->lastchange = getmonotime();
> + } else
> + new->lastchange = old->lastchange;
> }
> }
> }
> Index: bgpd/rde_filter.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_filter.c,v
> retrieving revision 1.125
> diff -u -p -r1.125 rde_filter.c
> --- bgpd/rde_filter.c 3 Dec 2020 11:53:34 -0000 1.125
> +++ bgpd/rde_filter.c 3 Dec 2020 11:58:58 -0000
> @@ -55,8 +55,8 @@ rde_apply_set(struct filter_set_head *sh
> state->aspath.lpref +=
> set->action.relative;
> } else {
> - if ((u_int32_t)-set->action.relative >
> - state->aspath.lpref)
> + if (state->aspath.lpref <
> + 0U - set->action.relative)
> state->aspath.lpref = 0;
> else
> state->aspath.lpref +=
> @@ -77,8 +77,8 @@ rde_apply_set(struct filter_set_head *sh
> state->aspath.med +=
> set->action.relative;
> } else {
> - if ((u_int32_t)-set->action.relative >
> - state->aspath.med)
> + if (state->aspath.med <
> + 0U - set->action.relative)
> state->aspath.med = 0;
> else
> state->aspath.med +=
> @@ -97,8 +97,8 @@ rde_apply_set(struct filter_set_head *sh
> state->aspath.weight +=
> set->action.relative;
> } else {
> - if ((u_int32_t)-set->action.relative >
> - state->aspath.weight)
> + if (state->aspath.weight <
> + 0U - set->action.relative)
> state->aspath.weight = 0;
> else
> state->aspath.weight +=
> Index: bgpd/rde_sets.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_sets.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 rde_sets.c
> --- bgpd/rde_sets.c 5 Aug 2019 08:46:55 -0000 1.9
> +++ bgpd/rde_sets.c 3 Dec 2020 16:36:15 -0000
> @@ -93,8 +93,11 @@ as_sets_mark_dirty(struct as_set_head *o
>
> SIMPLEQ_FOREACH(n, new, entry) {
> if (old == NULL || (o = as_sets_lookup(old, n->name)) == NULL ||
> - !set_equal(n->set, o->set))
> + !set_equal(n->set, o->set)) {
> n->dirty = 1;
> + n->lastchange = getmonotime();
> + } else
> + n->lastchange = o->lastchange;
> }
> }
>
> @@ -223,4 +226,10 @@ set_equal(const struct set_table *a, con
> if (memcmp(a->set, b->set, a->nmemb * a->size) != 0)
> return 0;
> return 1;
> +}
> +
> +size_t
> +set_nmemb(const struct set_table *set)
> +{
> + return set->nmemb;
> }
> Index: bgpd/rde_trie.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_trie.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 rde_trie.c
> --- bgpd/rde_trie.c 26 Oct 2018 16:53:55 -0000 1.10
> +++ bgpd/rde_trie.c 3 Dec 2020 15:25:38 -0000
> @@ -189,6 +189,8 @@ trie_add_v4(struct trie_head *th, struct
>
> if (n->plen == plen) {
> /* matching node, adjust */
> + if (n->node == 0)
> + th->v4_cnt++;
> n->node = 1;
> return n;
> }
> @@ -204,6 +206,7 @@ trie_add_v4(struct trie_head *th, struct
> /* create new node */
> if ((new = calloc(1, sizeof(*new))) == NULL)
> return NULL;
> + th->v4_cnt++;
> rdemem.pset_cnt++;
> rdemem.pset_size += sizeof(*new);
> new->addr = p;
> @@ -269,6 +272,8 @@ trie_add_v6(struct trie_head *th, struct
>
> if (n->plen == plen) {
> /* matching node, adjust */
> + if (n->node == 0)
> + th->v6_cnt++;
> n->node = 1;
> return n;
> }
> @@ -284,6 +289,7 @@ trie_add_v6(struct trie_head *th, struct
> /* create new node */
> if ((new = calloc(1, sizeof(*new))) == NULL)
> return NULL;
> + th->v6_cnt++;
> rdemem.pset_cnt++;
> rdemem.pset_size += sizeof(*new);
> new->addr = p;
> Index: bgpd/session.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
> retrieving revision 1.407
> diff -u -p -r1.407 session.c
> --- bgpd/session.c 23 Dec 2020 13:20:47 -0000 1.407
> +++ bgpd/session.c 23 Dec 2020 14:22:32 -0000
> @@ -2837,6 +2837,7 @@ session_dispatch_imsg(struct imsgbuf *ib
> case IMSG_CTL_SHOW_RIB_HASH:
> case IMSG_CTL_SHOW_NETWORK:
> case IMSG_CTL_SHOW_NEIGHBOR:
> + case IMSG_CTL_SHOW_SET:
> if (idx != PFD_PIPE_ROUTE_CTL)
> fatalx("ctl rib request not from RDE");
> control_imsg_relay(&imsg);
>