From eugen@grosbein.pp.ru  Sun Apr 22 14:06:06 2012
Return-Path: <eugen@grosbein.pp.ru>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 614C5106567B
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 22 Apr 2012 14:06:06 +0000 (UTC)
	(envelope-from eugen@grosbein.pp.ru)
Received: from grosbein.pp.ru (grosbein.pp.ru [89.189.172.146])
	by mx1.freebsd.org (Postfix) with ESMTP id 809608FC1E
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 22 Apr 2012 14:06:05 +0000 (UTC)
Received: from grosbein.pp.ru (localhost [127.0.0.1])
	by grosbein.pp.ru (8.14.5/8.14.5) with ESMTP id q3ME61J1003677
	for <FreeBSD-gnats-submit@freebsd.org>; Sun, 22 Apr 2012 21:06:01 +0700 (NOVT)
	(envelope-from eugen@grosbein.pp.ru)
Received: (from eugen@localhost)
	by grosbein.pp.ru (8.14.5/8.14.5/Submit) id q3ME61Gw003676;
	Sun, 22 Apr 2012 21:06:01 +0700 (NOVT)
	(envelope-from eugen)
Message-Id: <201204221406.q3ME61Gw003676@grosbein.pp.ru>
Date: Sun, 22 Apr 2012 21:06:01 +0700 (NOVT)
From: Eugene Grosbein <eugen@grosbein.net>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: terrible "netstat -rn" performance due to slow kvm_nlist()
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         167204
>Category:       kern
>Synopsis:       [kernel] terrible "netstat -rn" performance due to slow kvm_nlist()
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    melifaro
>State:          patched
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Apr 22 14:10:10 UTC 2012
>Closed-Date:    
>Last-Modified:  Fri Dec 20 00:21:53 UTC 2013
>Originator:     Eugene Grosbein
>Release:        FreeBSD 8.3-PRERELEASE i386
>Organization:
RDTC JSC
>Environment:
System: FreeBSD grosbein.pp.ru 8.3-PRERELEASE

>Description:

	My home router runs FreeBSD/i386 on AMD Geode:

%uname -a
FreeBSD gw.grosbein.pp.ru 8.3-PRERELEASE FreeBSD 8.3-PRERELEASE #1: Tue Mar  6 23:11:20 NOVT 2012     root@grosbein.pp.ru:/usr/local/obj/nanobsd.gw/i386/usr/local/src/sys/GW  i386
%grep CPU /var/run/dmesg.boot
CPU: Geode(TM) Integrated Processor by AMD PCS (499.91-MHz 586-class CPU)

	It has no IPv6 in the kernel config and pretty small routing table:

%sh -c 'time netstat -rn | wc -l'
        1.47 real         0.00 user         1.06 sys
      30

	As you can see, it takes more than a second
	for 'netstat -rn' to complete.

	Most of time it spends calling kldsym() system call
	from kvm_nlist() function:

%kdump | fgrep -c 'CALL  kldsym(0,KLDSYM_LOOKUP'
347

	For some unknown reason, the performace of this syscall is way too bad.

>How-To-Repeat:

	Run "time netstat -rn"

>Fix:

	Unknown
>Release-Note:
>Audit-Trail:

From: "Eugene M. Zheganin" <emz@zhegan.in>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/167204: [kernel] terrible "netstat -rn" performance due
 to slow kvm_nlist()
Date: Thu, 10 Oct 2013 14:12:43 +0600

 Still there, on 9.1 and same equipment.

From: Jilles Tjoelker <jilles@stack.nl>
To: bug-followup@FreeBSD.org, eugen@grosbein.net
Cc: "Eugene M. Zheganin" <emz@zhegan.in>
Subject: Re: kern/167204: [kernel] terrible "netstat -rn" performance due to
 slow kvm_nlist()
Date: Sun, 20 Oct 2013 00:15:33 +0200

 In PR kern/167204, you wrote:
 > ['netstat -rn' is extremely slow]
 
 On a machine here with a faster CPU, 'netstat -rn' takes about 100ms
 which I still consider very slow.
 
 I see two main causes of the slowness here:
 
 * kldsym(2) is very slow, particularly if debug symbols are loaded or on
   architectures such as amd64 that use 'ELF relocatable' as their kld
   module format (architectures such as i386 use 'ELF shared object'
   which has a hash table for non-debug symbols).
 
 * netstat(1) looks up all kernel symbols it could ever need, with all
   possible compile options, when it needs any kernel symbol. This
   appears to be the usual way to use libkvm but netstat is particularly
   egregious in the number of kernel symbols it may need.
 
 The below ugly patch (for head only; stable/10 has a simple conflict and
 stable/9 is full of conflicts) ensures the '-r' and '-rs' modes only
 look up the symbols necessary. This speeds up those modes considerably.
 
 Index: usr.bin/netstat/main.c
 ===================================================================
 --- usr.bin/netstat/main.c	(revision 256728)
 +++ usr.bin/netstat/main.c	(working copy)
 @@ -69,100 +69,108 @@
  #include <unistd.h>
  #include "netstat.h"
  
 +static struct nlist rs_nl[] = {
 +#define	RS_N_RTSTAT	0
 +	{ .n_name = "_rtstat" },
 +#define	RS_N_RTTRASH	1
 +	{ .n_name = "_rttrash" },
 +	{ .n_name = NULL },
 +};
 +
 +static struct nlist r_nl[] = {
 +#define	R_N_RTREE	0
 +	{ .n_name = "_rt_tables"},
 +	{ .n_name = NULL },
 +};
 +
  static struct nlist nl[] = {
  #define	N_IFNET		0
  	{ .n_name = "_ifnet" },		/* XXXGL: can be deleted */
 -#define	N_RTSTAT	1
 -	{ .n_name = "_rtstat" },
 -#define	N_RTREE		2
 -	{ .n_name = "_rt_tables"},
 -#define	N_MRTSTAT	3
 +#define	N_MRTSTAT	1
  	{ .n_name = "_mrtstat" },
 -#define	N_MFCHASHTBL	4
 +#define	N_MFCHASHTBL	2
  	{ .n_name = "_mfchashtbl" },
 -#define	N_VIFTABLE	5
 +#define	N_VIFTABLE	3
  	{ .n_name = "_viftable" },
 -#define	N_IPX		6
 +#define	N_IPX		3
  	{ .n_name = "_ipxpcb_list"},
 -#define	N_IPXSTAT	7
 +#define	N_IPXSTAT	4
  	{ .n_name = "_ipxstat"},
 -#define	N_SPXSTAT	8
 +#define	N_SPXSTAT	5
  	{ .n_name = "_spx_istat"},
 -#define	N_DDPSTAT	9
 +#define	N_DDPSTAT	6
  	{ .n_name = "_ddpstat"},
 -#define	N_DDPCB		10
 +#define	N_DDPCB		7
  	{ .n_name = "_ddpcb"},
 -#define	N_NGSOCKS	11
 +#define	N_NGSOCKS	8
  	{ .n_name = "_ngsocklist"},
 -#define	N_IP6STAT	12
 +#define	N_IP6STAT	9
  	{ .n_name = "_ip6stat" },
 -#define	N_ICMP6STAT	13
 +#define	N_ICMP6STAT	10
  	{ .n_name = "_icmp6stat" },
 -#define	N_IPSECSTAT	14
 +#define	N_IPSECSTAT	11
  	{ .n_name = "_ipsec4stat" },
 -#define	N_IPSEC6STAT	15
 +#define	N_IPSEC6STAT	12
  	{ .n_name = "_ipsec6stat" },
 -#define	N_PIM6STAT	16
 +#define	N_PIM6STAT	13
  	{ .n_name = "_pim6stat" },
 -#define	N_MRT6STAT	17
 +#define	N_MRT6STAT	14
  	{ .n_name = "_mrt6stat" },
 -#define	N_MF6CTABLE	18
 +#define	N_MF6CTABLE	15
  	{ .n_name = "_mf6ctable" },
 -#define	N_MIF6TABLE	19
 +#define	N_MIF6TABLE	16
  	{ .n_name = "_mif6table" },
 -#define	N_PFKEYSTAT	20
 +#define	N_PFKEYSTAT	17
  	{ .n_name = "_pfkeystat" },
 -#define	N_RTTRASH	21
 -	{ .n_name = "_rttrash" },
 -#define	N_CARPSTAT	22
 +#define	N_CARPSTAT	19
  	{ .n_name = "_carpstats" },
 -#define	N_PFSYNCSTAT	23
 +#define	N_PFSYNCSTAT	20
  	{ .n_name = "_pfsyncstats" },
 -#define	N_AHSTAT	24
 +#define	N_AHSTAT	21
  	{ .n_name = "_ahstat" },
 -#define	N_ESPSTAT	25
 +#define	N_ESPSTAT	22
  	{ .n_name = "_espstat" },
 -#define	N_IPCOMPSTAT	26
 +#define	N_IPCOMPSTAT	23
  	{ .n_name = "_ipcompstat" },
 -#define	N_TCPSTAT	27
 +#define	N_TCPSTAT	24
  	{ .n_name = "_tcpstat" },
 -#define	N_UDPSTAT	28
 +#define	N_UDPSTAT	25
  	{ .n_name = "_udpstat" },
 -#define	N_IPSTAT	29
 +#define	N_IPSTAT	26
  	{ .n_name = "_ipstat" },
 -#define	N_ICMPSTAT	30
 +#define	N_ICMPSTAT	27
  	{ .n_name = "_icmpstat" },
 -#define	N_IGMPSTAT	31
 +#define	N_IGMPSTAT	28
  	{ .n_name = "_igmpstat" },
 -#define	N_PIMSTAT	32
 +#define	N_PIMSTAT	29
  	{ .n_name = "_pimstat" },
 -#define	N_TCBINFO	33
 +#define	N_TCBINFO	30
  	{ .n_name = "_tcbinfo" },
 -#define	N_UDBINFO	34
 +#define	N_UDBINFO	31
  	{ .n_name = "_udbinfo" },
 -#define	N_DIVCBINFO	35
 +#define	N_DIVCBINFO	32
  	{ .n_name = "_divcbinfo" },
 -#define	N_RIPCBINFO	36
 +#define	N_RIPCBINFO	33
  	{ .n_name = "_ripcbinfo" },
 -#define	N_UNP_COUNT	37
 +#define	N_UNP_COUNT	34
  	{ .n_name = "_unp_count" },
 -#define	N_UNP_GENCNT	38
 +#define	N_UNP_GENCNT	35
  	{ .n_name = "_unp_gencnt" },
 -#define	N_UNP_DHEAD	39
 +#define	N_UNP_DHEAD	36
  	{ .n_name = "_unp_dhead" },
 -#define	N_UNP_SHEAD	40
 +#define	N_UNP_SHEAD	37
  	{ .n_name = "_unp_shead" },
 -#define	N_RIP6STAT	41
 +#define	N_RIP6STAT	38
  	{ .n_name = "_rip6stat" },
 -#define	N_SCTPSTAT	42
 +#define	N_SCTPSTAT	39
  	{ .n_name = "_sctpstat" },
 -#define	N_MFCTABLESIZE	43
 +#define	N_MFCTABLESIZE	40
  	{ .n_name = "_mfctablesize" },
 -#define	N_ARPSTAT       44
 +#define	N_ARPSTAT       41
  	{ .n_name = "_arpstat" },
 -#define	N_UNP_SPHEAD	45
 +#define	N_UNP_SPHEAD	42
  	{ .n_name = "unp_sphead" },
 -#define	N_SFSTAT	46
 +#define	N_SFSTAT	43
  	{ .n_name = "_sfstat"},
  	{ .n_name = NULL },
  };
 @@ -305,6 +313,8 @@
  static struct protox *name2protox(const char *);
  static struct protox *knownname(const char *);
  
 +static int kvmd_init(struct nlist *);
 +
  static kvm_t *kvmd;
  static char *nlistf = NULL, *memf = NULL;
  
 @@ -550,18 +560,22 @@
  	 * used for the queries, which is slower.
  	 */
  #endif
 +	if (rflag) {
 +		if (sflag) {
 +			kvmd_init(rs_nl);
 +			rt_stats(rs_nl[RS_N_RTSTAT].n_value,
 +			    rs_nl[RS_N_RTTRASH].n_value);
 +		} else {
 +			kvmd_init(r_nl);
 +			routepr(r_nl[R_N_RTREE].n_value, fib);
 +		}
 +		exit(0);
 +	}
  	kread(0, NULL, 0);
  	if (iflag && !sflag) {
  		intpr(interval, NULL);
  		exit(0);
  	}
 -	if (rflag) {
 -		if (sflag)
 -			rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
 -		else
 -			routepr(nl[N_RTREE].n_value, fib);
 -		exit(0);
 -	}
  	if (gflag) {
  		if (sflag) {
  			if (af == AF_INET || af == AF_UNSPEC)
 @@ -684,7 +698,7 @@
  }
  
  static int
 -kvmd_init(void)
 +kvmd_init(struct nlist *nl1)
  {
  	char errbuf[_POSIX2_LINE_MAX];
  
 @@ -699,7 +713,7 @@
  		return (-1);
  	}
  
 -	if (kvm_nlist(kvmd, nl) < 0) {
 +	if (kvm_nlist(kvmd, nl1) < 0) {
  		if (nlistf)
  			errx(1, "%s: kvm_nlist: %s", nlistf,
  			     kvm_geterr(kvmd));
 @@ -707,7 +721,7 @@
  			errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
  	}
  
 -	if (nl[0].n_type == 0) {
 +	if (nl1[0].n_type == 0) {
  		if (nlistf)
  			errx(1, "%s: no namelist", nlistf);
  		else
 @@ -724,7 +738,7 @@
  kread(u_long addr, void *buf, size_t size)
  {
  
 -	if (kvmd_init() < 0)
 +	if (kvmd_init(nl) < 0)
  		return (-1);
  
  	if (!buf)
 @@ -744,7 +758,7 @@
  {
  	uint64_t *c = buf;
  
 -	if (kvmd_init() < 0)
 +	if (kvmd_init(nl) < 0)
  		return (-1);
  
  	if (kread(addr, buf, size) < 0)
 
 -- 
 Jilles Tjoelker

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/167204: commit references a PR
Date: Wed, 18 Dec 2013 18:25:34 +0000 (UTC)

 Author: melifaro
 Date: Wed Dec 18 18:25:27 2013
 New Revision: 259562
 URL: http://svnweb.freebsd.org/changeset/base/259562
 
 Log:
   Switch netstat -rn to use standard API for retrieving list of routes
   instead of peeking inside in-kernel radix via kget.
   This permits us to change kernel structures without breaking userland.
   Additionally, this change provide more reliable and faster output.
   
   `Refs` and `Use` fields available in IPv4 by default (and via -W
   for other families) were removed. `Refs` is radix-specific thing
   which is not informative for users. `Use` field value is handy sometimes,
   but a) current API does not support it and b) I'm not sure we will
   support per-rte pcpu counters in near future.
   
   Old method of retrieving data is still supported (either by defining
   NewTree=0 or running netstat with -A). However, Refs/Use fields are
   hidden.
   
   Sponsored by:	Yandex LLC
   MFC after:	4 weeks
   PR:		kern/167204
 
 Modified:
   head/usr.bin/netstat/route.c
 
 Modified: head/usr.bin/netstat/route.c
 ==============================================================================
 --- head/usr.bin/netstat/route.c	Wed Dec 18 17:03:43 2013	(r259561)
 +++ head/usr.bin/netstat/route.c	Wed Dec 18 18:25:27 2013	(r259562)
 @@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/sysctl.h>
  
  #include <arpa/inet.h>
 +#include <ifaddrs.h>
  #include <libutil.h>
  #include <netdb.h>
  #include <stdint.h>
 @@ -113,13 +114,20 @@ typedef union {
  
  static sa_u pt_u;
  
 +struct ifmap_entry {
 +	char ifname[IFNAMSIZ];
 +};
 +
 +static struct ifmap_entry *ifmap;
 +static int ifmap_size;
 +
  int	do_rtent = 0;
  struct	rtentry rtentry;
  struct	radix_node rnode;
  struct	radix_mask rmask;
  struct	radix_node_head **rt_tables;
  
 -int	NewTree = 0;
 +int	NewTree = 1;
  
  struct	timespec uptime;
  
 @@ -129,7 +137,7 @@ static void size_cols_tree(struct radix_
  static void size_cols_rtentry(struct rtentry *rt);
  static void p_tree(struct radix_node *);
  static void p_rtnode(void);
 -static void ntreestuff(void);
 +static void ntreestuff(int fibnum, int af);
  static void np_rtentry(struct rt_msghdr *);
  static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
  static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
 @@ -175,7 +183,7 @@ routepr(u_long rtree, int fibnum)
  	printf("\n");
  
  	if (Aflag == 0 && NewTree)
 -		ntreestuff();
 +		ntreestuff(fibnum, af);
  	else {
  		if (rtree == 0) {
  			printf("rt_tables: symbol not in namelist\n");
 @@ -288,7 +296,7 @@ static int wid_if;
  static int wid_expire;
  
  static void
 -size_cols(int ef __unused, struct radix_node *rn)
 +size_cols(int ef, struct radix_node *rn)
  {
  	wid_dst = WID_DST_DEFAULT(ef);
  	wid_gw = WID_GW_DEFAULT(ef);
 @@ -299,7 +307,7 @@ size_cols(int ef __unused, struct radix_
  	wid_if = WID_IF_DEFAULT(ef);
  	wid_expire = 6;
  
 -	if (Wflag)
 +	if (Wflag && rn != NULL)
  		size_cols_tree(rn);
  }
  
 @@ -397,27 +405,14 @@ pr_rthdr(int af1)
  
  	if (Aflag)
  		printf("%-8.8s ","Address");
 -	if (af1 == AF_INET || Wflag) {
 -		if (Wflag) {
 -			printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n",
 -				wid_dst,	wid_dst,	"Destination",
 -				wid_gw,		wid_gw,		"Gateway",
 -				wid_flags,	wid_flags,	"Flags",
 -				wid_refs,	wid_refs,	"Refs",
 -				wid_use,	wid_use,	"Use",
 -				wid_mtu,	wid_mtu,	"Mtu",
 -				wid_if,		wid_if,		"Netif",
 -				wid_expire,			"Expire");
 -		} else {
 -			printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
 -				wid_dst,	wid_dst,	"Destination",
 -				wid_gw,		wid_gw,		"Gateway",
 -				wid_flags,	wid_flags,	"Flags",
 -				wid_refs,	wid_refs,	"Refs",
 -				wid_use,	wid_use,	"Use",
 -				wid_if,		wid_if,		"Netif",
 -				wid_expire,			"Expire");
 -		}
 +	if (Wflag) {
 +		printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*s\n",
 +			wid_dst,	wid_dst,	"Destination",
 +			wid_gw,		wid_gw,		"Gateway",
 +			wid_flags,	wid_flags,	"Flags",
 +			wid_mtu,	wid_mtu,	"Mtu",
 +			wid_if,		wid_if,		"Netif",
 +			wid_expire,			"Expire");
  	} else {
  		printf("%-*.*s %-*.*s %-*.*s  %*.*s %*s\n",
  			wid_dst,	wid_dst,	"Destination",
 @@ -522,20 +517,61 @@ p_rtnode(void)
  }
  
  static void
 -ntreestuff(void)
 +ntreestuff(int fibnum, int af)
  {
  	size_t needed;
 -	int mib[6];
 +	int mib[7];
  	char *buf, *next, *lim;
  	struct rt_msghdr *rtm;
 +	struct sockaddr *sa;
 +	int fam = 0, ifindex = 0, size;
 +
 +	struct ifaddrs *ifap, *ifa;
 +	struct sockaddr_dl *sdl;
 +
 +	/*
 +	 * Retrieve interface list at first
 +	 * since we need #ifindex -> if_xname match
 +	 */
 +	if (getifaddrs(&ifap) != 0)
 +		err(EX_OSERR, "getifaddrs");
 +
 +	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
 +		
 +		if (ifa->ifa_addr->sa_family != AF_LINK)
 +			continue;
 +
 +		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
 +		ifindex = sdl->sdl_index;
 +
 +		if (ifindex >= ifmap_size) {
 +			size = roundup(ifindex + 1, 32) *
 +			    sizeof(struct ifmap_entry);
 +			if ((ifmap = realloc(ifmap, size)) == NULL)
 +				errx(2, "realloc(%d) failed", size);
 +			memset(&ifmap[ifmap_size], 0,
 +			    size - ifmap_size *
 +			     sizeof(struct ifmap_entry));
 +
 +			ifmap_size = roundup(ifindex + 1, 32);
 +		}
 +
 +		if (*ifmap[ifindex].ifname != '\0')
 +			continue;
 +
 +		strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ);
 +	}
 +
 +	freeifaddrs(ifap);
  
  	mib[0] = CTL_NET;
  	mib[1] = PF_ROUTE;
  	mib[2] = 0;
 -	mib[3] = 0;
 +	mib[3] = af;
  	mib[4] = NET_RT_DUMP;
  	mib[5] = 0;
 -	if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
 +	mib[6] = fibnum;
 +	if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) {
  		err(1, "sysctl: net.route.0.0.dump estimate");
  	}
  
 @@ -548,6 +584,16 @@ ntreestuff(void)
  	lim  = buf + needed;
  	for (next = buf; next < lim; next += rtm->rtm_msglen) {
  		rtm = (struct rt_msghdr *)next;
 +		/*
 +		 * Peek inside header to determine AF
 +		 */
 +		sa = (struct sockaddr *)(rtm + 1);
 +		if (fam != sa->sa_family) {
 +			fam = sa->sa_family;
 +			size_cols(fam, NULL);
 +			pr_family(fam);
 +			pr_rthdr(fam);
 +		}
  		np_rtentry(rtm);
  	}
  }
 @@ -556,38 +602,52 @@ static void
  np_rtentry(struct rt_msghdr *rtm)
  {
  	struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
 -#ifdef notdef
 -	static int masks_done, banner_printed;
 -#endif
 -	static int old_af;
 -	int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
 +	char buffer[128];
 +	char prettyname[128];
 +	sa_u addr, mask, gw;
 +	unsigned int l;
 +
 +#define	GETSA(_s, _f)	{ \
 +	bzero(&(_s), sizeof(_s)); \
 +	if (rtm->rtm_addrs & _f) { \
 +		l = roundup(sa->sa_len, sizeof(long)); \
 +		memcpy(&(_s), sa, (l > sizeof(_s)) ? sizeof(_s) : l); \
 +		sa = (struct sockaddr *)((char *)sa + l); \
 +	} \
 +}
 +
 +	GETSA(addr, RTA_DST);
 +	GETSA(gw, RTA_GATEWAY);
 +	GETSA(mask, RTA_NETMASK);
 +	p_sockaddr(&addr.u_sa, &mask.u_sa, rtm->rtm_flags, wid_dst);
 +	p_sockaddr(&gw.u_sa, NULL, RTF_HOST, wid_gw);
  
 -#ifdef notdef
 -	/* for the moment, netmasks are skipped over */
 -	if (!banner_printed) {
 -		printf("Netmasks:\n");
 -		banner_printed = 1;
 -	}
 -	if (masks_done == 0) {
 -		if (rtm->rtm_addrs != RTA_DST ) {
 -			masks_done = 1;
 -			af1 = sa->sa_family;
 -		}
 -	} else
 -#endif
 -		af1 = sa->sa_family;
 -	if (af1 != old_af) {
 -		pr_family(af1);
 -		old_af = af1;
 +	snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
 +	p_flags(rtm->rtm_flags, buffer);
 +	if (Wflag) {
 +		if (rtm->rtm_rmx.rmx_mtu != 0)
 +			printf("%*lu ", wid_mtu, rtm->rtm_rmx.rmx_mtu);
 +		else
 +			printf("%*s ", wid_mtu, "");
  	}
 -	if (rtm->rtm_addrs == RTA_DST)
 -		p_sockaddr(sa, NULL, 0, 36);
 -	else {
 -		p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
 -		sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
 -		p_sockaddr(sa, NULL, 0, 18);
 +
 +	memset(prettyname, 0, sizeof(prettyname));
 +	if (rtm->rtm_index < ifmap_size) {
 +		strlcpy(prettyname, ifmap[rtm->rtm_index].ifname,
 +		    sizeof(prettyname));
 +		if (*prettyname == '\0')
 +			strlcpy(prettyname, "---", sizeof(prettyname));
  	}
 -	p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
 +
 +	printf("%*.*s", wid_if, wid_if, prettyname);
 +	if (rtm->rtm_rmx.rmx_expire) {
 +		time_t expire_time;
 +
 +		if ((expire_time =
 +		    rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0)
 +			printf(" %*d", wid_expire, (int)expire_time);
 +	}
 +
  	putchar('\n');
  }
  
 @@ -775,8 +835,10 @@ p_rtentry(struct rtentry *rt)
  	snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
  	p_flags(rt->rt_flags, buffer);
  	if (addr.u_sa.sa_family == AF_INET || Wflag) {
 +#if 0
  		printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
  				     wid_use, rt->rt_use);
 +#endif
  		if (Wflag) {
  			if (rt->rt_rmx.rmx_mtu != 0)
  				printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/167204: commit references a PR
Date: Fri, 20 Dec 2013 00:17:36 +0000 (UTC)

 Author: melifaro
 Date: Fri Dec 20 00:17:26 2013
 New Revision: 259638
 URL: http://svnweb.freebsd.org/changeset/base/259638
 
 Log:
   Use more fine-grained kvm(3) symbol lookup: routing code retrieves only
   necessary symbols needed per subsystem. Main kvm(3) init is now delayed
   as much as possbile. This finally fixes performance issues reported in
   kern/167204.
   Some non-working code (ng_socket.ko symbol addresses calculation) removed.
   Some global variables eliminated.
   
   PR:		kern/167204
   MFC after:	4 weeks
 
 Modified:
   head/usr.bin/netstat/if.c
   head/usr.bin/netstat/main.c
   head/usr.bin/netstat/mroute.c
   head/usr.bin/netstat/mroute6.c
   head/usr.bin/netstat/netgraph.c
   head/usr.bin/netstat/netstat.h
   head/usr.bin/netstat/route.c
 
 Modified: head/usr.bin/netstat/if.c
 ==============================================================================
 --- head/usr.bin/netstat/if.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/if.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -223,7 +223,7 @@ next_ifma(struct ifmaddrs *ifma, const c
   * Print a description of the network interfaces.
   */
  void
 -intpr(int interval, void (*pfunc)(char *))
 +intpr(int interval, void (*pfunc)(char *), int af)
  {
  	struct ifaddrs *ifap, *ifa;
  	struct ifmaddrs *ifmap, *ifma;
 
 Modified: head/usr.bin/netstat/main.c
 ==============================================================================
 --- head/usr.bin/netstat/main.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/main.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -319,7 +319,6 @@ int	gflag;		/* show group (multicast) ro
  int	hflag;		/* show counters in human readable format */
  int	iflag;		/* show interfaces */
  int	Lflag;		/* show size of listen queues */
 -int	Mflag;		/* read statistics from core */
  int	mflag;		/* show memory stats */
  int	noutputs = 0;	/* how much outputs before we exit */
  int	numeric_addr;	/* show addresses numerically */
 @@ -425,7 +424,6 @@ main(int argc, char *argv[])
  			Lflag = 1;
  			break;
  		case 'M':
 -			Mflag = 1;
  			memf = optarg;
  			break;
  		case 'm':
 @@ -554,40 +552,40 @@ main(int argc, char *argv[])
  	 * used for the queries, which is slower.
  	 */
  #endif
 -	kread(0, NULL, 0);
  	if (iflag && !sflag) {
 -		intpr(interval, NULL);
 +		intpr(interval, NULL, af);
  		exit(0);
  	}
  	if (rflag) {
  		if (sflag)
 -			rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
 +			rt_stats();
  		else
 -			routepr(nl[N_RTREE].n_value, fib);
 +			routepr(fib, af);
  		exit(0);
  	}
 +
  	if (gflag) {
  		if (sflag) {
  			if (af == AF_INET || af == AF_UNSPEC)
 -				mrt_stats(nl[N_MRTSTAT].n_value);
 +				mrt_stats();
  #ifdef INET6
  			if (af == AF_INET6 || af == AF_UNSPEC)
 -				mrt6_stats(nl[N_MRT6STAT].n_value);
 +				mrt6_stats();
  #endif
  		} else {
  			if (af == AF_INET || af == AF_UNSPEC)
 -				mroutepr(nl[N_MFCHASHTBL].n_value,
 -					 nl[N_MFCTABLESIZE].n_value,
 -					 nl[N_VIFTABLE].n_value);
 +				mroutepr();
  #ifdef INET6
  			if (af == AF_INET6 || af == AF_UNSPEC)
 -				mroute6pr(nl[N_MF6CTABLE].n_value,
 -					  nl[N_MIF6TABLE].n_value);
 +				mroute6pr();
  #endif
  		}
  		exit(0);
  	}
  
 +	/* Load all necessary kvm symbols */
 +	kresolve_list(nl);
 +
  	if (tp) {
  		printproto(tp, tp->pr_name);
  		exit(0);
 @@ -640,7 +638,7 @@ printproto(struct protox *tp, const char
  	if (sflag) {
  		if (iflag) {
  			if (tp->pr_istats)
 -				intpr(interval, tp->pr_istats);
 +				intpr(interval, tp->pr_istats, af);
  			else if (pflag)
  				printf("%s: no per-interface stats routine\n",
  				    tp->pr_name);
 @@ -703,7 +701,23 @@ kvmd_init(void)
  		return (-1);
  	}
  
 -	if (kvm_nlist(kvmd, nl) < 0) {
 +	return (0);
 +}
 +
 +/*
 + * Resolve symbol list, return 0 on success.
 + */
 +int
 +kresolve_list(struct nlist *_nl)
 +{
 +
 +	if ((kvmd == NULL) && (kvmd_init() != 0))
 +		return (-1);
 +
 +	if (_nl[0].n_type != 0)
 +		return (0);
 +
 +	if (kvm_nlist(kvmd, _nl) < 0) {
  		if (nlistf)
  			errx(1, "%s: kvm_nlist: %s", nlistf,
  			     kvm_geterr(kvmd));
 @@ -711,13 +725,6 @@ kvmd_init(void)
  			errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
  	}
  
 -	if (nl[0].n_type == 0) {
 -		if (nlistf)
 -			errx(1, "%s: no namelist", nlistf);
 -		else
 -			errx(1, "no namelist");
 -	}
 -
  	return (0);
  }
  
 
 Modified: head/usr.bin/netstat/mroute.c
 ==============================================================================
 --- head/usr.bin/netstat/mroute.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/mroute.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -65,11 +65,26 @@ __FBSDID("$FreeBSD$");
  #undef _KERNEL
  
  #include <err.h>
 +#include <nlist.h>
  #include <stdint.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include "netstat.h"
  
 +/*
 + * kvm(3) bindings for every needed symbol
 + */
 +static struct nlist mrl[] = {
 +#define	N_MRTSTAT	0
 +	{ .n_name = "_mrtstat" },
 +#define	N_MFCHASHTBL	1
 +	{ .n_name = "_mfchashtbl" },
 +#define	N_VIFTABLE	2
 +	{ .n_name = "_viftable" },
 +#define	N_MFCTABLESIZE	3
 +	{ .n_name = "_mfctablesize" },
 +	{ .n_name = NULL },
 +};
  
  static void	print_bw_meter(struct bw_meter *, int *);
  static void	print_mfc(struct mfc *, int, int *);
 @@ -193,11 +208,12 @@ print_mfc(struct mfc *m, int maxvif, int
  }
  
  void
 -mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
 +mroutepr()
  {
  	struct vif viftable[MAXVIFS];
  	struct vif *v;
  	struct mfc *m;
 +	u_long pmfchashtbl, pmfctablesize, pviftbl;
  	int banner_printed;
  	int saved_numeric_addr;
  	size_t len;
 @@ -221,6 +237,16 @@ mroutepr(u_long pmfchashtbl, u_long pmfc
  	 */
  	maxvif = 0;
  
 +	kresolve_list(mrl);
 +	pmfchashtbl = mrl[N_MFCHASHTBL].n_value;
 +	pmfctablesize = mrl[N_MFCTABLESIZE].n_value;
 +	pviftbl = mrl[N_VIFTABLE].n_value;
 +
 +	if (pmfchashtbl == 0 || pmfctablesize == 0 || pviftbl == 0) {
 +		fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
 +		return;
 +	}
 +
  	len = sizeof(viftable);
  	if (live) {
  		if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
 @@ -338,15 +364,24 @@ mroutepr(u_long pmfchashtbl, u_long pmfc
  }
  
  void
 -mrt_stats(u_long mstaddr)
 +mrt_stats()
  {
  	struct mrtstat mrtstat;
 -	size_t len = sizeof mrtstat;
 +	u_long mstaddr;
 +	size_t len = sizeof(mrtstat);
 +
 +	kresolve_list(mrl);
 +	mstaddr = mrl[N_MRTSTAT].n_value;
 +
 +	if (mstaddr == 0) {
 +		fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
 +		return;
 +	}
  
  	if (live) {
  		if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
  		    0) < 0) {
 -			warn("sysctl: net.inet.ip.mrtstat");
 +			warn("sysctl: net.inet.ip.mrtstat failed.");
  			return;
  		}
  	} else
 
 Modified: head/usr.bin/netstat/mroute6.c
 ==============================================================================
 --- head/usr.bin/netstat/mroute6.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/mroute6.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
  #include <netinet/in.h>
  
  #include <err.h>
 +#include <nlist.h>
  #include <stdint.h>
  #include <stdio.h>
  #include <stdlib.h>
 @@ -95,17 +96,32 @@ __FBSDID("$FreeBSD$");
  
  #include "netstat.h"
  
 +/*
 + * kvm(3) bindings for every needed symbol
 + */
 +static struct nlist mrl[] = {
 +#define	N_MF6CTABLE	0
 +	{ .n_name = "_mf6ctable" },
 +#define	N_MIF6TABLE	1
 +	{ .n_name = "_mif6table" },
 +#define	N_MRT6STAT	2
 +	{ .n_name = "_mrt6stat" },
 +	{ .n_name = NULL },
 +};
 +
 +
  #define	WID_ORG	(Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
  #define	WID_GRP	(Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
  
  void
 -mroute6pr(u_long mfcaddr, u_long mifaddr)
 +mroute6pr()
  {
  	struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
  	struct mif6 mif6table[MAXMIFS];
  	struct mf6c mfc;
  	struct rtdetq rte, *rtep;
  	struct mif6 *mifp;
 +	u_long mfcaddr, mifaddr;
  	mifi_t mifi;
  	int i;
  	int banner_printed;
 @@ -114,6 +130,15 @@ mroute6pr(u_long mfcaddr, u_long mifaddr
  	long int waitings;
  	size_t len;
  
 +	kresolve_list(mrl);
 +	mfcaddr = mrl[N_MF6CTABLE].n_value;
 +	mifaddr = mrl[N_MIF6TABLE].n_value;
 +
 +	if (mfcaddr == 0 || mifaddr == 0) {
 +		fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
 +		return;
 +	}
 +
  	len = sizeof(mif6table);
  	if (live) {
  		if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
 @@ -217,11 +242,20 @@ mroute6pr(u_long mfcaddr, u_long mifaddr
  }
  
  void
 -mrt6_stats(u_long mstaddr)
 +mrt6_stats()
  {
  	struct mrt6stat mrtstat;
 +	u_long mstaddr;
  	size_t len = sizeof mrtstat;
  
 +	kresolve_list(mrl);
 +	mstaddr = mrl[N_MRT6STAT].n_value;
 +
 +	if (mstaddr == 0) {
 +		fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
 +		return;
 +	}
 +
  	if (live) {
  		if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
  		    NULL, 0) < 0) {
 
 Modified: head/usr.bin/netstat/netgraph.c
 ==============================================================================
 --- head/usr.bin/netstat/netgraph.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/netgraph.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -72,53 +72,10 @@ netgraphprotopr(u_long off, const char *
  
  	/* If symbol not found, try looking in the KLD module */
  	if (off == 0) {
 -		const char *const modname = "ng_socket.ko";
 -/* XXX We should get "mpath" from "sysctl kern.module_path" */
 -		const char *mpath[] = { "/", "/boot/", "/modules/", NULL };
 -		struct nlist sym[] = { { .n_name = "_ngsocklist" },
 -				       { .n_name = NULL } };
 -		const char **pre;
 -		struct kld_file_stat ks;
 -		int fileid;
 -
 -		/* Can't do this for core dumps. */
 -		if (!live)
 -			return;
 -
 -		/* See if module is loaded */
 -		if ((fileid = kldfind(modname)) < 0) {
 -			if (debug)
 -				warn("kldfind(%s)", modname);
 -			return;
 -		}
 -
 -		/* Get module info */
 -		memset(&ks, 0, sizeof(ks));
 -		ks.version = sizeof(struct kld_file_stat);
 -		if (kldstat(fileid, &ks) < 0) {
 -			if (debug)
 -				warn("kldstat(%d)", fileid);
 -			return;
 -		}
 -
 -		/* Get symbol table from module file */
 -		for (pre = mpath; *pre; pre++) {
 -			char path[MAXPATHLEN];
 -
 -			snprintf(path, sizeof(path), "%s%s", *pre, modname);
 -			if (nlist(path, sym) == 0)
 -				break;
 -		}
 -
 -		/* Did we find it? */
 -		if (sym[0].n_value == 0) {
 -			if (debug)
 -				warnx("%s not found", modname);
 -			return;
 -		}
 -
 -		/* Symbol found at load address plus symbol offset */
 -		off = (u_long) ks.address + sym[0].n_value;
 +		if (debug)
 +			fprintf(stderr,
 +			    "Error reading symbols from ng_socket.ko");
 +		return;
  	}
  
  	/* Get pointer to first socket */
 
 Modified: head/usr.bin/netstat/netstat.h
 ==============================================================================
 --- head/usr.bin/netstat/netstat.h	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/netstat.h	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -40,7 +40,6 @@ extern int	gflag;	/* show group (multica
  extern int	hflag;	/* show counters in human readable format */
  extern int	iflag;	/* show interfaces */
  extern int	Lflag;	/* show size of listen queues */
 -extern int	Mflag;	/* read statistics from core */
  extern int	mflag;	/* show memory stats */
  extern int	noutputs;	/* how much outputs before we exit */
  extern int	numeric_addr;	/* show addresses numerically */
 @@ -57,11 +56,12 @@ extern int	interval; /* repeat interval 
  extern char	*interface; /* desired i/f for stats, or NULL for all i/fs */
  extern int	unit;	/* unit number for above */
  
 -extern int	af;	/* address family */
  extern int	live;	/* true if we are examining a live system */
  
 +struct nlist;
  int	kread(u_long addr, void *buf, size_t size);
  int	kread_counters(u_long addr, void *buf, size_t size);
 +int	kresolve_list(struct nlist *);
  const char *plural(uintmax_t);
  const char *plurales(uintmax_t);
  const char *pluralies(uintmax_t);
 @@ -98,8 +98,8 @@ void	icmp6_stats(u_long, const char *, i
  void	icmp6_ifstats(char *);
  void	pim6_stats(u_long, const char *, int, int);
  void	rip6_stats(u_long, const char *, int, int);
 -void	mroute6pr(u_long, u_long);
 -void	mrt6_stats(u_long);
 +void	mroute6pr(void);
 +void	mrt6_stats(void);
  
  struct sockaddr_in6;
  struct in6_addr;
 @@ -120,11 +120,11 @@ void	netisr_stats(void *);
  void	hostpr(u_long, u_long);
  void	impstats(u_long, u_long);
  
 -void	intpr(int, void (*)(char *));
 +void	intpr(int, void (*)(char *), int);
  
  void	pr_rthdr(int);
  void	pr_family(int);
 -void	rt_stats(u_long, u_long);
 +void	rt_stats(void);
  char	*ipx_pnet(struct sockaddr *);
  char	*ipx_phost(struct sockaddr *);
  char	*ns_phost(struct sockaddr *);
 @@ -136,7 +136,7 @@ char	*atalk_print(struct sockaddr *, int
  char	*atalk_print2(struct sockaddr *, struct sockaddr *, int);
  char	*ipx_print(struct sockaddr *);
  char	*ns_print(struct sockaddr *);
 -void	routepr(u_long, int);
 +void	routepr(int, int);
  
  void	ipxprotopr(u_long, const char *, int, int);
  void	spx_stats(u_long, const char *, int, int);
 @@ -166,6 +166,6 @@ void	tp_protopr(u_long, const char *, in
  void	tp_inproto(u_long);
  void	tp_stats(caddr_t, caddr_t);
  
 -void	mroutepr(u_long, u_long, u_long);
 -void	mrt_stats(u_long);
 +void	mroutepr(void);
 +void	mrt_stats(void);
  void	bpf_stats(char *);
 
 Modified: head/usr.bin/netstat/route.c
 ==============================================================================
 --- head/usr.bin/netstat/route.c	Fri Dec 20 00:09:14 2013	(r259637)
 +++ head/usr.bin/netstat/route.c	Fri Dec 20 00:17:26 2013	(r259638)
 @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
  #include <ifaddrs.h>
  #include <libutil.h>
  #include <netdb.h>
 +#include <nlist.h>
  #include <stdint.h>
  #include <stdio.h>
  #include <stdlib.h>
 @@ -106,6 +107,19 @@ struct bits {
  	{ 0 , 0 }
  };
  
 +/*
 + * kvm(3) bindings for every needed symbol
 + */
 +static struct nlist rl[] = {
 +#define	N_RTSTAT	0
 +	{ .n_name = "_rtstat" },
 +#define	N_RTREE		1
 +	{ .n_name = "_rt_tables"},
 +#define	N_RTTRASH	2
 +	{ .n_name = "_rttrash" },
 +	{ .n_name = NULL },
 +};
 +
  typedef union {
  	long	dummy;		/* Helps align structure. */
  	struct	sockaddr u_sa;
 @@ -151,9 +165,10 @@ static void domask(char *, in_addr_t, u_
   * Print routing tables.
   */
  void
 -routepr(u_long rtree, int fibnum)
 +routepr(int fibnum, int af)
  {
  	struct radix_node_head **rnhp, *rnh, head;
 +	u_long rtree;
  	size_t intsize;
  	int fam, numfibs;
  
 @@ -165,10 +180,6 @@ routepr(u_long rtree, int fibnum)
  		numfibs = 1;
  	if (fibnum < 0 || fibnum > numfibs - 1)
  		errx(EX_USAGE, "%d: invalid fib", fibnum);
 -	rt_tables = calloc(numfibs * (AF_MAX+1),
 -	    sizeof(struct radix_node_head *));
 -	if (rt_tables == NULL)
 -		err(EX_OSERR, "memory allocation failed");
  	/*
  	 * Since kernel & userland use different timebase
  	 * (time_uptime vs time_second) and we are reading kernel memory
 @@ -182,14 +193,20 @@ routepr(u_long rtree, int fibnum)
  		printf(" (fib: %d)", fibnum);
  	printf("\n");
  
 -	if (Aflag == 0 && Mflag == 0 && NewTree)
 +	if (Aflag == 0 && live != 0 && NewTree)
  		ntreestuff(fibnum, af);
  	else {
 -		if (rtree == 0) {
 +		kresolve_list(rl);
 +		if ((rtree = rl[N_RTREE].n_value) == 0) {
  			printf("rt_tables: symbol not in namelist\n");
  			return;
  		}
  
 +		rt_tables = calloc(numfibs * (AF_MAX + 1),
 +		    sizeof(struct radix_node_head *));
 +		if (rt_tables == NULL)
 +			err(EX_OSERR, "memory allocation failed");
 +
  		if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
  		    (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
  			return;
 @@ -572,14 +589,14 @@ ntreestuff(int fibnum, int af)
  	mib[5] = 0;
  	mib[6] = fibnum;
  	if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) {
 -		err(1, "sysctl: net.route.0.0.dump estimate");
 +		err(1, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum);
  	}
  
  	if ((buf = malloc(needed)) == 0) {
  		errx(2, "malloc(%lu)", (unsigned long)needed);
  	}
  	if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
 -		err(1, "sysctl: net.route.0.0.dump");
 +		err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum);
  	}
  	lim  = buf + needed;
  	for (next = buf; next < lim; next += rtm->rtm_msglen) {
 @@ -1071,16 +1088,19 @@ routename6(struct sockaddr_in6 *sa6)
   * Print routing statistics
   */
  void
 -rt_stats(u_long rtsaddr, u_long rttaddr)
 +rt_stats(void)
  {
  	struct rtstat rtstat;
 +	u_long rtsaddr, rttaddr;
  	int rttrash;
  
 -	if (rtsaddr == 0) {
 +	kresolve_list(rl);
 +
 +	if ((rtsaddr = rl[N_RTSTAT].n_value) == 0) {
  		printf("rtstat: symbol not in namelist\n");
  		return;
  	}
 -	if (rttaddr == 0) {
 +	if ((rttaddr = rl[N_RTTRASH].n_value) == 0) {
  		printf("rttrash: symbol not in namelist\n");
  		return;
  	}
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: melifaro 
State-Changed-When: Fri Dec 20 00:20:52 UTC 2013 
State-Changed-Why:  
Fixed in head. 


Responsible-Changed-From-To: freebsd-bugs->melifaro 
Responsible-Changed-By: melifaro 
Responsible-Changed-When: Fri Dec 20 00:20:52 UTC 2013 
Responsible-Changed-Why:  

http://www.freebsd.org/cgi/query-pr.cgi?pr=167204 
>Unformatted:
