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.

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