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,

Reply via email to