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? -- :wq Claudio > PS: apply diff in /usr/src/usr.sbin Index: bgpd/bgpd.h =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v retrieving revision 1.405 diff -u -p -r1.405 bgpd.h --- bgpd/bgpd.h 5 Nov 2020 11:52:59 -0000 1.405 +++ bgpd/bgpd.h 3 Dec 2020 20:15:30 -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.101 diff -u -p -r1.101 control.c --- bgpd/control.c 5 Nov 2020 11:28:11 -0000 1.101 +++ bgpd/control.c 3 Dec 2020 17:07:58 -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 */ @@ -496,6 +497,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.506 diff -u -p -r1.506 rde.c --- bgpd/rde.c 5 Nov 2020 14:44:59 -0000 1.506 +++ bgpd/rde.c 3 Dec 2020 20:16:06 -0000 @@ -342,12 +342,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; @@ -571,6 +574,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)); @@ -3046,6 +3096,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 */ @@ -3069,8 +3120,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); @@ -3809,9 +3862,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_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.405 diff -u -p -r1.405 session.c --- bgpd/session.c 5 Nov 2020 14:44:59 -0000 1.405 +++ bgpd/session.c 3 Dec 2020 17:08:29 -0000 @@ -2816,6 +2816,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); 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,