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. 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]); + } }