Make ARP stats per-cpu.

This commit is contained in:
thorpej 2008-04-15 15:17:54 +00:00
parent b849cd90e5
commit 881a947288
4 changed files with 172 additions and 94 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_arp.h,v 1.28 2008/02/20 17:05:52 matt Exp $ */ /* $NetBSD: if_arp.h,v 1.29 2008/04/15 15:17:54 thorpej Exp $ */
/* /*
* Copyright (c) 1986, 1993 * Copyright (c) 1986, 1993
@ -101,33 +101,30 @@ struct arpreq {
/* /*
* Kernel statistics about arp * Kernel statistics about arp
*/ */
struct arpstat { #define ARP_STAT_SNDTOTAL 0 /* total packets sent */
u_quad_t as_sndtotal; /* total packets sent */ #define ARP_STAT_SNDREPLY 1 /* replies sent */
u_quad_t as_sndreply; /* replies sent */ #define ARP_STAT_SENDREQUEST 2 /* requests sent */
u_quad_t as_sndrequest; /* requests sent */ #define ARP_STAT_RCVTOTAL 3 /* total packets received */
#define ARP_STAT_RCVREQUEST 4 /* valid requests received */
#define ARP_STAT_RCVREPLY 5 /* replies received */
#define ARP_STAT_RCVMCAST 6 /* multicast/broadcast received */
#define ARP_STAT_RCVBADPROTO 7 /* unknown protocol type received */
#define ARP_STAT_RCVBADLEN 8 /* bad (short) length received */
#define ARP_STAT_RCVZEROTPA 9 /* received w/ null target ip */
#define ARP_STAT_RCVZEROSPA 10 /* received w/ null source ip */
#define ARP_STAT_RCVNOINT 11 /* couldn't map to interface */
#define ARP_STAT_RCVLOCALSHA 12 /* received from local hw address */
#define ARP_STAT_RCVBCASTSHA 13 /* received w/ broadcast src */
#define ARP_STAT_RCVLOCALSPA 14 /* received for a local ip [dup!] */
#define ARP_STAT_RCVOVERPERM 15 /* attempts to overwrite static info */
#define ARP_STAT_RCVOVERINT 16 /* attempts to overwrite wrong if */
#define ARP_STAT_RCVOVER 17 /* entries overwritten! */
#define ARP_STAT_RCVLENCHG 18 /* changes in hw address len */
#define ARP_STAT_DFRTOTAL 19 /* deferred pending ARP resolution */
#define ARP_STAT_DFRSENT 20 /* deferred, then sent */
#define ARP_STAT_DFRDROPPED 21 /* deferred, then dropped */
#define ARP_STAT_ALLOCFAIL 22 /* failures to allocate llinfo */
u_quad_t as_rcvtotal; /* total packets received */ #define ARP_NSTATS 23
u_quad_t as_rcvrequest; /* valid requests received */
u_quad_t as_rcvreply; /* replies received */
u_quad_t as_rcvmcast; /* multicast/broadcast received */
u_quad_t as_rcvbadproto; /* unknown protocol type received */
u_quad_t as_rcvbadlen; /* bad (short) length received */
u_quad_t as_rcvzerotpa; /* received w/ null target ip */
u_quad_t as_rcvzerospa; /* received w/ null src ip */
u_quad_t as_rcvnoint; /* couldn't map to interface */
u_quad_t as_rcvlocalsha; /* received from local hw address */
u_quad_t as_rcvbcastsha; /* received w/ broadcast src */
u_quad_t as_rcvlocalspa; /* received for a local ip [dup!] */
u_quad_t as_rcvoverperm; /* attempts to overwrite static info */
u_quad_t as_rcvoverint; /* attempts to overwrite wrong if */
u_quad_t as_rcvover; /* entries overwritten! */
u_quad_t as_rcvlenchg; /* changes in hw add len */
u_quad_t as_dfrtotal; /* deferred pending ARP resolution. */
u_quad_t as_dfrsent; /* deferred, then sent */
u_quad_t as_dfrdropped; /* deferred, then dropped */
u_quad_t as_allocfail; /* Failures to allocate llinfo */
};
#endif /* !_NET_IF_ARP_H_ */ #endif /* !_NET_IF_ARP_H_ */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_arp.c,v 1.131 2008/01/20 18:09:12 joerg Exp $ */ /* $NetBSD: if_arp.c,v 1.132 2008/04/15 15:17:54 thorpej Exp $ */
/*- /*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@ -75,7 +75,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.131 2008/01/20 18:09:12 joerg Exp $"); __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.132 2008/04/15 15:17:54 thorpej Exp $");
#include "opt_ddb.h" #include "opt_ddb.h"
#include "opt_inet.h" #include "opt_inet.h"
@ -100,6 +100,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.131 2008/01/20 18:09:12 joerg Exp $");
#include <sys/protosw.h> #include <sys/protosw.h>
#include <sys/domain.h> #include <sys/domain.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/percpu.h>
#include <net/ethertypes.h> #include <net/ethertypes.h>
#include <net/if.h> #include <net/if.h>
@ -169,7 +170,25 @@ int arp_maxtries = 5;
int useloopback = 1; /* use loopback interface for local traffic */ int useloopback = 1; /* use loopback interface for local traffic */
int arpinit_done = 0; int arpinit_done = 0;
struct arpstat arpstat; static percpu_t *arpstat_percpu;
#define ARP_STAT_GETREF() percpu_getref(arpstat_percpu)
#define ARP_STAT_PUTREF() percpu_putref(arpstat_percpu)
#define ARP_STATINC(x) \
do { \
uint64_t *_arps_ = ARP_STAT_GETREF(); \
_arps_[x]++; \
ARP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
#define ARP_STATADD(x, v) \
do { \
uint64_t *_arps_ = ARP_STAT_GETREF(); \
_arps_[x] += (v); \
ARP_STAT_PUTREF(); \
} while (/*CONSTCOND*/0)
struct callout arptimer_ch; struct callout arptimer_ch;
/* revarp state */ /* revarp state */
@ -231,7 +250,7 @@ const struct protosw arpsw[] = {
.pr_ctlinput = 0, .pr_ctlinput = 0,
.pr_ctloutput = 0, .pr_ctloutput = 0,
.pr_usrreq = 0, .pr_usrreq = 0,
.pr_init = 0, .pr_init = arp_init,
.pr_fasttimo = 0, .pr_fasttimo = 0,
.pr_slowtimo = 0, .pr_slowtimo = 0,
.pr_drain = arp_drain, .pr_drain = arp_drain,
@ -315,11 +334,17 @@ do { \
#define ARP_UNLOCK() arp_unlock() #define ARP_UNLOCK() arp_unlock()
void
arp_init(void)
{
arpstat_percpu = percpu_alloc(sizeof(uint64_t) * ARP_NSTATS);
}
/* /*
* ARP protocol drain routine. Called when memory is in short supply. * ARP protocol drain routine. Called when memory is in short supply.
* Called at splvm(); * Called at splvm();
*/ */
void void
arp_drain(void) arp_drain(void)
{ {
@ -344,7 +369,7 @@ arp_drain(void)
} }
} }
ARP_UNLOCK(); ARP_UNLOCK();
arpstat.as_dfrdropped += count; ARP_STATADD(ARP_STAT_DFRDROPPED, count);
} }
@ -658,6 +683,7 @@ arprequest(struct ifnet *ifp,
struct mbuf *m; struct mbuf *m;
struct arphdr *ah; struct arphdr *ah;
struct sockaddr sa; struct sockaddr sa;
uint64_t *arps;
if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
return; return;
@ -695,8 +721,10 @@ arprequest(struct ifnet *ifp,
sa.sa_family = AF_ARP; sa.sa_family = AF_ARP;
sa.sa_len = 2; sa.sa_len = 2;
m->m_flags |= M_BCAST; m->m_flags |= M_BCAST;
arpstat.as_sndtotal++; arps = ARP_STAT_GETREF();
arpstat.as_sndrequest++; arps[ARP_STAT_SNDTOTAL]++;
arps[ARP_STAT_SENDREQUEST]++;
ARP_STAT_PUTREF();
(*ifp->if_output)(ifp, m, &sa, NULL); (*ifp->if_output)(ifp, m, &sa, NULL);
} }
@ -723,7 +751,7 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
rt = la->la_rt; rt = la->la_rt;
if (la == 0 || rt == 0) { if (la == 0 || rt == 0) {
arpstat.as_allocfail++; ARP_STATINC(ARP_STAT_ALLOCFAIL);
log(LOG_DEBUG, log(LOG_DEBUG,
"arpresolve: can't allocate llinfo on %s for %s\n", "arpresolve: can't allocate llinfo on %s for %s\n",
ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr)); ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr));
@ -748,14 +776,14 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m,
* latest one. * latest one.
*/ */
arpstat.as_dfrtotal++; ARP_STATINC(ARP_STAT_DFRTOTAL);
s = splnet(); s = splnet();
mold = la->la_hold; mold = la->la_hold;
la->la_hold = m; la->la_hold = m;
splx(s); splx(s);
if (mold) { if (mold) {
arpstat.as_dfrdropped++; ARP_STATINC(ARP_STAT_DFRDROPPED);
m_freem(mold); m_freem(mold);
} }
@ -813,7 +841,7 @@ arpintr(void)
panic("arpintr"); panic("arpintr");
MCLAIM(m, &arpdomain.dom_mowner); MCLAIM(m, &arpdomain.dom_mowner);
arpstat.as_rcvtotal++; ARP_STATINC(ARP_STAT_RCVTOTAL);
/* /*
* First, make sure we have at least struct arphdr. * First, make sure we have at least struct arphdr.
@ -841,11 +869,11 @@ arpintr(void)
in_arpinput(m); in_arpinput(m);
continue; continue;
default: default:
arpstat.as_rcvbadproto++; ARP_STATINC(ARP_STAT_RCVBADPROTO);
} }
else { else {
badlen: badlen:
arpstat.as_rcvbadlen++; ARP_STATINC(ARP_STAT_RCVBADLEN);
} }
m_freem(m); m_freem(m);
} }
@ -886,6 +914,7 @@ in_arpinput(struct mbuf *m)
struct mbuf *mold; struct mbuf *mold;
void *tha; void *tha;
int s; int s;
uint64_t *arps;
if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT))) if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT)))
goto out; goto out;
@ -915,7 +944,7 @@ in_arpinput(struct mbuf *m)
memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr)); memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr));
if (m->m_flags & (M_BCAST|M_MCAST)) if (m->m_flags & (M_BCAST|M_MCAST))
arpstat.as_rcvmcast++; ARP_STATINC(ARP_STAT_RCVMCAST);
/* /*
* If the target IP address is zero, ignore the packet. * If the target IP address is zero, ignore the packet.
@ -923,7 +952,7 @@ in_arpinput(struct mbuf *m)
* when we are using IP address zero (booting). * when we are using IP address zero (booting).
*/ */
if (in_nullhost(itaddr)) { if (in_nullhost(itaddr)) {
arpstat.as_rcvzerotpa++; ARP_STATINC(ARP_STAT_RCVZEROTPA);
goto out; goto out;
} }
@ -933,7 +962,7 @@ in_arpinput(struct mbuf *m)
* XXX: Should we bother trying to reply to these? * XXX: Should we bother trying to reply to these?
*/ */
if (in_nullhost(isaddr)) { if (in_nullhost(isaddr)) {
arpstat.as_rcvzerospa++; ARP_STATINC(ARP_STAT_RCVZEROSPA);
goto out; goto out;
} }
@ -990,7 +1019,7 @@ in_arpinput(struct mbuf *m)
if (ia == NULL) { if (ia == NULL) {
IFP_TO_IA(ifp, ia); IFP_TO_IA(ifp, ia);
if (ia == NULL) { if (ia == NULL) {
arpstat.as_rcvnoint++; ARP_STATINC(ARP_STAT_RCVNOINT);
goto out; goto out;
} }
} }
@ -1000,13 +1029,13 @@ in_arpinput(struct mbuf *m)
/* XXX checks for bridge case? */ /* XXX checks for bridge case? */
if (!memcmp(ar_sha(ah), CLLADDR(ifp->if_sadl), ifp->if_addrlen)) { if (!memcmp(ar_sha(ah), CLLADDR(ifp->if_sadl), ifp->if_addrlen)) {
arpstat.as_rcvlocalsha++; ARP_STATINC(ARP_STAT_RCVLOCALSHA);
goto out; /* it's from me, ignore it. */ goto out; /* it's from me, ignore it. */
} }
/* XXX checks for bridge case? */ /* XXX checks for bridge case? */
if (!memcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { if (!memcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) {
arpstat.as_rcvbcastsha++; ARP_STATINC(ARP_STAT_RCVBCASTSHA);
log(LOG_ERR, log(LOG_ERR,
"%s: arp: link address is broadcast for IP address %s!\n", "%s: arp: link address is broadcast for IP address %s!\n",
ifp->if_xname, in_fmtaddr(isaddr)); ifp->if_xname, in_fmtaddr(isaddr));
@ -1014,7 +1043,7 @@ in_arpinput(struct mbuf *m)
} }
if (in_hosteq(isaddr, myaddr)) { if (in_hosteq(isaddr, myaddr)) {
arpstat.as_rcvlocalspa++; ARP_STATINC(ARP_STAT_RCVLOCALSPA);
log(LOG_ERR, log(LOG_ERR,
"duplicate IP address %s sent from link address %s\n", "duplicate IP address %s sent from link address %s\n",
in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln)); in_fmtaddr(isaddr), lla_snprintf(ar_sha(ah), ah->ar_hln));
@ -1026,7 +1055,7 @@ in_arpinput(struct mbuf *m)
if (sdl->sdl_alen && if (sdl->sdl_alen &&
memcmp(ar_sha(ah), CLLADDR(sdl), sdl->sdl_alen)) { memcmp(ar_sha(ah), CLLADDR(sdl), sdl->sdl_alen)) {
if (rt->rt_flags & RTF_STATIC) { if (rt->rt_flags & RTF_STATIC) {
arpstat.as_rcvoverperm++; ARP_STATINC(ARP_STAT_RCVOVERPERM);
log(LOG_INFO, log(LOG_INFO,
"%s tried to overwrite permanent arp info" "%s tried to overwrite permanent arp info"
" for %s\n", " for %s\n",
@ -1034,7 +1063,7 @@ in_arpinput(struct mbuf *m)
in_fmtaddr(isaddr)); in_fmtaddr(isaddr));
goto out; goto out;
} else if (rt->rt_ifp != ifp) { } else if (rt->rt_ifp != ifp) {
arpstat.as_rcvoverint++; ARP_STATINC(ARP_STAT_RCVOVERINT);
log(LOG_INFO, log(LOG_INFO,
"%s on %s tried to overwrite " "%s on %s tried to overwrite "
"arp info for %s on %s\n", "arp info for %s on %s\n",
@ -1043,7 +1072,7 @@ in_arpinput(struct mbuf *m)
rt->rt_ifp->if_xname); rt->rt_ifp->if_xname);
goto out; goto out;
} else { } else {
arpstat.as_rcvover++; ARP_STATINC(ARP_STAT_RCVOVER);
log(LOG_INFO, log(LOG_INFO,
"arp info overwritten for %s by %s\n", "arp info overwritten for %s by %s\n",
in_fmtaddr(isaddr), in_fmtaddr(isaddr),
@ -1057,13 +1086,13 @@ in_arpinput(struct mbuf *m)
*/ */
if (sdl->sdl_alen && if (sdl->sdl_alen &&
sdl->sdl_alen != ah->ar_hln) { sdl->sdl_alen != ah->ar_hln) {
arpstat.as_rcvlenchg++; ARP_STATINC(ARP_STAT_RCVLENCHG);
log(LOG_WARNING, log(LOG_WARNING,
"arp from %s: new addr len %d, was %d", "arp from %s: new addr len %d, was %d",
in_fmtaddr(isaddr), ah->ar_hln, sdl->sdl_alen); in_fmtaddr(isaddr), ah->ar_hln, sdl->sdl_alen);
} }
if (ifp->if_addrlen != ah->ar_hln) { if (ifp->if_addrlen != ah->ar_hln) {
arpstat.as_rcvbadlen++; ARP_STATINC(ARP_STAT_RCVBADLEN);
log(LOG_WARNING, log(LOG_WARNING,
"arp from %s: addr len: new %d, i/f %d (ignored)", "arp from %s: addr len: new %d, i/f %d (ignored)",
in_fmtaddr(isaddr), ah->ar_hln, in_fmtaddr(isaddr), ah->ar_hln,
@ -1110,19 +1139,19 @@ in_arpinput(struct mbuf *m)
splx(s); splx(s);
if (mold) { if (mold) {
arpstat.as_dfrsent++; ARP_STATINC(ARP_STAT_DFRSENT);
(*ifp->if_output)(ifp, mold, rt_getkey(rt), rt); (*ifp->if_output)(ifp, mold, rt_getkey(rt), rt);
} }
} }
reply: reply:
if (op != ARPOP_REQUEST) { if (op != ARPOP_REQUEST) {
if (op == ARPOP_REPLY) if (op == ARPOP_REPLY)
arpstat.as_rcvreply++; ARP_STATINC(ARP_STAT_RCVREPLY);
out: out:
m_freem(m); m_freem(m);
return; return;
} }
arpstat.as_rcvrequest++; ARP_STATINC(ARP_STAT_RCVREQUEST);
if (in_hosteq(itaddr, myaddr)) { if (in_hosteq(itaddr, myaddr)) {
/* I am the target */ /* I am the target */
tha = ar_tha(ah); tha = ar_tha(ah);
@ -1166,8 +1195,10 @@ reply:
m->m_pkthdr.len = m->m_len; m->m_pkthdr.len = m->m_len;
sa.sa_family = AF_ARP; sa.sa_family = AF_ARP;
sa.sa_len = 2; sa.sa_len = 2;
arpstat.as_sndtotal++; arps = ARP_STAT_GETREF();
arpstat.as_sndreply++; arps[ARP_STAT_SNDTOTAL]++;
arps[ARP_STAT_SNDREPLY]++;
ARP_STAT_PUTREF();
(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0); (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
return; return;
} }
@ -1238,7 +1269,7 @@ arplookup1(struct mbuf *m, const struct in_addr *addr, int create, int proxy,
if (rt->rt_flags & RTF_GATEWAY) if (rt->rt_flags & RTF_GATEWAY)
why = "host is not on local network"; why = "host is not on local network";
else if ((rt->rt_flags & RTF_LLINFO) == 0) { else if ((rt->rt_flags & RTF_LLINFO) == 0) {
arpstat.as_allocfail++; ARP_STATINC(ARP_STAT_ALLOCFAIL);
why = "could not allocate llinfo"; why = "could not allocate llinfo";
} else } else
why = "gateway route is not ours"; why = "gateway route is not ours";
@ -1546,6 +1577,38 @@ db_show_arptab(db_expr_t addr, bool have_addr,
} }
#endif #endif
static void
arpstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
{
uint64_t *arpsc = v1;
uint64_t *arps = v2;
u_int i;
for (i = 0; i < ARP_NSTATS; i++)
arps[i] += arpsc[i];
}
static void
arpstat_convert_to_user(uint64_t *arps)
{
memset(arps, 0, sizeof(uint64_t) * ARP_NSTATS);
percpu_foreach(arpstat_percpu, arpstat_convert_to_user_cb, arps);
}
static int
sysctl_net_inet_arp_stats(SYSCTLFN_ARGS)
{
struct sysctlnode node;
uint64_t arps[ARP_NSTATS];
arpstat_convert_to_user(arps);
node = *rnode;
node.sysctl_data = arps;
node.sysctl_size = sizeof(arps);
return (sysctl_lookup(SYSCTLFN_CALL(&node)));
}
SYSCTL_SETUP(sysctl_net_inet_arp_setup, "sysctl net.inet.arp subtree setup") SYSCTL_SETUP(sysctl_net_inet_arp_setup, "sysctl net.inet.arp subtree setup")
{ {
const struct sysctlnode *node; const struct sysctlnode *node;
@ -1594,6 +1657,13 @@ SYSCTL_SETUP(sysctl_net_inet_arp_setup, "sysctl net.inet.arp subtree setup")
SYSCTL_DESCR("ARP entry refresh interval"), SYSCTL_DESCR("ARP entry refresh interval"),
NULL, 0, &arpt_refresh, 0, NULL, 0, &arpt_refresh, 0,
CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL); CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
sysctl_createv(clog, 0, NULL, NULL,
CTLFLAG_PERMANENT,
CTLTYPE_STRUCT, "stats",
SYSCTL_DESCR("ARP statistics"),
sysctl_net_inet_arp_stats, 0, NULL, 0,
CTL_NET,PF_INET, node->sysctl_num, CTL_CREATE, CTL_EOL);
} }
#endif /* INET */ #endif /* INET */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_inarp.h,v 1.39 2007/03/04 06:03:20 christos Exp $ */ /* $NetBSD: if_inarp.h,v 1.40 2008/04/15 15:17:54 thorpej Exp $ */
/* /*
* Copyright (c) 1982, 1986, 1993 * Copyright (c) 1982, 1986, 1993
@ -68,6 +68,7 @@ int arpresolve(struct ifnet *, struct rtentry *, struct mbuf *,
void arpintr(void); void arpintr(void);
void arprequest(struct ifnet *, const struct in_addr *, const struct in_addr *, void arprequest(struct ifnet *, const struct in_addr *, const struct in_addr *,
const u_int8_t *); const u_int8_t *);
void arp_init(void);
void arp_drain(void); void arp_drain(void);
int arpioctl(u_long, void *); int arpioctl(u_long, void *);
void arpwhohas(struct ifnet *, struct in_addr *); void arpwhohas(struct ifnet *, struct in_addr *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: inet.c,v 1.85 2008/04/15 06:03:28 thorpej Exp $ */ /* $NetBSD: inet.c,v 1.86 2008/04/15 15:17:54 thorpej Exp $ */
/* /*
* Copyright (c) 1983, 1988, 1993 * Copyright (c) 1983, 1988, 1993
@ -34,7 +34,7 @@
#if 0 #if 0
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
#else #else
__RCSID("$NetBSD: inet.c,v 1.85 2008/04/15 06:03:28 thorpej Exp $"); __RCSID("$NetBSD: inet.c,v 1.86 2008/04/15 15:17:54 thorpej Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -720,46 +720,56 @@ pim_stats(u_long off, char *name)
void void
arp_stats(u_long off, char *name) arp_stats(u_long off, char *name)
{ {
struct arpstat arpstat; uint64_t arpstat[ARP_NSTATS];
if (use_sysctl) {
size_t size = sizeof(arpstat);
if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
NULL, 0) == -1) {
return;
}
} else {
if (off == 0)
return;
kread(off, (char *)arpstat, sizeof(arpstat));
}
if (off == 0)
return;
kread(off, (char *)&arpstat, sizeof (arpstat));
printf("%s:\n", name); printf("%s:\n", name);
#define ps(f, m) if (arpstat.f || sflag <= 1) \ #define ps(f, m) if (arpstat[f] || sflag <= 1) \
printf(m, (unsigned long long)arpstat.f) printf(m, (unsigned long long)arpstat[f])
#define p(f, m) if (arpstat.f || sflag <= 1) \ #define p(f, m) if (arpstat[f] || sflag <= 1) \
printf(m, (unsigned long long)arpstat.f, plural(arpstat.f)) printf(m, (unsigned long long)arpstat[f], plural(arpstat[f]))
p(as_sndtotal, "\t%llu packet%s sent\n"); p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
p(as_sndreply, "\t\t%llu reply packet%s\n"); p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n");
p(as_sndrequest, "\t\t%llu request packet%s\n"); p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n");
p(as_rcvtotal, "\t%llu packet%s received\n"); p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
p(as_rcvreply, "\t\t%llu reply packet%s\n"); p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n");
p(as_rcvrequest, "\t\t%llu valid request packet%s\n"); p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n");
p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n"); p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n");
p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n"); p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n");
p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n"); p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n");
p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n"); p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n");
p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n"); p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n");
ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n"); ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n");
p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware " p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware "
"address\n"); "address\n");
p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast " p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast "
"source hardware address\n"); "source hardware address\n");
p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n"); p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n");
p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n"); p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n");
p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n"); p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n");
p(as_rcvover, "\t\t%llu entry%s overwritten\n"); p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n");
p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n"); p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n");
p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n"); p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n");
ps(as_dfrsent, "\t\t%llu sent\n"); ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n");
ps(as_dfrdropped, "\t\t%llu dropped\n"); ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n");
p(as_allocfail, "\t%llu failure%s to allocate llinfo\n"); p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n");
#undef ps #undef ps
#undef p #undef p