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:
parent
7daad711df
commit
5da0521fce
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user