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