kern/167204: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Fri Dec 20 00:20:01 UTC 2013


The following reply was made to PR kern/167204; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at 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 at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-bugs mailing list