On Tue, Jun 09, 2020 at 09:17:31AM +0200, Claudio Jeker wrote:
> On Tue, Jun 09, 2020 at 08:44:42AM +0200, Remi Locherer wrote:
> > On Mon, Jun 08, 2020 at 10:10:17PM +0200, Remi Locherer wrote:
> > > Hi,
> > >
> > > to my knowledge there is no easy way to list all active rdomains or
> > > routing tables. Other platforms have "show vrf" or similar commands
> > > for an overview.
> > >
> > > Here is my attempt at such a view for OpenBSD:
> >
> > Updated diff with small changes:
> > - Print inet instead of Internet (input deraadt)
> > - Removed padding before rdomain id.
> > - Changed man page wording.
> >
> > twister ..in/netstat$ obj/netstat -R
> > Rdomain 0
> > Interfaces: lo0 iwm0 re0 enc0 pflog0 mpe0
> > Routing tables:
> > 0: inet 8, inet6 45, mpls 1
> > 3: inet 1, inet6 0, mpls 0
> > 7: inet 130309, inet6 10000, mpls 0
> >
> > Rdomain 77
> > Interfaces: vether77 lo77
> > Routing tables:
> > 77: inet 0, inet6 0, mpls 0
> >
> > Rdomain 122
> > Interfaces: vether122 lo122 pair122 vether1122 vether1123 vether1124
> > vether1125 vether1126 vether1127
> > Routing tables:
> > 122: inet 24, inet6 0, mpls 0
> >
> > Rdomain 255
> > Interfaces: vether255 lo255
> > Routing tables:
> > 255: inet 3, inet6 0, mpls 0
> >
> > twister ..in/netstat$
> >
> > OK?
>
> Why do you think the route counts are needed? You fetch all routing tables
> to count them in userland. The sysctl for doing that is expensive and
> especially on systems with full tables will make this command slow.
> If this is something we really want then the kernel should track and
> provide the count.
These counters are of interest for operators. But I agree that counting
the routes in userland is unfortunate. But I don't know how bad it is.
Is a lock involved in the kernel when dumping the full table?
I see in art.h that struct art_table has a counter. What would be a good
way to export this to userland?
>
> Apart from that I think this is a good addition.
>
> > Index: main.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/netstat/main.c,v
> > retrieving revision 1.116
> > diff -u -p -r1.116 main.c
> > --- main.c 28 Apr 2019 17:59:51 -0000 1.116
> > +++ main.c 30 May 2020 17:59:33 -0000
> > @@ -127,7 +127,7 @@ main(int argc, char *argv[])
> > tableid = getrtable();
> >
> > while ((ch = getopt(argc, argv,
> > - "AaBbc:deFf:ghI:iLlM:mN:np:P:qrsT:tuvW:w:")) != -1)
> > + "AaBbc:deFf:ghI:iLlM:mN:np:P:qRrsT:tuvW:w:")) != -1)
> > switch (ch) {
> > case 'A':
> > Aflag = 1;
> > @@ -225,6 +225,9 @@ main(int argc, char *argv[])
> > case 'q':
> > qflag = 1;
> > break;
> > + case 'R':
> > + Rflag = 1;
> > + break;
> > case 'r':
> > rflag = 1;
> > break;
> > @@ -318,6 +321,11 @@ main(int argc, char *argv[])
> > mroutepr();
> > if (af == AF_INET6 || af == AF_UNSPEC)
> > mroute6pr();
> > + exit(0);
> > + }
> > +
> > + if (Rflag) {
> > + rdomainpr();
> > exit(0);
> > }
> >
> > Index: netstat.1
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/netstat/netstat.1,v
> > retrieving revision 1.86
> > diff -u -p -r1.86 netstat.1
> > --- netstat.1 17 Apr 2019 20:34:21 -0000 1.86
> > +++ netstat.1 8 Jun 2020 20:42:46 -0000
> > @@ -74,6 +74,8 @@
> > .Op Fl i | I Ar interface
> > .Nm
> > .Op Fl W Ar interface
> > +.Nm
> > +.Op Fl R
> > .Sh DESCRIPTION
> > The
> > .Nm
> > @@ -267,6 +269,8 @@ Otherwise the states of the matching soc
> > Only show interfaces that have seen packets (or bytes if
> > .Fl b
> > is specified).
> > +.It Fl R
> > +List all rdomains with associated interfaces and routing tables.
> > .It Fl r
> > Show the routing tables.
> > The output is explained in more detail below.
> > Index: netstat.h
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/netstat/netstat.h,v
> > retrieving revision 1.74
> > diff -u -p -r1.74 netstat.h
> > --- netstat.h 28 Apr 2019 17:59:51 -0000 1.74
> > +++ netstat.h 7 Jun 2020 22:03:10 -0000
> > @@ -57,6 +57,7 @@ int pflag; /* show given protocol */
> > int Pflag; /* show given PCB */
> > int qflag; /* only display non-zero values for output */
> > int rflag; /* show routing tables (or routing stats) */
> > +int Rflag; /* show rdomain and rtable summary */
> > int sflag; /* show protocol statistics */
> > int tflag; /* show i/f watchdog timers */
> > int vflag; /* be verbose */
> > @@ -112,6 +113,9 @@ void rt_stats(void);
> > void pr_rthdr(int, int);
> > void pr_encaphdr(void);
> > void pr_family(int);
> > +
> > +void rdomainpr(void);
> > +void rttsummarypr(int);
> >
> > void ip6_stats(char *);
> > void icmp6_stats(char *);
> > Index: route.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/netstat/route.c,v
> > retrieving revision 1.104
> > diff -u -p -r1.104 route.c
> > --- route.c 28 Jun 2019 13:35:02 -0000 1.104
> > +++ route.c 9 Jun 2020 06:36:29 -0000
> > @@ -51,6 +51,7 @@
> > #include <stdlib.h>
> > #include <string.h>
> > #include <unistd.h>
> > +#include <ifaddrs.h>
> >
> > #include "netstat.h"
> >
> > @@ -346,4 +347,117 @@ rt_stats(void)
> > rtstat.rts_unreach, plural(rtstat.rts_unreach));
> > printf("\t%u use%s of a wildcard route\n",
> > rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
> > +}
> > +
> > +/*
> > + * Print rdomain and rtable summary
> > + */
> > +
> > +void
> > +rdomainpr(void)
> > +{
> > + struct if_data *ifd;
> > + struct ifaddrs *ifap, *ifa;
> > + struct rt_tableinfo info;
> > +
> > + int rtt_dom[RT_TABLEID_MAX+1];
> > + int mib[6], rdom, rtt;
> > + size_t len;
> > + char *old, *rdom_if[RT_TABLEID_MAX+1] = { };
> > +
> > + getifaddrs(&ifap);
> > + for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> > + if (ifa->ifa_addr->sa_family != AF_LINK)
> > + continue;
> > + ifd = ifa->ifa_data;
> > + if (rdom_if[ifd->ifi_rdomain] == NULL) {
> > + if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s",
> > + ifa->ifa_name) == -1)
> > + exit(1);
> > + } else {
> > + old = rdom_if[ifd->ifi_rdomain];
> > + if (asprintf(&rdom_if[ifd->ifi_rdomain], "%s %s",
> > + old, ifa->ifa_name) == -1)
> > + exit(1);
> > + free(old);
> > + }
> > + }
> > + freeifaddrs(ifap);
> > +
> > + mib[0] = CTL_NET;
> > + mib[1] = PF_ROUTE;
> > + mib[2] = 0;
> > + mib[3] = 0;
> > + mib[4] = NET_RT_TABLE;
> > +
> > + len = sizeof(info);
> > + for (rtt = 0; rtt <= RT_TABLEID_MAX; rtt++) {
> > + mib[5] = rtt;
> > + if (sysctl(mib, 6, &info, &len, NULL, 0) == -1)
> > + rtt_dom[rtt] = -1;
> > + else
> > + rtt_dom[rtt] = info.rti_domainid;
> > + }
> > +
> > + for (rdom = 0; rdom <= RT_TABLEID_MAX; rdom++) {
> > + if (rdom_if[rdom] == NULL)
> > + continue;
> > + printf("Rdomain %i\n", rdom);
> > + printf(" Interfaces: %s\n", rdom_if[rdom]);
> > + printf(" Routing tables:\n");
> > + for (rtt = 0; rtt <= RT_TABLEID_MAX; rtt++) {
> > + if (rtt_dom[rtt] == rdom)
> > + rttsummarypr(rtt);
> > + }
> > + printf("\n");
> > + free(rdom_if[rdom]);
> > + }
> > +}
> > +
> > +void
> > +rttsummarypr(int tableid)
> > +{
> > + struct rt_msghdr *rtm;
> > + struct sockaddr *sa;
> > + char *buf = NULL, *next, *lim = NULL;
> > + size_t needed;
> > + int mib[7], mcnt;
> > + int inet = 0, inet6 = 0, mpls = 0;
> > +
> > + mib[0] = CTL_NET;
> > + mib[1] = PF_ROUTE;
> > + mib[2] = 0;
> > + mib[3] = af;
> > + mib[4] = NET_RT_DUMP;
> > + mib[5] = 0;
> > + mib[6] = tableid;
> > + mcnt = 7;
> > +
> > + needed = get_sysctl(mib, mcnt, &buf);
> > + lim = buf + needed;
> > +
> > + if (buf) {
> > + for (next = buf; next < lim; next += rtm->rtm_msglen) {
> > + rtm = (struct rt_msghdr *)next;
> > + if (rtm->rtm_version != RTM_VERSION)
> > + continue;
> > +
> > + sa = (struct sockaddr *)((char *)rtm + rtm->rtm_hdrlen);
> > + switch(sa->sa_family) {
> > + case AF_INET:
> > + inet++;
> > + break;
> > + case AF_INET6:
> > + inet6++;
> > + break;
> > + case AF_MPLS:
> > + mpls++;
> > + break;
> > + }
> > + }
> > + }
> > + free(buf);
> > +
> > + printf(" %3i: inet %7i, inet6 %7i, mpls %7i\n", tableid,
> > + inet, inet6, mpls);
> > }
> >
>
> --
> :wq Claudio
>