Author: rwatson
Date: Mon Feb 22 15:03:16 2010
New Revision: 204199
URL: http://svn.freebsd.org/changeset/base/204199

Log:
  Export netisr configuration and statistics to userspace via sysctl(9).
  
  MFC after:    1 week
  Sponsored by: Juniper Networks

Modified:
  head/sys/net/netisr.c
  head/sys/net/netisr.h

Modified: head/sys/net/netisr.c
==============================================================================
--- head/sys/net/netisr.c       Mon Feb 22 14:49:52 2010        (r204198)
+++ head/sys/net/netisr.c       Mon Feb 22 15:03:16 2010        (r204199)
@@ -1,7 +1,11 @@
 /*-
  * Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010 Juniper Networks, Inc.
  * All rights reserved.
  *
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -1126,6 +1130,170 @@ netisr_start(void *arg)
 }
 SYSINIT(netisr_start, SI_SUB_SMP, SI_ORDER_MIDDLE, netisr_start, NULL);
 
+/*
+ * Sysctl monitoring for netisr: query a list of registered protocols.
+ */
+static int
+sysctl_netisr_proto(SYSCTL_HANDLER_ARGS)
+{
+       struct rm_priotracker tracker;
+       struct sysctl_netisr_proto *snpp, *snp_array;
+       struct netisr_proto *npp;
+       u_int counter, proto;
+       int error;
+
+       if (req->newptr != NULL)
+               return (EINVAL);
+       snp_array = malloc(sizeof(*snp_array) * NETISR_MAXPROT, M_TEMP,
+           M_ZERO | M_WAITOK);
+       counter = 0;
+       NETISR_RLOCK(&tracker);
+       for (proto = 0; proto < NETISR_MAXPROT; proto++) {
+               npp = &np[proto];
+               if (npp->np_name == NULL)
+                       continue;
+               snpp = &snp_array[counter];
+               snpp->snp_version = sizeof(*snpp);
+               strlcpy(snpp->snp_name, npp->np_name, NETISR_NAMEMAXLEN);
+               snpp->snp_proto = proto;
+               snpp->snp_qlimit = npp->np_qlimit;
+               snpp->snp_policy = npp->np_policy;
+               if (npp->np_m2flow != NULL)
+                       snpp->snp_flags |= NETISR_SNP_FLAGS_M2FLOW;
+               if (npp->np_m2cpuid != NULL)
+                       snpp->snp_flags |= NETISR_SNP_FLAGS_M2CPUID;
+               if (npp->np_drainedcpu != NULL)
+                       snpp->snp_flags |= NETISR_SNP_FLAGS_DRAINEDCPU;
+               counter++;
+       }
+       NETISR_RUNLOCK(&tracker);
+       KASSERT(counter < NETISR_MAXPROT,
+           ("sysctl_netisr_proto: counter too big (%d)", counter));
+       error = SYSCTL_OUT(req, snp_array, sizeof(*snp_array) * counter);
+       free(snp_array, M_TEMP);
+       return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, proto,
+    CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_proto,
+    "S,sysctl_netisr_proto",
+    "Return list of protocols registered with netisr");
+
+/*
+ * Sysctl monitoring for netisr: query a list of workstreams.
+ */
+static int
+sysctl_netisr_workstream(SYSCTL_HANDLER_ARGS)
+{
+       struct rm_priotracker tracker;
+       struct sysctl_netisr_workstream *snwsp, *snws_array;
+       struct netisr_workstream *nwsp;
+       u_int counter, cpuid;
+       int error;
+
+       if (req->newptr != NULL)
+               return (EINVAL);
+       snws_array = malloc(sizeof(*snws_array) * MAXCPU, M_TEMP,
+           M_ZERO | M_WAITOK);
+       counter = 0;
+       NETISR_RLOCK(&tracker);
+       for (cpuid = 0; cpuid < MAXCPU; cpuid++) {
+               if (CPU_ABSENT(cpuid))
+                       continue;
+               nwsp = DPCPU_ID_PTR(cpuid, nws);
+               if (nwsp->nws_intr_event == NULL)
+                       continue;
+               NWS_LOCK(nwsp);
+               snwsp = &snws_array[counter];
+               snwsp->snws_version = sizeof(*snwsp);
+
+               /*
+                * For now, we equate workstream IDs and CPU IDs in the
+                * kernel, but expose them independently to userspace in case
+                * that assumption changes in the future.
+                */
+               snwsp->snws_wsid = cpuid;
+               snwsp->snws_cpu = cpuid;
+               if (nwsp->nws_intr_event != NULL)
+                       snwsp->snws_flags |= NETISR_SNWS_FLAGS_INTR;
+               NWS_UNLOCK(nwsp);
+               counter++;
+       }
+       NETISR_RUNLOCK(&tracker);
+       KASSERT(counter < MAXCPU,
+           ("sysctl_netisr_workstream: counter too big (%d)", counter));
+       error = SYSCTL_OUT(req, snws_array, sizeof(*snws_array) * counter);
+       free(snws_array, M_TEMP);
+       return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, workstream,
+    CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_workstream,
+    "S,sysctl_netisr_workstream",
+    "Return list of workstreams implemented by netisr");
+
+/*
+ * Sysctl monitoring for netisr: query per-protocol data across all
+ * workstreams.
+ */
+static int
+sysctl_netisr_work(SYSCTL_HANDLER_ARGS)
+{
+       struct rm_priotracker tracker;
+       struct sysctl_netisr_work *snwp, *snw_array;
+       struct netisr_workstream *nwsp;
+       struct netisr_proto *npp;
+       struct netisr_work *nwp;
+       u_int counter, cpuid, proto;
+       int error;
+
+       if (req->newptr != NULL)
+               return (EINVAL);
+       snw_array = malloc(sizeof(*snw_array) * MAXCPU * NETISR_MAXPROT,
+           M_TEMP, M_ZERO | M_WAITOK);
+       counter = 0;
+       NETISR_RLOCK(&tracker);
+       for (cpuid = 0; cpuid < MAXCPU; cpuid++) {
+               if (CPU_ABSENT(cpuid))
+                       continue;
+               nwsp = DPCPU_ID_PTR(cpuid, nws);
+               if (nwsp->nws_intr_event == NULL)
+                       continue;
+               NWS_LOCK(nwsp);
+               for (proto = 0; proto < NETISR_MAXPROT; proto++) {
+                       npp = &np[proto];
+                       if (npp->np_name == NULL)
+                               continue;
+                       nwp = &nwsp->nws_work[proto];
+                       snwp = &snw_array[counter];
+                       snwp->snw_version = sizeof(*snwp);
+                       snwp->snw_wsid = cpuid;         /* See comment above. */
+                       snwp->snw_proto = proto;
+                       snwp->snw_len = nwp->nw_len;
+                       snwp->snw_watermark = nwp->nw_watermark;
+                       snwp->snw_dispatched = nwp->nw_dispatched;
+                       snwp->snw_hybrid_dispatched =
+                           nwp->nw_hybrid_dispatched;
+                       snwp->snw_qdrops = nwp->nw_qdrops;
+                       snwp->snw_queued = nwp->nw_queued;
+                       snwp->snw_handled = nwp->nw_handled;
+                       counter++;
+               }
+               NWS_UNLOCK(nwsp);
+       }
+       KASSERT(counter < MAXCPU * NETISR_MAXPROT,
+           ("sysctl_netisr_work: counter too big (%d)", counter));
+       NETISR_RUNLOCK(&tracker);
+       error = SYSCTL_OUT(req, snw_array, sizeof(*snw_array) * counter);
+       free(snw_array, M_TEMP);
+       return (error);
+}
+
+SYSCTL_PROC(_net_isr, OID_AUTO, work,
+    CTLFLAG_RD|CTLTYPE_STRUCT|CTLFLAG_MPSAFE, 0, 0, sysctl_netisr_work,
+    "S,sysctl_netisr_work",
+    "Return list of per-workstream, per-protocol work in netisr");
+
 #ifdef DDB
 DB_SHOW_COMMAND(netisr, db_show_netisr)
 {

Modified: head/sys/net/netisr.h
==============================================================================
--- head/sys/net/netisr.h       Mon Feb 22 14:49:52 2010        (r204198)
+++ head/sys/net/netisr.h       Mon Feb 22 15:03:16 2010        (r204199)
@@ -1,7 +1,11 @@
 /*-
  * Copyright (c) 2007-2009 Robert N. M. Watson
+ * Copyright (c) 2010 Juniper Networks, Inc.
  * All rights reserved.
  *
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -28,7 +32,6 @@
 
 #ifndef _NET_NETISR_H_
 #define _NET_NETISR_H_
-#ifdef _KERNEL
 
 /*
  * The netisr (network interrupt service routine) provides a deferred
@@ -39,6 +42,13 @@
  * Historically, this was implemented by the BSD software ISR facility; it is
  * now implemented via a software ithread (SWI).
  */
+
+/*
+ * Protocol numbers, which are encoded in monitoring applications and kernel
+ * modules.  Internally, these are used in bit shift operations so must have
+ * a value 0 < proto < 32; we currently further limit at compile-time to 16
+ * for array-sizing purposes.
+ */
 #define        NETISR_IP       1
 #define        NETISR_IGMP     2               /* IGMPv3 output queue */
 #define        NETISR_ROUTE    3               /* routing socket */
@@ -52,6 +62,78 @@
 #define        NETISR_NATM     11
 #define        NETISR_EPAIR    12              /* if_epair(4) */
 
+/*
+ * Protocol ordering and affinity policy constants.  See the detailed
+ * discussion of policies later in the file.
+ */
+#define        NETISR_POLICY_SOURCE    1       /* Maintain source ordering. */
+#define        NETISR_POLICY_FLOW      2       /* Maintain flow ordering. */
+#define        NETISR_POLICY_CPU       3       /* Protocol determines CPU 
placement. */
+
+/*
+ * Monitoring data structures, exported by sysctl(2).
+ *
+ * Three sysctls are defined.  First, a per-protocol structure exported by
+ * net.isr.proto.
+ */
+#define        NETISR_NAMEMAXLEN       32
+struct sysctl_netisr_proto {
+       u_int   snp_version;                    /* Length of struct. */
+       char    snp_name[NETISR_NAMEMAXLEN];    /* nh_name */
+       u_int   snp_proto;                      /* nh_proto */
+       u_int   snp_qlimit;                     /* nh_qlimit */
+       u_int   snp_policy;                     /* nh_policy */
+       u_int   snp_flags;                      /* Various flags. */
+       u_int   _snp_ispare[7];
+};
+
+/*
+ * Flags for sysctl_netisr_proto.snp_flags.
+ */
+#define        NETISR_SNP_FLAGS_M2FLOW         0x00000001      /* nh_m2flow */
+#define        NETISR_SNP_FLAGS_M2CPUID        0x00000002      /* nh_m2cpuid */
+#define        NETISR_SNP_FLAGS_DRAINEDCPU     0x00000003      /* 
nh_drainedcpu */
+
+/*
+ * Next, a structure per-workstream, with per-protocol data, exported as
+ * net.isr.workstream.
+ */
+struct sysctl_netisr_workstream {
+       u_int   snws_version;                   /* Length of struct. */
+       u_int   snws_flags;                     /* Various flags. */
+       u_int   snws_wsid;                      /* Workstream ID. */
+       u_int   snws_cpu;                       /* nws_cpu */
+       u_int   _snws_ispare[12];
+};
+
+/*
+ * Flags for sysctl_netisr_workstream.snws_flags
+ */
+#define        NETISR_SNWS_FLAGS_INTR          0x00000001      /* 
nws_intr_event */
+
+/*
+ * Finally, a per-workstream-per-protocol structure, exported as
+ * net.isr.work.
+ */
+struct sysctl_netisr_work {
+       u_int   snw_version;                    /* Length of struct. */
+       u_int   snw_wsid;                       /* Workstream ID. */
+       u_int   snw_proto;                      /* Protocol number. */
+       u_int   snw_len;                        /* nw_len */
+       u_int   snw_watermark;                  /* nw_watermark */
+       u_int   _snw_ispare[3];
+
+       uint64_t        snw_dispatched;         /* nw_dispatched */
+       uint64_t        snw_hybrid_dispatched;  /* nw_hybrid_dispatched */
+       uint64_t        snw_qdrops;             /* nw_qdrops */
+       uint64_t        snw_queued;             /* nw_queued */
+       uint64_t        snw_handled;            /* nw_handled */
+
+       uint64_t        _snw_llspare[7];
+};
+
+#ifdef _KERNEL
+
 /*-
  * Protocols express ordering constraints and affinity preferences by
  * implementing one or neither of nh_m2flow and nh_m2cpuid, which are used by
@@ -91,10 +173,6 @@ typedef struct mbuf *netisr_m2cpuid_t(st
 typedef        struct mbuf     *netisr_m2flow_t(struct mbuf *m, uintptr_t 
source);
 typedef void            netisr_drainedcpu_t(u_int cpuid);
 
-#define        NETISR_POLICY_SOURCE    1       /* Maintain source ordering. */
-#define        NETISR_POLICY_FLOW      2       /* Maintain flow ordering. */
-#define        NETISR_POLICY_CPU       3       /* Protocol determines CPU 
placement. */
-
 /*
  * Data structure describing a protocol handler.
  */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to