Use kvm_counter_u64_fetch() to fix obtaining ipstat and tcpstat from
kernel core files. Sponsored by: Nginx, Inc.
This commit is contained in:
parent
2a2134043c
commit
29dde48df4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249345
@ -603,8 +603,13 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
|
||||
warn("sysctl: net.inet.tcp.stats");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
kread(off, &tcpstat, len);
|
||||
} 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));
|
||||
}
|
||||
|
||||
printf ("%s:\n", name);
|
||||
|
||||
@ -858,8 +863,13 @@ ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
|
||||
warn("sysctl: net.inet.ip.stats");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
kread(off, &ipstat, len);
|
||||
} 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));
|
||||
}
|
||||
|
||||
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 = "_tcpstat" },
|
||||
{ .n_name = "_tcpstatp" },
|
||||
#define N_UDPSTAT 39
|
||||
{ .n_name = "_udpstat" },
|
||||
#define N_IPSTAT 40
|
||||
{ .n_name = "_ipstat" },
|
||||
{ .n_name = "_ipstatp" },
|
||||
#define N_ICMPSTAT 41
|
||||
{ .n_name = "_icmpstat" },
|
||||
#define N_IGMPSTAT 42
|
||||
@ -696,37 +696,50 @@ printproto(struct protox *tp, const char *name)
|
||||
(*pr)(off, name, af, tp->pr_protocol);
|
||||
}
|
||||
|
||||
static int
|
||||
kvmd_init(void)
|
||||
{
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
if (kvmd != NULL)
|
||||
return (0);
|
||||
|
||||
kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
|
||||
setgid(getgid());
|
||||
|
||||
if (kvmd == NULL) {
|
||||
warnx("kvm not available: %s", errbuf);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (kvm_nlist(kvmd, nl) < 0) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: kvm_nlist: %s", nlistf,
|
||||
kvm_geterr(kvmd));
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read kernel memory, return 0 on success.
|
||||
*/
|
||||
int
|
||||
kread(u_long addr, void *buf, size_t size)
|
||||
{
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
if (kvmd == NULL) {
|
||||
kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
|
||||
setgid(getgid());
|
||||
if (kvmd != NULL) {
|
||||
if (kvm_nlist(kvmd, nl) < 0) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: kvm_nlist: %s", nlistf,
|
||||
kvm_geterr(kvmd));
|
||||
else
|
||||
errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
|
||||
}
|
||||
if (kvmd_init() < 0)
|
||||
return (-1);
|
||||
|
||||
if (nl[0].n_type == 0) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: no namelist", nlistf);
|
||||
else
|
||||
errx(1, "no namelist");
|
||||
}
|
||||
} else {
|
||||
warnx("kvm not available: %s", errbuf);
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
if (!buf)
|
||||
return (0);
|
||||
if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
|
||||
@ -736,6 +749,22 @@ kread(u_long addr, void *buf, size_t size)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
if (kvmd_init() < 0)
|
||||
return (-1);
|
||||
|
||||
for (u_int i = 0; i < count; i++, addr++, rval++)
|
||||
*rval = kvm_counter_u64_fetch(kvmd, *addr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
const char *
|
||||
plural(uintmax_t n)
|
||||
{
|
||||
|
@ -60,6 +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);
|
||||
const char *plural(uintmax_t);
|
||||
const char *plurales(uintmax_t);
|
||||
const char *pluralies(uintmax_t);
|
||||
|
Loading…
Reference in New Issue
Block a user