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

From: dfil...@freebsd.org (dfilter service)
To: bug-follo...@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-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to