Remi Locherer([email protected]) on 2020.06.10 22:16:36 +0200:
> On Tue, Jun 09, 2020 at 10:02:06AM +0200, Remi Locherer wrote:
> > 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 did some homework and figured out, that dumping a routing table takes the
> NET_LOCK. So it's not just inefficient counting all routes in userland it
> might have a negative impact on the system.
> 
> Below my new proposal without the counters. I still think it would be good
> to have those counters. Maybe I'll try to find a solution for that.

Maybe sysctl NET_RT_STATS and struct rtstat could be expanded to cover this?

As for the diff, ok benno@. The number of routes is interesting but can be
added later.

/B.



 
> twister ..in/netstat$ obj/netstat -R 
> Rdomain 0
>   Interfaces: lo0 iwm0 re0 enc0 pflog0
>   Routing tables: 0 6 7 77
> 
> Rdomain 100
>   Interfaces: vether100 lo100 vether101 vether102 vether103 vether104 
> vether105 vether106 vether107 vether108 vether109
>   Routing tables: 100
> 
> Rdomain 255
>   Interfaces: vether255 lo255
>   Routing tables: 255
> 
> twister ..in/netstat$
> 
> 
> 
> 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 10 Jun 2020 20:08:28 -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,8 @@ void      rt_stats(void);
>  void pr_rthdr(int, int);
>  void pr_encaphdr(void);
>  void pr_family(int);
> +
> +void rdomainpr(void);
>  
>  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   10 Jun 2020 19:49:02 -0000
> @@ -51,6 +51,7 @@
>  #include <stdlib.h>
>  #include <string.h>
>  #include <unistd.h>
> +#include <ifaddrs.h>
>  
>  #include "netstat.h"
>  
> @@ -346,4 +347,69 @@ 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:");
> +             for (rtt = 0; rtt <= RT_TABLEID_MAX; rtt++) {
> +                     if (rtt_dom[rtt] == rdom)
> +                             printf(" %i", rtt);
> +             }
> +             printf("\n\n");
> +             free(rdom_if[rdom]);
> +     }
>  }
> 

Reply via email to