Export netisr configuration and statistics to userspace via sysctl(9).
MFC after: 1 week Sponsored by: Juniper Networks
This commit is contained in:
parent
4cd0801096
commit
2d22f334ea
168
sys/net/netisr.c
168
sys/net/netisr.c
@ -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)
|
||||
{
|
||||
|
@ -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(struct mbuf *m, uintptr_t source,
|
||||
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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user