Claudio Jeker(cje...@diehard.n-r-g.com) on 2019.12.20 08:24:34 +0100: > 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?
ok did you check that bgplg etc still build (i dont see why they should not). > -- > :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]); > + } > +} >