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
> 

Reply via email to