Use new macros to implement ipstat and tcpstat using PCPU counters.

Change interface of kread_counters() similar ot kread() in the netstat(1).
This commit is contained in:
Andrey V. Elsukov 2013-07-09 09:43:03 +00:00
parent 7daad711df
commit 5da0521fce
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=253083
7 changed files with 42 additions and 291 deletions

View File

@ -208,73 +208,17 @@ SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, output_flowtable_size, CTLFLAG_RDTUN,
static void ip_freef(struct ipqhead *, struct ipq *);
/*
* IP statistics are stored in struct ipstat_p, which is
* an "array" of counter(9)s. Although it isn't a real
* array, we treat it as array to reduce code bloat.
* IP statistics are stored in the "array" of counter(9)s.
*/
VNET_DEFINE(struct ipstat_p, ipstatp);
static void
vnet_ipstatp_init(const void *unused)
{
counter_u64_t *c;
int i;
for (i = 0, c = (counter_u64_t *)&V_ipstatp;
i < sizeof(V_ipstatp) / sizeof(counter_u64_t);
i++, c++) {
*c = counter_u64_alloc(M_WAITOK);
counter_u64_zero(*c);
}
}
VNET_SYSINIT(vnet_ipstatp_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_ipstatp_init, NULL);
VNET_PCPUSTAT_DEFINE(struct ipstat, ipstat);
VNET_PCPUSTAT_SYSINIT(ipstat);
SYSCTL_VNET_PCPUSTAT(_net_inet_ip, IPCTL_STATS, stats, struct ipstat, ipstat,
"IP statistics (struct ipstat, netinet/ip_var.h)");
#ifdef VIMAGE
static void
vnet_ipstatp_uninit(const void *unused)
{
counter_u64_t *c;
int i;
for (i = 0, c = (counter_u64_t *)&V_ipstatp;
i < sizeof(V_ipstatp) / sizeof(counter_u64_t);
i++, c++)
counter_u64_free(*c);
}
VNET_SYSUNINIT(vnet_ipstatp_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_ipstatp_uninit, NULL);
VNET_PCPUSTAT_SYSUNINIT(ipstat);
#endif /* VIMAGE */
static int
ipstat_sysctl(SYSCTL_HANDLER_ARGS)
{
struct ipstat ipstat;
counter_u64_t *c;
uint64_t *v;
int i;
for (i = 0, c = (counter_u64_t *)&V_ipstatp, v = (uint64_t *)&ipstat;
i < sizeof(V_ipstatp) / sizeof(counter_u64_t);
i++, c++, v++) {
*v = counter_u64_fetch(*c);
/*
* Old interface allowed to rewrite 'struct ipstat', and
* netstat(1) used it to zero the structure. To keep
* compatibility with old netstat(1) we will zero out
* statistics on every write attempt, however we no longer
* support writing arbitrary fake values to the statistics.
*/
if (req->newptr)
counter_u64_zero(*c);
}
return (SYSCTL_OUT(req, &ipstat, sizeof(ipstat)));
}
SYSCTL_VNET_PROC(_net_inet_ip, IPCTL_STATS, stats, CTLTYPE_OPAQUE | CTLFLAG_RW,
NULL, 0, ipstat_sysctl, "I",
"IP statistics (struct ipstat, netinet/ip_var.h)");
/*
* Kernel module interface for updating ipstat. The argument is an index
* into ipstat treated as an array.
@ -283,14 +227,14 @@ void
kmod_ipstat_inc(int statnum)
{
counter_u64_add(*((counter_u64_t *)&V_ipstatp + statnum), 1);
counter_u64_add(VNET(ipstat)[statnum], 1);
}
void
kmod_ipstat_dec(int statnum)
{
counter_u64_add(*((counter_u64_t *)&V_ipstatp + statnum), -1);
counter_u64_add(VNET(ipstat)[statnum], -1);
}
static int

View File

@ -133,46 +133,13 @@ struct ipstat {
#include <sys/counter.h>
#include <net/vnet.h>
/* Should match 'struct ipstat' above. */
struct ipstat_p {
counter_u64_t ips_total;
counter_u64_t ips_badsum;
counter_u64_t ips_tooshort;
counter_u64_t ips_toosmall;
counter_u64_t ips_badhlen;
counter_u64_t ips_badlen;
counter_u64_t ips_fragments;
counter_u64_t ips_fragdropped;
counter_u64_t ips_fragtimeout;
counter_u64_t ips_forward;
counter_u64_t ips_fastforward;
counter_u64_t ips_cantforward;
counter_u64_t ips_redirectsent;
counter_u64_t ips_noproto;
counter_u64_t ips_delivered;
counter_u64_t ips_localout;
counter_u64_t ips_odropped;
counter_u64_t ips_reassembled;
counter_u64_t ips_fragmented;
counter_u64_t ips_ofragments;
counter_u64_t ips_cantfrag;
counter_u64_t ips_badoptions;
counter_u64_t ips_noroute;
counter_u64_t ips_badvers;
counter_u64_t ips_rawout;
counter_u64_t ips_toolong;
counter_u64_t ips_notmember;
counter_u64_t ips_nogif;
counter_u64_t ips_badaddr;
};
VNET_DECLARE(struct ipstat_p, ipstatp);
#define V_ipstatp VNET(ipstatp)
VNET_PCPUSTAT_DECLARE(struct ipstat, ipstat);
/*
* In-kernel consumers can use these accessor macros directly to update
* stats.
*/
#define IPSTAT_ADD(name, val) counter_u64_add(V_ipstatp.name, (val))
#define IPSTAT_ADD(name, val) \
VNET_PCPUSTAT_ADD(struct ipstat, ipstat, name, (val))
#define IPSTAT_SUB(name, val) IPSTAT_ADD(name, -(val))
#define IPSTAT_INC(name) IPSTAT_ADD(name, 1)
#define IPSTAT_DEC(name) IPSTAT_SUB(name, 1)
@ -181,11 +148,11 @@ VNET_DECLARE(struct ipstat_p, ipstatp);
* Kernel module consumers must use this accessor macro.
*/
void kmod_ipstat_inc(int statnum);
#define KMOD_IPSTAT_INC(name) \
kmod_ipstat_inc(offsetof(struct ipstat_p, name) / sizeof(counter_u64_t))
#define KMOD_IPSTAT_INC(name) \
kmod_ipstat_inc(offsetof(struct ipstat, name) / sizeof(uint64_t))
void kmod_ipstat_dec(int statnum);
#define KMOD_IPSTAT_DEC(name) \
kmod_ipstat_dec(offsetof(struct ipstat_p, name) / sizeof(counter_u64_t))
#define KMOD_IPSTAT_DEC(name) \
kmod_ipstat_dec(offsetof(struct ipstat, name) / sizeof(uint64_t))
/* flags passed to ip_output as last parameter */
#define IP_FORWARDING 0x1 /* most of ip header exists */

View File

@ -240,67 +240,16 @@ static void inline hhook_run_tcp_est_in(struct tcpcb *tp,
struct tcphdr *th, struct tcpopt *to);
/*
* TCP statistics are stored in struct tcpstat_p, which is
* an "array" of counter(9)s. Although it isn't a real
* array, we treat it as array to reduce code bloat.
* TCP statistics are stored in an "array" of counter(9)s.
*/
VNET_DEFINE(struct tcpstat_p, tcpstatp);
static void
vnet_tcpstatp_init(const void *unused)
{
counter_u64_t *c;
int i;
for (i = 0, c = (counter_u64_t *)&V_tcpstatp;
i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
i++, c++) {
*c = counter_u64_alloc(M_WAITOK);
counter_u64_zero(*c);
}
}
VNET_SYSINIT(vnet_tcpstatp_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_tcpstatp_init, NULL);
VNET_PCPUSTAT_DEFINE(struct tcpstat, tcpstat);
VNET_PCPUSTAT_SYSINIT(tcpstat);
SYSCTL_VNET_PCPUSTAT(_net_inet_tcp, TCPCTL_STATS, stats, struct tcpstat,
tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
#ifdef VIMAGE
static void
vnet_tcpstatp_uninit(const void *unused)
{
counter_u64_t *c;
int i;
for (i = 0, c = (counter_u64_t *)&V_tcpstatp;
i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
i++, c++)
counter_u64_free(*c);
}
VNET_SYSUNINIT(vnet_tcpstatp_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
vnet_tcpstatp_uninit, NULL);
VNET_PCPUSTAT_SYSUNINIT(tcpstat);
#endif /* VIMAGE */
static int
tcpstat_sysctl(SYSCTL_HANDLER_ARGS)
{
struct tcpstat tcpstat;
counter_u64_t *c;
uint64_t *v;
int i;
for (i = 0, c = (counter_u64_t *)&V_tcpstatp, v = (uint64_t *)&tcpstat;
i < sizeof(V_tcpstatp) / sizeof(counter_u64_t);
i++, c++, v++) {
*v = counter_u64_fetch(*c);
if (req->newptr)
counter_u64_zero(*c);
}
return (SYSCTL_OUT(req, &tcpstat, sizeof(tcpstat)));
}
SYSCTL_VNET_PROC(_net_inet_tcp, TCPCTL_STATS, stats, CTLTYPE_OPAQUE |
CTLFLAG_RW, NULL, 0, tcpstat_sysctl, "I",
"TCP statistics (struct tcpstat, netinet/tcp_var.h)");
/*
* Kernel module interface for updating tcpstat. The argument is an index
* into tcpstat treated as an array.
@ -309,7 +258,7 @@ void
kmod_tcpstat_inc(int statnum)
{
counter_u64_add(*((counter_u64_t *)&V_tcpstatp + statnum), 1);
counter_u64_add(VNET(tcpstat)[statnum], 1);
}
/*

View File

@ -514,119 +514,15 @@ struct tcpstat {
};
#ifdef _KERNEL
#include <sys/counter.h>
/* Should match 'struct tcpstat' above. */
struct tcpstat_p {
counter_u64_t tcps_connattempt;
counter_u64_t tcps_accepts;
counter_u64_t tcps_connects;
counter_u64_t tcps_drops;
counter_u64_t tcps_conndrops;
counter_u64_t tcps_minmssdrops;
counter_u64_t tcps_closed;
counter_u64_t tcps_segstimed;
counter_u64_t tcps_rttupdated;
counter_u64_t tcps_delack;
counter_u64_t tcps_timeoutdrop;
counter_u64_t tcps_rexmttimeo;
counter_u64_t tcps_persisttimeo;
counter_u64_t tcps_keeptimeo;
counter_u64_t tcps_keepprobe;
counter_u64_t tcps_keepdrops;
counter_u64_t tcps_sndtotal;
counter_u64_t tcps_sndpack;
counter_u64_t tcps_sndbyte;
counter_u64_t tcps_sndrexmitpack;
counter_u64_t tcps_sndrexmitbyte;
counter_u64_t tcps_sndrexmitbad;
counter_u64_t tcps_sndacks;
counter_u64_t tcps_sndprobe;
counter_u64_t tcps_sndurg;
counter_u64_t tcps_sndwinup;
counter_u64_t tcps_sndctrl;
counter_u64_t tcps_rcvtotal;
counter_u64_t tcps_rcvpack;
counter_u64_t tcps_rcvbyte;
counter_u64_t tcps_rcvbadsum;
counter_u64_t tcps_rcvbadoff;
counter_u64_t tcps_rcvmemdrop;
counter_u64_t tcps_rcvshort;
counter_u64_t tcps_rcvduppack;
counter_u64_t tcps_rcvdupbyte;
counter_u64_t tcps_rcvpartduppack;
counter_u64_t tcps_rcvpartdupbyte;
counter_u64_t tcps_rcvoopack;
counter_u64_t tcps_rcvoobyte;
counter_u64_t tcps_rcvpackafterwin;
counter_u64_t tcps_rcvbyteafterwin;
counter_u64_t tcps_rcvafterclose;
counter_u64_t tcps_rcvwinprobe;
counter_u64_t tcps_rcvdupack;
counter_u64_t tcps_rcvacktoomuch;
counter_u64_t tcps_rcvackpack;
counter_u64_t tcps_rcvackbyte;
counter_u64_t tcps_rcvwinupd;
counter_u64_t tcps_pawsdrop;
counter_u64_t tcps_predack;
counter_u64_t tcps_preddat;
counter_u64_t tcps_pcbcachemiss;
counter_u64_t tcps_cachedrtt;
counter_u64_t tcps_cachedrttvar;
counter_u64_t tcps_cachedssthresh;
counter_u64_t tcps_usedrtt;
counter_u64_t tcps_usedrttvar;
counter_u64_t tcps_usedssthresh;
counter_u64_t tcps_persistdrop;
counter_u64_t tcps_badsyn;
counter_u64_t tcps_mturesent;
counter_u64_t tcps_listendrop;
counter_u64_t tcps_badrst;
counter_u64_t tcps_sc_added;
counter_u64_t tcps_sc_retransmitted;
counter_u64_t tcps_sc_dupsyn;
counter_u64_t tcps_sc_dropped;
counter_u64_t tcps_sc_completed;
counter_u64_t tcps_sc_bucketoverflow;
counter_u64_t tcps_sc_cacheoverflow;
counter_u64_t tcps_sc_reset;
counter_u64_t tcps_sc_stale;
counter_u64_t tcps_sc_aborted;
counter_u64_t tcps_sc_badack;
counter_u64_t tcps_sc_unreach;
counter_u64_t tcps_sc_zonefail;
counter_u64_t tcps_sc_sendcookie;
counter_u64_t tcps_sc_recvcookie;
counter_u64_t tcps_hc_added;
counter_u64_t tcps_hc_bucketoverflow;
counter_u64_t tcps_finwait2_drops;
counter_u64_t tcps_sack_recovery_episode;
counter_u64_t tcps_sack_rexmits;
counter_u64_t tcps_sack_rexmit_bytes;
counter_u64_t tcps_sack_rcv_blocks;
counter_u64_t tcps_sack_send_blocks;
counter_u64_t tcps_sack_sboverflow;
counter_u64_t tcps_ecn_ce;
counter_u64_t tcps_ecn_ect0;
counter_u64_t tcps_ecn_ect1;
counter_u64_t tcps_ecn_shs;
counter_u64_t tcps_ecn_rcwnd;
counter_u64_t tcps_sig_rcvgoodsig;
counter_u64_t tcps_sig_rcvbadsig;
counter_u64_t tcps_sig_err_buildsig;
counter_u64_t tcps_sig_err_sigopt;
counter_u64_t tcps_sig_err_nosigopt;
};
VNET_DECLARE(struct tcpstat_p, tcpstatp); /* tcp statistics */
#define V_tcpstatp VNET(tcpstatp)
VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
/*
* In-kernel consumers can use these accessor macros directly to update
* stats.
*/
#define TCPSTAT_ADD(name, val) counter_u64_add(V_tcpstatp.name, (val))
#define TCPSTAT_ADD(name, val) \
VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val))
#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
/*
@ -634,8 +530,7 @@ VNET_DECLARE(struct tcpstat_p, tcpstatp); /* tcp statistics */
*/
void kmod_tcpstat_inc(int statnum);
#define KMOD_TCPSTAT_INC(name) \
kmod_tcpstat_inc(offsetof(struct tcpstat_p, name) / \
sizeof(counter_u64_t))
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(uint64_t))
/*
* TCP specific helper hook point identifiers.

View File

@ -603,13 +603,8 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
warn("sysctl: net.inet.tcp.stats");
return;
}
} else {
u_long tcpstat_p[sizeof(struct tcpstat)/sizeof(uint64_t)];
kread(off, &tcpstat_p, sizeof(tcpstat_p));
kread_counters(tcpstat_p, (uint64_t *)&tcpstat,
sizeof(struct tcpstat)/sizeof(uint64_t));
}
} else
kread_counters(off, &tcpstat, len);
printf ("%s:\n", name);
@ -863,13 +858,8 @@ ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
warn("sysctl: net.inet.ip.stats");
return;
}
} else {
u_long ipstat_p[sizeof(struct ipstat)/sizeof(uint64_t)];
kread(off, &ipstat_p, sizeof(ipstat_p));
kread_counters(ipstat_p, (uint64_t *)&ipstat,
sizeof(struct ipstat)/sizeof(uint64_t));
}
} else
kread_counters(off, &ipstat, len);
printf("%s:\n", name);

View File

@ -147,11 +147,11 @@ static struct nlist nl[] = {
#define N_IPCOMPSTAT 37
{ .n_name = "_ipcompstat" },
#define N_TCPSTAT 38
{ .n_name = "_tcpstatp" },
{ .n_name = "_tcpstat" },
#define N_UDPSTAT 39
{ .n_name = "_udpstat" },
#define N_IPSTAT 40
{ .n_name = "_ipstatp" },
{ .n_name = "_ipstat" },
#define N_ICMPSTAT 41
{ .n_name = "_icmpstat" },
#define N_IGMPSTAT 42
@ -753,15 +753,21 @@ kread(u_long addr, void *buf, size_t size)
* Read an array of N counters in kernel memory into array of N uint64_t's.
*/
int
kread_counters(u_long *addr, uint64_t *rval, size_t count)
kread_counters(u_long addr, void *buf, size_t size)
{
uint64_t *c = buf;
if (kvmd_init() < 0)
return (-1);
for (u_int i = 0; i < count; i++, addr++, rval++)
*rval = kvm_counter_u64_fetch(kvmd, *addr);
if (kread(addr, buf, size) < 0)
return (-1);
while (size != 0) {
*c = kvm_counter_u64_fetch(kvmd, *c);
size -= sizeof(*c);
c++;
}
return (0);
}

View File

@ -60,7 +60,7 @@ extern int af; /* address family */
extern int live; /* true if we are examining a live system */
int kread(u_long addr, void *buf, size_t size);
int kread_counters(u_long *addr, uint64_t *rval, size_t count);
int kread_counters(u_long addr, void *buf, size_t size);
const char *plural(uintmax_t);
const char *plurales(uintmax_t);
const char *pluralies(uintmax_t);