This diff just moves most show related functions into a new file.
It is mostly mechanical (remove function from bgpctl.c and add it to
output.c).

OK?
-- 
:wq Claudio

? obj
Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/Makefile,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile
--- Makefile    25 Jun 2019 07:44:20 -0000      1.15
+++ Makefile    20 Dec 2019 07:20:26 -0000
@@ -3,7 +3,7 @@
 .PATH:         ${.CURDIR}/../bgpd
 
 PROG=  bgpctl
-SRCS=  bgpctl.c parser.c mrtparser.c util.c
+SRCS=  bgpctl.c output.c parser.c mrtparser.c util.c
 CFLAGS+= -Wall
 CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
 CFLAGS+= -Wmissing-declarations
Index: bgpctl.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.253
diff -u -p -r1.253 bgpctl.c
--- bgpctl.c    20 Dec 2019 07:18:51 -0000      1.253
+++ bgpctl.c    20 Dec 2019 07:20:27 -0000
@@ -2,6 +2,7 @@
 
 /*
  * Copyright (c) 2003 Henning Brauer <henn...@openbsd.org>
+ * Copyright (c) 2004-2019 Claudio Jeker <clau...@openbsd.org>
  * Copyright (c) 2016 Job Snijders <j...@instituut.net>
  * Copyright (c) 2016 Peter Hessler <phess...@openbsd.org>
  *
@@ -38,49 +39,20 @@
 #include "bgpd.h"
 #include "session.h"
 #include "rde.h"
+
+#include "bgpctl.h"
 #include "parser.h"
 #include "mrtparser.h"
 
-enum neighbor_views {
-       NV_DEFAULT,
-       NV_TIMERS
-};
-
-#define EOL0(flag)     ((flag & F_CTL_SSV) ? ';' : '\n')
-
 int             main(int, char *[]);
 int             show(struct imsg *, struct parse_result *);
-char           *fmt_peer(const char *, const struct bgpd_addr *, int);
-void            show_summary(struct peer *);
-void            show_neighbor_full(struct peer *, struct parse_result *);
-void            show_neighbor(struct peer *, struct parse_result *res);
-void            print_neighbor_capa_mp(struct peer *);
-void            print_neighbor_capa_restart(struct peer *);
-void            print_neighbor_msgstats(struct peer *);
 void            print_timer(const char *, time_t);
-const char     *fmt_timeframe(time_t t);
-void            show_fib_flags(u_int16_t);
-void            show_fib(struct kroute_full *);
-void            show_fib_table(struct ktable *);
-void            show_nexthop(struct ctl_show_nexthop *);
-void            show_interface(struct ctl_show_interface *);
-void            print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t, u_int8_t);
-const char *    print_origin(u_int8_t, int);
-const char *    print_ovs(u_int8_t, int);
-void            print_flags(u_int8_t, int);
-void            show_rib(struct ctl_show_rib *, u_char *, size_t,
-                   struct parse_result *);
-void            show_rib_brief(struct ctl_show_rib *, u_char *, size_t);
-void            show_rib_detail(struct ctl_show_rib *, u_char *, size_t, int);
 void            show_attr(void *, u_int16_t, int);
 void            show_communities(u_char *, size_t, int);
 void            show_community(u_char *, u_int16_t);
 void            show_large_community(u_char *, u_int16_t);
 void            show_ext_community(u_char *, u_int16_t);
-void            show_rib_mem(struct rde_memstats *);
-void            show_rib_hash(struct rde_hashstats *);
 void            send_filterset(struct imsgbuf *, struct filter_set_head *);
-const char     *get_errstr(u_int8_t, u_int8_t);
 void            show_mrt_dump_neighbors(struct mrt_rib *, struct mrt_peer *,
                    void *);
 void            show_mrt_dump(struct mrt_rib *, struct mrt_peer *, void *);
@@ -89,10 +61,7 @@ void          show_mrt_state(struct mrt_bgp_sta
 void            show_mrt_msg(struct mrt_bgp_msg *, void *);
 const char     *msg_type(u_int8_t);
 void            network_bulk(struct parse_result *);
-const char     *print_auth_method(enum auth_method);
 int             match_aspath(void *, u_int16_t, struct filter_as *);
-void            show_head(struct parse_result *);
-void            show_result(u_int);
 
 struct imsgbuf *ibuf;
 struct mrt_parser show_mrt = { show_mrt_dump, show_mrt_state, show_mrt_msg };
@@ -537,46 +506,6 @@ fmt_peer(const char *descr, const struct
        return (p);
 }
 
-void
-show_summary(struct peer *p)
-{
-       char                    *s;
-       const char              *a;
-       size_t                  alen;
-
-       s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
-           p->conf.remote_masklen);
-
-       a = log_as(p->conf.remote_as);
-       alen = strlen(a);
-       /* max displayed length of the peers name is 28 */
-       if (alen < 28) {
-               if (strlen(s) > 28 - alen)
-                               s[28 - alen] = '\0';
-       } else
-               alen = 0;
-
-       printf("%-*s %s %10llu %10llu %5u %-8s ",
-           (28 - (int)alen), s, a,
-           p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
-           p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
-           p->stats.msg_rcvd_rrefresh,
-           p->stats.msg_sent_open + p->stats.msg_sent_notification +
-           p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
-           p->stats.msg_sent_rrefresh,
-           p->wbuf.queued,
-           fmt_timeframe(p->stats.last_updown));
-       if (p->state == STATE_ESTABLISHED) {
-               printf("%6u", p->stats.prefix_cnt);
-               if (p->conf.max_prefix != 0)
-                       printf("/%u", p->conf.max_prefix);
-       } else if (p->conf.template)
-               printf("Template");
-       else
-               printf("%s", statenames[p->state]);
-       printf("\n");
-}
-
 const char *
 print_auth_method(enum auth_method method)
 {
@@ -598,162 +527,6 @@ print_auth_method(enum auth_method metho
 }
 
 void
-show_neighbor_full(struct peer *p, struct parse_result *res)
-{
-       struct in_addr           ina;
-       char                    *s;
-       int                      hascapamp = 0;
-       u_int8_t                 i;
-
-       if ((p->conf.remote_addr.aid == AID_INET &&
-           p->conf.remote_masklen != 32) ||
-           (p->conf.remote_addr.aid == AID_INET6 &&
-           p->conf.remote_masklen != 128)) {
-               if (asprintf(&s, "%s/%u",
-                   log_addr(&p->conf.remote_addr),
-                   p->conf.remote_masklen) == -1)
-                       err(1, NULL);
-       } else if ((s = strdup(log_addr(&p->conf.remote_addr))) == NULL)
-                       err(1, "strdup");
-
-       ina.s_addr = p->remote_bgpid;
-       printf("BGP neighbor is %s, ", s);
-       free(s);
-       if (p->conf.remote_as == 0 && p->conf.template)
-               printf("remote AS: accept any");
-       else
-               printf("remote AS %s", log_as(p->conf.remote_as));
-       if (p->conf.template)
-               printf(", Template");
-       if (p->template)
-               printf(", Cloned");
-       if (p->conf.passive)
-               printf(", Passive");
-       if (p->conf.ebgp && p->conf.distance > 1)
-               printf(", Multihop (%u)", (int)p->conf.distance);
-       printf("\n");
-       if (p->conf.descr[0])
-               printf(" Description: %s\n", p->conf.descr);
-       if (p->conf.max_prefix) {
-               printf(" Max-prefix: %u", p->conf.max_prefix);
-               if (p->conf.max_prefix_restart)
-                       printf(" (restart %u)",
-                           p->conf.max_prefix_restart);
-               printf("\n");
-       }
-       printf("  BGP version 4, remote router-id %s",
-           inet_ntoa(ina));
-       printf("%s\n", print_auth_method(p->auth.method));
-       printf("  BGP state = %s", statenames[p->state]);
-       if (p->conf.down) {
-               printf(", marked down");
-               if (*(p->conf.shutcomm)) {
-                       printf(" with shutdown reason \"%s\"",
-                           log_shutcomm(p->conf.shutcomm));
-               }
-       }
-       if (p->stats.last_updown != 0)
-               printf(", %s for %s",
-                   p->state == STATE_ESTABLISHED ? "up" : "down",
-                   fmt_timeframe(p->stats.last_updown));
-       printf("\n");
-       printf("  Last read %s, holdtime %us, keepalive interval %us\n",
-           fmt_timeframe(p->stats.last_read),
-           p->holdtime, p->holdtime/3);
-       for (i = 0; i < AID_MAX; i++)
-               if (p->capa.peer.mp[i])
-                       hascapamp = 1;
-       if (hascapamp || p->capa.peer.refresh ||
-           p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
-               printf("  Neighbor capabilities:\n");
-               if (hascapamp) {
-                       printf("    Multiprotocol extensions: ");
-                       print_neighbor_capa_mp(p);
-                       printf("\n");
-               }
-               if (p->capa.peer.refresh)
-                       printf("    Route Refresh\n");
-               if (p->capa.peer.grestart.restart) {
-                       printf("    Graceful Restart");
-                       print_neighbor_capa_restart(p);
-                       printf("\n");
-               }
-               if (p->capa.peer.as4byte)
-                       printf("    4-byte AS numbers\n");
-       }
-       printf("\n");
-
-       if (res->action == SHOW_NEIGHBOR_TIMERS)
-               return;
-
-       print_neighbor_msgstats(p);
-       printf("\n");
-       if (*(p->stats.last_shutcomm)) {
-               printf("  Last received shutdown reason: \"%s\"\n",
-                   log_shutcomm(p->stats.last_shutcomm));
-       }
-       if (p->state == STATE_IDLE) {
-               static const char       *errstr;
-
-               errstr = get_errstr(p->stats.last_sent_errcode,
-                   p->stats.last_sent_suberr);
-               if (errstr)
-                       printf("  Last error: %s\n\n", errstr);
-       } else {
-               printf("  Local host:  %20s, Local port:  %5u\n",
-                   log_addr(&p->local), p->local_port);
-
-               printf("  Remote host: %20s, Remote port: %5u\n",
-                   log_addr(&p->remote), p->remote_port);
-               printf("\n");
-       }
-}
-
-void
-show_neighbor(struct peer *p, struct parse_result *res)
-{
-       char *s;
-
-       switch (res->action) {
-       case SHOW:
-       case SHOW_SUMMARY:
-               show_summary(p);
-               break;
-       case SHOW_SUMMARY_TERSE:
-               s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
-                   p->conf.remote_masklen);
-               printf("%s %s %s\n", s, log_as(p->conf.remote_as),
-                   p->conf.template ? "Template" : statenames[p->state]);
-               free(s);
-               break;
-       case SHOW_NEIGHBOR:
-       case SHOW_NEIGHBOR_TIMERS:
-               show_neighbor_full(p, res);
-               break;
-       case SHOW_NEIGHBOR_TERSE:
-               s = fmt_peer(NULL, &p->conf.remote_addr,
-                   p->conf.remote_masklen);
-               printf("%llu %llu %llu %llu %llu %llu %llu %llu %llu "
-                   "%llu %u %u %llu %llu %llu %llu %s %s \"%s\"\n",
-                   p->stats.msg_sent_open, p->stats.msg_rcvd_open,
-                   p->stats.msg_sent_notification,
-                   p->stats.msg_rcvd_notification,
-                   p->stats.msg_sent_update, p->stats.msg_rcvd_update,
-                   p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive,
-                   p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh,
-                   p->stats.prefix_cnt, p->conf.max_prefix,
-                   p->stats.prefix_sent_update, p->stats.prefix_rcvd_update,
-                   p->stats.prefix_sent_withdraw,
-                   p->stats.prefix_rcvd_withdraw, s,
-                   log_as(p->conf.remote_as), p->conf.descr);
-               free(s);
-               break;
-       default:
-               break;
-       }
-}
-
-void
 print_neighbor_capa_mp(struct peer *p)
 {
        int             comma;
@@ -919,99 +692,6 @@ show_fib_flags(u_int16_t flags)
 }
 
 void
-show_fib(struct kroute_full *kf)
-{
-       char                    *p;
-
-       show_fib_flags(kf->flags);
-
-       if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), kf->prefixlen) == -1)
-               err(1, NULL);
-       printf("%4i %-20s ", kf->priority, p);
-       free(p);
-
-       if (kf->flags & F_CONNECTED)
-               printf("link#%u", kf->ifindex);
-       else
-               printf("%s", log_addr(&kf->nexthop));
-       printf("\n");
-}
-
-void
-show_fib_table(struct ktable *kt)
-{
-       printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr,
-           kt->fib_sync ? "coupled" : "decoupled",
-           kt->fib_sync != kt->fib_conf ? "*" : "");
-}
-
-void
-show_nexthop(struct ctl_show_nexthop *nh)
-{
-       struct kroute           *k;
-       struct kroute6          *k6;
-       char                    *s;
-
-       printf("%s %-15s ", nh->valid ? "*" : " ", log_addr(&nh->addr));
-       if (!nh->krvalid) {
-               printf("\n");
-               return;
-       }
-       switch (nh->addr.aid) {
-       case AID_INET:
-               k = &nh->kr.kr4;
-               if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix),
-                   k->prefixlen) == -1)
-                       err(1, NULL);
-               printf("%-20s", s);
-               free(s);
-               printf("%3i %-15s ", k->priority,
-                   k->flags & F_CONNECTED ? "connected" :
-                   inet_ntoa(k->nexthop));
-               break;
-       case AID_INET6:
-               k6 = &nh->kr.kr6;
-               if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix),
-                   k6->prefixlen) == -1)
-                       err(1, NULL);
-               printf("%-20s", s);
-               free(s);
-               printf("%3i %-15s ", k6->priority,
-                   k6->flags & F_CONNECTED ? "connected" :
-                   log_in6addr(&k6->nexthop));
-               break;
-       default:
-               printf("unknown address family\n");
-               return;
-       }
-       if (nh->iface.ifname[0]) {
-               printf("%s (%s, %s)", nh->iface.ifname,
-                   nh->iface.is_up ? "UP" : "DOWN",
-                   nh->iface.baudrate ?
-                   get_baudrate(nh->iface.baudrate, "bps") :
-                   nh->iface.linkstate);
-       }
-       printf("\n");
-}
-
-void
-show_interface(struct ctl_show_interface *iface)
-{
-       printf("%-15s", iface->ifname);
-       printf("%-9u", iface->rdomain);
-       printf("%-9s", iface->nh_reachable ? "ok" : "invalid");
-       printf("%-7s", iface->is_up ? "UP" : "");
-
-       if (iface->media[0])
-               printf("%s, ", iface->media);
-       printf("%s", iface->linkstate);
-
-       if (iface->baudrate > 0)
-               printf(", %s", get_baudrate(iface->baudrate, "Bit/s"));
-       printf("\n");
-}
-
-void
 print_prefix(struct bgpd_addr *prefix, u_int8_t prefixlen, u_int8_t flags,
     u_int8_t ovs)
 {
@@ -1090,74 +770,6 @@ print_ovs(u_int8_t validation_state, int
        }
 }
 
-void
-show_rib(struct ctl_show_rib *r, u_char *asdata, size_t aslen,
-    struct parse_result *res)
-{
-       if (res->flags & F_CTL_DETAIL)
-               show_rib_detail(r, asdata, aslen, res->flags);
-       else
-               show_rib_brief(r, asdata, aslen);
-}
-
-void
-show_rib_brief(struct ctl_show_rib *r, u_char *asdata, size_t aslen)
-{
-       char                    *aspath;
-
-       print_prefix(&r->prefix, r->prefixlen, r->flags, r->validation_state);
-       printf(" %-15s ", log_addr(&r->exit_nexthop));
-       printf(" %5u %5u ", r->local_pref, r->med);
-
-       if (aspath_asprint(&aspath, asdata, aslen) == -1)
-               err(1, NULL);
-       if (strlen(aspath) > 0)
-               printf("%s ", aspath);
-       free(aspath);
-
-       printf("%s\n", print_origin(r->origin, 1));
-}
-
-void
-show_rib_detail(struct ctl_show_rib *r, u_char *asdata, size_t aslen,
-    int flag0)
-{
-       struct in_addr           id;
-       char                    *aspath, *s;
-       time_t                   now;
-
-       printf("\nBGP routing table entry for %s/%u%c",
-           log_addr(&r->prefix), r->prefixlen,
-           EOL0(flag0));
-
-       if (aspath_asprint(&aspath, asdata, aslen) == -1)
-               err(1, NULL);
-       if (strlen(aspath) > 0)
-               printf("    %s%c", aspath, EOL0(flag0));
-       free(aspath);
-
-       s = fmt_peer(r->descr, &r->remote_addr, -1);
-       printf("    Nexthop %s ", log_addr(&r->exit_nexthop));
-       printf("(via %s) Neighbor %s (", log_addr(&r->true_nexthop), s);
-       free(s);
-       id.s_addr = htonl(r->remote_id);
-       printf("%s)%c", inet_ntoa(id), EOL0(flag0));
-
-       printf("    Origin %s, metric %u, localpref %u, weight %u, ovs %s, ",
-           print_origin(r->origin, 0), r->med, r->local_pref, r->weight,
-           print_ovs(r->validation_state, 0));
-       print_flags(r->flags, 0);
-
-       now = time(NULL);
-       if (now > r->lastchange)
-               now -= r->lastchange;
-       else
-               now = 0;
-
-       printf("%c    Last update: %s ago%c", EOL0(flag0),
-           fmt_timeframe_core(now), EOL0(flag0));
-}
-
 static const char *
 print_attr(u_int8_t type, u_int8_t flags)
 {
@@ -1672,7 +1284,7 @@ show_ext_community(u_char *data, u_int16
        }
 }
 
-static char *
+const char *
 fmt_mem(long long num)
 {
        static char     buf[16];
@@ -1684,79 +1296,6 @@ fmt_mem(long long num)
 }
 
 void
-show_rib_mem(struct rde_memstats *stats)
-{
-       static size_t  pt_sizes[AID_MAX] = AID_PTSIZE;
-       size_t                  pts = 0;
-       int                     i;
-
-       printf("RDE memory statistics\n");
-       for (i = 0; i < AID_MAX; i++) {
-               if (stats->pt_cnt[i] == 0)
-                       continue;
-               pts += stats->pt_cnt[i] * pt_sizes[i];
-               printf("%10lld %s network entries using %s of memory\n",
-                   stats->pt_cnt[i], aid_vals[i].name,
-                   fmt_mem(stats->pt_cnt[i] * pt_sizes[i]));
-       }
-       printf("%10lld rib entries using %s of memory\n",
-           stats->rib_cnt, fmt_mem(stats->rib_cnt *
-           sizeof(struct rib_entry)));
-       printf("%10lld prefix entries using %s of memory\n",
-           stats->prefix_cnt, fmt_mem(stats->prefix_cnt *
-           sizeof(struct prefix)));
-       printf("%10lld BGP path attribute entries using %s of memory\n",
-           stats->path_cnt, fmt_mem(stats->path_cnt *
-           sizeof(struct rde_aspath)));
-       printf("\t   and holding %lld references\n",
-           stats->path_refs);
-       printf("%10lld BGP AS-PATH attribute entries using "
-           "%s of memory\n\t   and holding %lld references\n",
-           stats->aspath_cnt, fmt_mem(stats->aspath_size),
-           stats->aspath_refs);
-       printf("%10lld entries for %lld BGP communities "
-           "using %s of memory\n", stats->comm_cnt, stats->comm_nmemb,
-           fmt_mem(stats->comm_cnt * sizeof(struct rde_community) +
-           stats->comm_size * sizeof(struct community)));
-       printf("\t   and holding %lld references\n",
-           stats->comm_refs);
-       printf("%10lld BGP attributes entries using %s of memory\n",
-           stats->attr_cnt, fmt_mem(stats->attr_cnt *
-           sizeof(struct attr)));
-       printf("\t   and holding %lld references\n",
-           stats->attr_refs);
-       printf("%10lld BGP attributes using %s of memory\n",
-           stats->attr_dcnt, fmt_mem(stats->attr_data));
-       printf("%10lld as-set elements in %lld tables using "
-           "%s of memory\n", stats->aset_nmemb, stats->aset_cnt,
-           fmt_mem(stats->aset_size));
-       printf("%10lld prefix-set elements using %s of memory\n",
-           stats->pset_cnt, fmt_mem(stats->pset_size));
-       printf("RIB using %s of memory\n", fmt_mem(pts +
-           stats->prefix_cnt * sizeof(struct prefix) +
-           stats->rib_cnt * sizeof(struct rib_entry) +
-           stats->path_cnt * sizeof(struct rde_aspath) +
-           stats->aspath_size + stats->attr_cnt * sizeof(struct attr) +
-           stats->attr_data));
-       printf("Sets using %s of memory\n", fmt_mem(stats->aset_size +
-           stats->pset_size));
-       printf("\nRDE hash statistics\n");
-}
-
-void
-show_rib_hash(struct rde_hashstats *hash)
-{
-       double avg, dev;
-
-       printf("\t%s: size %lld, %lld entries\n", hash->name, hash->num,
-           hash->sum);
-       avg = (double)hash->sum / (double)hash->num;
-       dev = sqrt(fmax(0, hash->sumq / hash->num - avg * avg));
-       printf("\t    min %lld max %lld avg/std-dev = %.3f/%.3f\n",
-           hash->min, hash->max, avg, dev);
-}
-
-void
 send_filterset(struct imsgbuf *i, struct filter_set_head *set)
 {
        struct filter_set       *s;
@@ -2579,69 +2118,4 @@ match_aspath(void *data, u_int16_t len, 
                }
        }
        return (0);
-}
-
-void
-show_head(struct parse_result *res)
-{
-       switch (res->action) {
-       case SHOW:
-       case SHOW_SUMMARY:
-               printf("%-20s %8s %10s %10s %5s %-8s %s\n", "Neighbor", "AS",
-                   "MsgRcvd", "MsgSent", "OutQ", "Up/Down", "State/PrfRcvd");
-               break;
-       case SHOW_FIB:
-               printf("flags: * = valid, B = BGP, C = Connected, "
-                   "S = Static, D = Dynamic\n");
-               printf("       "
-                   "N = BGP Nexthop reachable via this route\n");
-               printf("       r = reject route, b = blackhole route\n\n");
-               printf("flags prio destination          gateway\n");
-               break;
-       case SHOW_FIB_TABLES:
-               printf("%-5s %-20s %-8s\n", "Table", "Description", "State");
-               break;
-       case SHOW_NEXTHOP:
-               printf("Flags: * = nexthop valid\n");
-               printf("\n  %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route",
-                    "Prio", "Gateway", "Iface");
-               break;
-       case SHOW_INTERFACE:
-               printf("%-15s%-9s%-9s%-7s%s\n", "Interface", "rdomain",
-                   "Nexthop", "Flags", "Link state");
-               break;
-       case SHOW_RIB:
-               if (res->flags & F_CTL_DETAIL)
-                       break;
-               printf("flags: "
-                   "* = Valid, > = Selected, I = via IBGP, A = Announced,\n"
-                   "       S = Stale, E = Error\n");
-               printf("origin validation state: "
-                   "N = not-found, V = valid, ! = invalid\n");
-               printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n");
-               printf("%-5s %3s %-20s %-15s  %5s %5s %s\n",
-                   "flags", "ovs", "destination", "gateway", "lpref", "med",
-                   "aspath origin");
-               break;
-       case NETWORK_SHOW:
-               printf("flags: S = Static\n");
-               printf("flags prio destination          gateway\n");
-               break;
-       default:
-               break;
-       }
-}
-
-void
-show_result(u_int rescode)
-{
-       if (rescode == 0)
-               printf("request processed\n");
-       else {
-               if (rescode >
-                   sizeof(ctl_res_strerror)/sizeof(ctl_res_strerror[0]))
-                       printf("unknown result error code %u\n", rescode);
-               else
-                       printf("%s\n", ctl_res_strerror[rescode]);
-       }
 }
Index: bgpctl.h
===================================================================
RCS file: bgpctl.h
diff -N bgpctl.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ bgpctl.h    20 Dec 2019 07:20:27 -0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Claudio Jeker <clau...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct parse_result;
+void   show_head(struct parse_result *);
+void   show_neighbor(struct peer *, struct parse_result *);
+void   show_fib(struct kroute_full *);
+void   show_fib_table(struct ktable *);
+void   show_nexthop(struct ctl_show_nexthop *);
+void   show_interface(struct ctl_show_interface *);
+void   show_rib(struct ctl_show_rib *, u_char *, size_t,
+           struct parse_result *);
+void   show_rib_hash(struct rde_hashstats *);
+void   show_rib_mem(struct rde_memstats *);
+void   show_result(u_int);
+
+
+#define EOL0(flag)     ((flag & F_CTL_SSV) ? ';' : '\n')
+
+void            print_prefix(struct bgpd_addr *, u_int8_t, u_int8_t, u_int8_t);
+void            print_neighbor_capa_mp(struct peer *);
+void            print_neighbor_capa_restart(struct peer *);
+void            print_neighbor_msgstats(struct peer *);
+void            print_flags(u_int8_t, int);
+void            show_fib_flags(u_int16_t);
+
+const char     *print_ovs(u_int8_t, int);
+const char     *print_origin(u_int8_t, int);
+const char     *print_auth_method(enum auth_method);
+const char     *fmt_mem(long long);
+
+const char     *fmt_timeframe(time_t);
+char           *fmt_peer(const char *, const struct bgpd_addr *, int);
+const char     *get_errstr(u_int8_t, u_int8_t);
+
Index: output.c
===================================================================
RCS file: output.c
diff -N output.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ output.c    20 Dec 2019 07:20:27 -0000
@@ -0,0 +1,522 @@
+/*     $OpenBSD$ */
+
+/*
+ * Copyright (c) 2003 Henning Brauer <henn...@openbsd.org>
+ * Copyright (c) 2004-2019 Claudio Jeker <clau...@openbsd.org>
+ * Copyright (c) 2016 Job Snijders <j...@instituut.net>
+ * Copyright (c) 2016 Peter Hessler <phess...@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <err.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bgpd.h"
+#include "session.h"
+#include "rde.h"
+
+#include "bgpctl.h"
+#include "parser.h"
+
+void
+show_head(struct parse_result *res)
+{
+       switch (res->action) {
+       case SHOW:
+       case SHOW_SUMMARY:
+               printf("%-20s %8s %10s %10s %5s %-8s %s\n", "Neighbor", "AS",
+                   "MsgRcvd", "MsgSent", "OutQ", "Up/Down", "State/PrfRcvd");
+               break;
+       case SHOW_FIB:
+               printf("flags: * = valid, B = BGP, C = Connected, "
+                   "S = Static, D = Dynamic\n");
+               printf("       "
+                   "N = BGP Nexthop reachable via this route\n");
+               printf("       r = reject route, b = blackhole route\n\n");
+               printf("flags prio destination          gateway\n");
+               break;
+       case SHOW_FIB_TABLES:
+               printf("%-5s %-20s %-8s\n", "Table", "Description", "State");
+               break;
+       case SHOW_NEXTHOP:
+               printf("Flags: * = nexthop valid\n");
+               printf("\n  %-15s %-19s%-4s %-15s %-20s\n", "Nexthop", "Route",
+                    "Prio", "Gateway", "Iface");
+               break;
+       case SHOW_INTERFACE:
+               printf("%-15s%-9s%-9s%-7s%s\n", "Interface", "rdomain",
+                   "Nexthop", "Flags", "Link state");
+               break;
+       case SHOW_RIB:
+               if (res->flags & F_CTL_DETAIL)
+                       break;
+               printf("flags: "
+                   "* = Valid, > = Selected, I = via IBGP, A = Announced,\n"
+                   "       S = Stale, E = Error\n");
+               printf("origin validation state: "
+                   "N = not-found, V = valid, ! = invalid\n");
+               printf("origin: i = IGP, e = EGP, ? = Incomplete\n\n");
+               printf("%-5s %3s %-20s %-15s  %5s %5s %s\n",
+                   "flags", "ovs", "destination", "gateway", "lpref", "med",
+                   "aspath origin");
+               break;
+       case NETWORK_SHOW:
+               printf("flags: S = Static\n");
+               printf("flags prio destination          gateway\n");
+               break;
+       default:
+               break;
+       }
+}
+
+static void
+show_summary(struct peer *p)
+{
+       char                    *s;
+       const char              *a;
+       size_t                  alen;
+
+       s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
+           p->conf.remote_masklen);
+
+       a = log_as(p->conf.remote_as);
+       alen = strlen(a);
+       /* max displayed length of the peers name is 28 */
+       if (alen < 28) {
+               if (strlen(s) > 28 - alen)
+                       s[28 - alen] = '\0';
+       } else
+               alen = 0;
+
+       printf("%-*s %s %10llu %10llu %5u %-8s ",
+           (28 - (int)alen), s, a,
+           p->stats.msg_rcvd_open + p->stats.msg_rcvd_notification +
+           p->stats.msg_rcvd_update + p->stats.msg_rcvd_keepalive +
+           p->stats.msg_rcvd_rrefresh,
+           p->stats.msg_sent_open + p->stats.msg_sent_notification +
+           p->stats.msg_sent_update + p->stats.msg_sent_keepalive +
+           p->stats.msg_sent_rrefresh,
+           p->wbuf.queued,
+           fmt_timeframe(p->stats.last_updown));
+       if (p->state == STATE_ESTABLISHED) {
+               printf("%6u", p->stats.prefix_cnt);
+               if (p->conf.max_prefix != 0)
+                       printf("/%u", p->conf.max_prefix);
+       } else if (p->conf.template)
+               printf("Template");
+       else
+               printf("%s", statenames[p->state]);
+       printf("\n");
+       free(s);
+}
+
+static void
+show_neighbor_full(struct peer *p, struct parse_result *res)
+{
+       struct in_addr           ina;
+       char                    *s;
+       int                      hascapamp = 0;
+       u_int8_t                 i;
+
+       if ((p->conf.remote_addr.aid == AID_INET &&
+           p->conf.remote_masklen != 32) ||
+           (p->conf.remote_addr.aid == AID_INET6 &&
+           p->conf.remote_masklen != 128)) {
+               if (asprintf(&s, "%s/%u",
+                   log_addr(&p->conf.remote_addr),
+                   p->conf.remote_masklen) == -1)
+                       err(1, NULL);
+       } else if ((s = strdup(log_addr(&p->conf.remote_addr))) == NULL)
+                       err(1, "strdup");
+
+       ina.s_addr = p->remote_bgpid;
+       printf("BGP neighbor is %s, ", s);
+       free(s);
+       if (p->conf.remote_as == 0 && p->conf.template)
+               printf("remote AS: accept any");
+       else
+               printf("remote AS %s", log_as(p->conf.remote_as));
+       if (p->conf.template)
+               printf(", Template");
+       if (p->template)
+               printf(", Cloned");
+       if (p->conf.passive)
+               printf(", Passive");
+       if (p->conf.ebgp && p->conf.distance > 1)
+               printf(", Multihop (%u)", (int)p->conf.distance);
+       printf("\n");
+       if (p->conf.descr[0])
+               printf(" Description: %s\n", p->conf.descr);
+       if (p->conf.max_prefix) {
+               printf(" Max-prefix: %u", p->conf.max_prefix);
+               if (p->conf.max_prefix_restart)
+                       printf(" (restart %u)",
+                           p->conf.max_prefix_restart);
+               printf("\n");
+       }
+       printf("  BGP version 4, remote router-id %s",
+           inet_ntoa(ina));
+       printf("%s\n", print_auth_method(p->auth.method));
+       printf("  BGP state = %s", statenames[p->state]);
+       if (p->conf.down) {
+               printf(", marked down");
+               if (*(p->conf.shutcomm)) {
+                       printf(" with shutdown reason \"%s\"",
+                           log_shutcomm(p->conf.shutcomm));
+               }
+       }
+       if (p->stats.last_updown != 0)
+               printf(", %s for %s",
+                   p->state == STATE_ESTABLISHED ? "up" : "down",
+                   fmt_timeframe(p->stats.last_updown));
+       printf("\n");
+       printf("  Last read %s, holdtime %us, keepalive interval %us\n",
+           fmt_timeframe(p->stats.last_read),
+           p->holdtime, p->holdtime/3);
+       for (i = 0; i < AID_MAX; i++)
+               if (p->capa.peer.mp[i])
+                       hascapamp = 1;
+       if (hascapamp || p->capa.peer.refresh ||
+           p->capa.peer.grestart.restart || p->capa.peer.as4byte) {
+               printf("  Neighbor capabilities:\n");
+               if (hascapamp) {
+                       printf("    Multiprotocol extensions: ");
+                       print_neighbor_capa_mp(p);
+                       printf("\n");
+               }
+               if (p->capa.peer.refresh)
+                       printf("    Route Refresh\n");
+               if (p->capa.peer.grestart.restart) {
+                       printf("    Graceful Restart");
+                       print_neighbor_capa_restart(p);
+                       printf("\n");
+               }
+               if (p->capa.peer.as4byte)
+                       printf("    4-byte AS numbers\n");
+       }
+       printf("\n");
+
+       if (res->action == SHOW_NEIGHBOR_TIMERS)
+               return;
+
+       print_neighbor_msgstats(p);
+       printf("\n");
+       if (*(p->stats.last_shutcomm)) {
+               printf("  Last received shutdown reason: \"%s\"\n",
+                   log_shutcomm(p->stats.last_shutcomm));
+       }
+       if (p->state == STATE_IDLE) {
+               static const char       *errstr;
+
+               errstr = get_errstr(p->stats.last_sent_errcode,
+                   p->stats.last_sent_suberr);
+               if (errstr)
+                       printf("  Last error: %s\n\n", errstr);
+       } else {
+               printf("  Local host:  %20s, Local port:  %5u\n",
+                   log_addr(&p->local), p->local_port);
+
+               printf("  Remote host: %20s, Remote port: %5u\n",
+                   log_addr(&p->remote), p->remote_port);
+               printf("\n");
+       }
+}
+
+void
+show_neighbor(struct peer *p, struct parse_result *res)
+{
+       char *s;
+
+       switch (res->action) {
+       case SHOW:
+       case SHOW_SUMMARY:
+               show_summary(p);
+               break;
+       case SHOW_SUMMARY_TERSE:
+               s = fmt_peer(p->conf.descr, &p->conf.remote_addr,
+                   p->conf.remote_masklen);
+               printf("%s %s %s\n", s, log_as(p->conf.remote_as),
+                   p->conf.template ? "Template" : statenames[p->state]);
+               free(s);
+               break;
+       case SHOW_NEIGHBOR:
+       case SHOW_NEIGHBOR_TIMERS:
+               show_neighbor_full(p, res);
+               break;
+       case SHOW_NEIGHBOR_TERSE:
+               s = fmt_peer(NULL, &p->conf.remote_addr,
+                   p->conf.remote_masklen);
+               printf("%llu %llu %llu %llu %llu %llu %llu %llu %llu "
+                   "%llu %u %u %llu %llu %llu %llu %s %s \"%s\"\n",
+                   p->stats.msg_sent_open, p->stats.msg_rcvd_open,
+                   p->stats.msg_sent_notification,
+                   p->stats.msg_rcvd_notification,
+                   p->stats.msg_sent_update, p->stats.msg_rcvd_update,
+                   p->stats.msg_sent_keepalive, p->stats.msg_rcvd_keepalive,
+                   p->stats.msg_sent_rrefresh, p->stats.msg_rcvd_rrefresh,
+                   p->stats.prefix_cnt, p->conf.max_prefix,
+                   p->stats.prefix_sent_update, p->stats.prefix_rcvd_update,
+                   p->stats.prefix_sent_withdraw,
+                   p->stats.prefix_rcvd_withdraw, s,
+                   log_as(p->conf.remote_as), p->conf.descr);
+               free(s);
+               break;
+       default:
+               break;
+       }
+}
+
+void
+show_fib(struct kroute_full *kf)
+{
+       char                    *p;
+
+       show_fib_flags(kf->flags);
+
+       if (asprintf(&p, "%s/%u", log_addr(&kf->prefix), kf->prefixlen) == -1)
+               err(1, NULL);
+       printf("%4i %-20s ", kf->priority, p);
+       free(p);
+
+       if (kf->flags & F_CONNECTED)
+               printf("link#%u", kf->ifindex);
+       else
+               printf("%s", log_addr(&kf->nexthop));
+       printf("\n");
+}
+
+void
+show_fib_table(struct ktable *kt)
+{
+       printf("%5i %-20s %-8s%s\n", kt->rtableid, kt->descr,
+           kt->fib_sync ? "coupled" : "decoupled",
+           kt->fib_sync != kt->fib_conf ? "*" : "");
+}
+
+void
+show_nexthop(struct ctl_show_nexthop *nh)
+{
+       struct kroute           *k;
+       struct kroute6          *k6;
+       char                    *s;
+
+       printf("%s %-15s ", nh->valid ? "*" : " ", log_addr(&nh->addr));
+       if (!nh->krvalid) {
+               printf("\n");
+               return;
+       }
+       switch (nh->addr.aid) {
+       case AID_INET:
+               k = &nh->kr.kr4;
+               if (asprintf(&s, "%s/%u", inet_ntoa(k->prefix),
+                   k->prefixlen) == -1)
+                       err(1, NULL);
+               printf("%-20s", s);
+               free(s);
+               printf("%3i %-15s ", k->priority,
+                   k->flags & F_CONNECTED ? "connected" :
+                   inet_ntoa(k->nexthop));
+               break;
+       case AID_INET6:
+               k6 = &nh->kr.kr6;
+               if (asprintf(&s, "%s/%u", log_in6addr(&k6->prefix),
+                   k6->prefixlen) == -1)
+                       err(1, NULL);
+               printf("%-20s", s);
+               free(s);
+               printf("%3i %-15s ", k6->priority,
+                   k6->flags & F_CONNECTED ? "connected" :
+                   log_in6addr(&k6->nexthop));
+               break;
+       default:
+               printf("unknown address family\n");
+               return;
+       }
+       if (nh->iface.ifname[0]) {
+               printf("%s (%s, %s)", nh->iface.ifname,
+                   nh->iface.is_up ? "UP" : "DOWN",
+                   nh->iface.baudrate ?
+                   get_baudrate(nh->iface.baudrate, "bps") :
+                   nh->iface.linkstate);
+       }
+       printf("\n");
+}
+
+void
+show_interface(struct ctl_show_interface *iface)
+{
+       printf("%-15s", iface->ifname);
+       printf("%-9u", iface->rdomain);
+       printf("%-9s", iface->nh_reachable ? "ok" : "invalid");
+       printf("%-7s", iface->is_up ? "UP" : "");
+
+       if (iface->media[0])
+               printf("%s, ", iface->media);
+       printf("%s", iface->linkstate);
+
+       if (iface->baudrate > 0)
+               printf(", %s", get_baudrate(iface->baudrate, "Bit/s"));
+       printf("\n");
+}
+
+static void
+show_rib_brief(struct ctl_show_rib *r, u_char *asdata, size_t aslen)
+{
+       char                    *aspath;
+
+       print_prefix(&r->prefix, r->prefixlen, r->flags, r->validation_state);
+       printf(" %-15s ", log_addr(&r->exit_nexthop));
+       printf(" %5u %5u ", r->local_pref, r->med);
+
+       if (aspath_asprint(&aspath, asdata, aslen) == -1)
+               err(1, NULL);
+       if (strlen(aspath) > 0)
+               printf("%s ", aspath);
+       free(aspath);
+
+       printf("%s\n", print_origin(r->origin, 1));
+}
+
+static void
+show_rib_detail(struct ctl_show_rib *r, u_char *asdata, size_t aslen,
+    int flag0)
+{
+       struct in_addr           id;
+       char                    *aspath, *s;
+
+       printf("\nBGP routing table entry for %s/%u%c",
+           log_addr(&r->prefix), r->prefixlen,
+           EOL0(flag0));
+
+       if (aspath_asprint(&aspath, asdata, aslen) == -1)
+               err(1, NULL);
+       if (strlen(aspath) > 0)
+               printf("    %s%c", aspath, EOL0(flag0));
+       free(aspath);
+
+       s = fmt_peer(r->descr, &r->remote_addr, -1);
+       printf("    Nexthop %s ", log_addr(&r->exit_nexthop));
+       printf("(via %s) Neighbor %s (", log_addr(&r->true_nexthop), s);
+       free(s);
+       id.s_addr = htonl(r->remote_id);
+       printf("%s)%c", inet_ntoa(id), EOL0(flag0));
+
+       printf("    Origin %s, metric %u, localpref %u, weight %u, ovs %s, ",
+           print_origin(r->origin, 0), r->med, r->local_pref, r->weight,
+           print_ovs(r->validation_state, 0));
+       print_flags(r->flags, 0);
+
+       printf("%c    Last update: %s ago%c", EOL0(flag0),
+           fmt_timeframe(r->lastchange), EOL0(flag0));
+}
+
+void
+show_rib(struct ctl_show_rib *r, u_char *asdata, size_t aslen,
+    struct parse_result *res)
+{
+       if (res->flags & F_CTL_DETAIL)
+               show_rib_detail(r, asdata, aslen, res->flags);
+       else
+               show_rib_brief(r, asdata, aslen);
+}
+
+void
+show_rib_mem(struct rde_memstats *stats)
+{
+       static size_t  pt_sizes[AID_MAX] = AID_PTSIZE;
+       size_t                  pts = 0;
+       int                     i;
+
+       printf("RDE memory statistics\n");
+       for (i = 0; i < AID_MAX; i++) {
+               if (stats->pt_cnt[i] == 0)
+                       continue;
+               pts += stats->pt_cnt[i] * pt_sizes[i];
+               printf("%10lld %s network entries using %s of memory\n",
+                   stats->pt_cnt[i], aid_vals[i].name,
+                   fmt_mem(stats->pt_cnt[i] * pt_sizes[i]));
+       }
+       printf("%10lld rib entries using %s of memory\n",
+           stats->rib_cnt, fmt_mem(stats->rib_cnt *
+           sizeof(struct rib_entry)));
+       printf("%10lld prefix entries using %s of memory\n",
+           stats->prefix_cnt, fmt_mem(stats->prefix_cnt *
+           sizeof(struct prefix)));
+       printf("%10lld BGP path attribute entries using %s of memory\n",
+           stats->path_cnt, fmt_mem(stats->path_cnt *
+           sizeof(struct rde_aspath)));
+       printf("\t   and holding %lld references\n",
+           stats->path_refs);
+       printf("%10lld BGP AS-PATH attribute entries using "
+           "%s of memory\n\t   and holding %lld references\n",
+           stats->aspath_cnt, fmt_mem(stats->aspath_size),
+           stats->aspath_refs);
+       printf("%10lld entries for %lld BGP communities "
+           "using %s of memory\n", stats->comm_cnt, stats->comm_nmemb,
+           fmt_mem(stats->comm_cnt * sizeof(struct rde_community) +
+           stats->comm_size * sizeof(struct community)));
+       printf("\t   and holding %lld references\n",
+           stats->comm_refs);
+       printf("%10lld BGP attributes entries using %s of memory\n",
+           stats->attr_cnt, fmt_mem(stats->attr_cnt *
+           sizeof(struct attr)));
+       printf("\t   and holding %lld references\n",
+           stats->attr_refs);
+       printf("%10lld BGP attributes using %s of memory\n",
+           stats->attr_dcnt, fmt_mem(stats->attr_data));
+       printf("%10lld as-set elements in %lld tables using "
+           "%s of memory\n", stats->aset_nmemb, stats->aset_cnt,
+           fmt_mem(stats->aset_size));
+       printf("%10lld prefix-set elements using %s of memory\n",
+           stats->pset_cnt, fmt_mem(stats->pset_size));
+       printf("RIB using %s of memory\n", fmt_mem(pts +
+           stats->prefix_cnt * sizeof(struct prefix) +
+           stats->rib_cnt * sizeof(struct rib_entry) +
+           stats->path_cnt * sizeof(struct rde_aspath) +
+           stats->aspath_size + stats->attr_cnt * sizeof(struct attr) +
+           stats->attr_data));
+       printf("Sets using %s of memory\n", fmt_mem(stats->aset_size +
+           stats->pset_size));
+       printf("\nRDE hash statistics\n");
+}
+
+void
+show_rib_hash(struct rde_hashstats *hash)
+{
+       double avg, dev;
+
+       printf("\t%s: size %lld, %lld entries\n", hash->name, hash->num,
+           hash->sum);
+       avg = (double)hash->sum / (double)hash->num;
+       dev = sqrt(fmax(0, hash->sumq / hash->num - avg * avg));
+       printf("\t    min %lld max %lld avg/std-dev = %.3f/%.3f\n",
+           hash->min, hash->max, avg, dev);
+}
+
+void
+show_result(u_int rescode)
+{
+       if (rescode == 0)
+               printf("request processed\n");
+       else {
+               if (rescode >
+                   sizeof(ctl_res_strerror)/sizeof(ctl_res_strerror[0]))
+                       printf("unknown result error code %u\n", rescode);
+               else
+                       printf("%s\n", ctl_res_strerror[rescode]);
+       }
+}

Reply via email to