mirror of
https://github.com/opnsense/src.git
synced 2026-03-24 19:53:08 -04:00
MFC r196797:
Add ARP statistics to the kernel and netstat.
This commit is contained in:
parent
ef096f9d2a
commit
fbbbfe0ba5
5 changed files with 93 additions and 2 deletions
|
|
@ -108,6 +108,31 @@ struct arpcom {
|
|||
#define IFP2AC(ifp) ((struct arpcom *)(ifp->if_l2com))
|
||||
#define AC2IFP(ac) ((ac)->ac_ifp)
|
||||
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
|
||||
struct arpstat {
|
||||
/* Normal things that happen: */
|
||||
u_long txrequests; /* # of ARP requests sent by this host. */
|
||||
u_long txreplies; /* # of ARP replies sent by this host. */
|
||||
u_long rxrequests; /* # of ARP requests received by this host. */
|
||||
u_long rxreplies; /* # of ARP replies received by this host. */
|
||||
u_long received; /* # of ARP packets received by this host. */
|
||||
|
||||
u_long arp_spares[4]; /* For either the upper or lower half. */
|
||||
/* Abnormal event and error counting: */
|
||||
u_long dropped; /* # of packets dropped waiting for a reply. */
|
||||
u_long timeouts; /* # of times with entries removed */
|
||||
/* due to timeout. */
|
||||
u_long dupips; /* # of duplicate IPs detected. */
|
||||
};
|
||||
|
||||
/*
|
||||
* In-kernel consumers can use these accessor macros directly to update
|
||||
* stats.
|
||||
*/
|
||||
#define ARPSTAT_ADD(name, val) V_arpstat.name += (val)
|
||||
#define ARPSTAT_SUB(name, val) V_arpstat.name -= (val)
|
||||
#define ARPSTAT_INC(name) ARPSTAT_ADD(name, 1)
|
||||
#define ARPSTAT_DEC(name) ARPSTAT_SUB(name, 1)
|
||||
|
||||
#endif /* !_NET_IF_ARP_H_ */
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ __FBSDID("$FreeBSD$");
|
|||
|
||||
SYSCTL_DECL(_net_link_ether);
|
||||
SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
|
||||
SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, "");
|
||||
|
||||
VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for
|
||||
* local traffic */
|
||||
|
|
@ -91,11 +92,13 @@ static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for
|
|||
* 20 seconds */
|
||||
static VNET_DEFINE(int, arp_maxtries) = 5;
|
||||
static VNET_DEFINE(int, arp_proxyall);
|
||||
static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */
|
||||
|
||||
#define V_arpt_keep VNET(arpt_keep)
|
||||
#define V_arpt_down VNET(arpt_down)
|
||||
#define V_arp_maxtries VNET(arp_maxtries)
|
||||
#define V_arp_proxyall VNET(arp_proxyall)
|
||||
#define V_arpstat VNET(arpstat)
|
||||
|
||||
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
|
||||
&VNET_NAME(arpt_keep), 0,
|
||||
|
|
@ -110,6 +113,9 @@ SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
|
|||
SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
|
||||
&VNET_NAME(arp_proxyall), 0,
|
||||
"Enable proxy ARP for all suitable requests");
|
||||
SYSCTL_VNET_STRUCT(_net_link_ether_arp, OID_AUTO, stats, CTLFLAG_RW,
|
||||
&VNET_NAME(arpstat), arpstat,
|
||||
"ARP statistics (struct arpstat, net/if_arp.h)");
|
||||
|
||||
static void arp_init(void);
|
||||
void arprequest(struct ifnet *,
|
||||
|
|
@ -166,6 +172,7 @@ arptimer(void *arg)
|
|||
return;
|
||||
}
|
||||
ifp = lle->lle_tbl->llt_ifp;
|
||||
CURVNET_SET(ifp->if_vnet);
|
||||
IF_AFDATA_LOCK(ifp);
|
||||
LLE_WLOCK(lle);
|
||||
if (lle->la_flags & LLE_STATIC)
|
||||
|
|
@ -174,6 +181,7 @@ arptimer(void *arg)
|
|||
if (!callout_pending(&lle->la_timer) &&
|
||||
callout_active(&lle->la_timer)) {
|
||||
(void) llentry_free(lle);
|
||||
ARPSTAT_INC(timeouts);
|
||||
}
|
||||
#ifdef DIAGNOSTIC
|
||||
else {
|
||||
|
|
@ -186,6 +194,7 @@ arptimer(void *arg)
|
|||
#endif
|
||||
}
|
||||
IF_AFDATA_UNLOCK(ifp);
|
||||
CURVNET_RESTORE();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -247,6 +256,7 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
|
|||
sa.sa_len = 2;
|
||||
m->m_flags |= M_BCAST;
|
||||
(*ifp->if_output)(ifp, m, &sa, NULL);
|
||||
ARPSTAT_INC(txrequests);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -348,8 +358,10 @@ retry:
|
|||
* latest one.
|
||||
*/
|
||||
if (m != NULL) {
|
||||
if (la->la_hold != NULL)
|
||||
if (la->la_hold != NULL) {
|
||||
m_freem(la->la_hold);
|
||||
ARPSTAT_INC(dropped);
|
||||
}
|
||||
la->la_hold = m;
|
||||
if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
|
||||
flags &= ~LLE_EXCLUSIVE;
|
||||
|
|
@ -422,6 +434,7 @@ arpintr(struct mbuf *m)
|
|||
ar = mtod(m, struct arphdr *);
|
||||
}
|
||||
|
||||
ARPSTAT_INC(received);
|
||||
switch (ntohs(ar->ar_pro)) {
|
||||
#ifdef INET
|
||||
case ETHERTYPE_IP:
|
||||
|
|
@ -502,6 +515,9 @@ in_arpinput(struct mbuf *m)
|
|||
(void)memcpy(&isaddr, ar_spa(ah), sizeof (isaddr));
|
||||
(void)memcpy(&itaddr, ar_tpa(ah), sizeof (itaddr));
|
||||
|
||||
if (op == ARPOP_REPLY)
|
||||
ARPSTAT_INC(rxreplies);
|
||||
|
||||
/*
|
||||
* For a bridge, we want to check the address irrespective
|
||||
* of the receive interface. (This will change slightly
|
||||
|
|
@ -612,6 +628,7 @@ match:
|
|||
ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
|
||||
inet_ntoa(isaddr), ifp->if_xname);
|
||||
itaddr = myaddr;
|
||||
ARPSTAT_INC(dupips);
|
||||
goto reply;
|
||||
}
|
||||
if (ifp->if_flags & IFF_STATICARP)
|
||||
|
|
@ -695,6 +712,7 @@ match:
|
|||
reply:
|
||||
if (op != ARPOP_REQUEST)
|
||||
goto drop;
|
||||
ARPSTAT_INC(rxrequests);
|
||||
|
||||
if (itaddr.s_addr == myaddr.s_addr) {
|
||||
/* Shortcut.. the receiving interface is the target. */
|
||||
|
|
@ -791,6 +809,7 @@ reply:
|
|||
sa.sa_family = AF_ARP;
|
||||
sa.sa_len = 2;
|
||||
(*ifp->if_output)(ifp, m, &sa, NULL);
|
||||
ARPSTAT_INC(txreplies);
|
||||
return;
|
||||
|
||||
drop:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
|
|||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/route.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
|
|
@ -871,6 +872,47 @@ ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
|
|||
#undef p1a
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump ARP statistics structure.
|
||||
*/
|
||||
void
|
||||
arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
|
||||
{
|
||||
struct arpstat arpstat, zerostat;
|
||||
size_t len = sizeof(arpstat);
|
||||
|
||||
if (live) {
|
||||
if (zflag)
|
||||
memset(&zerostat, 0, len);
|
||||
if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
|
||||
zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
|
||||
warn("sysctl: net.link.ether.arp.stats");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
kread(off, &arpstat, len);
|
||||
|
||||
printf("%s:\n", name);
|
||||
|
||||
#define p(f, m) if (arpstat.f || sflag <= 1) \
|
||||
printf(m, arpstat.f, plural(arpstat.f))
|
||||
#define p2(f, m) if (arpstat.f || sflag <= 1) \
|
||||
printf(m, arpstat.f, pluralies(arpstat.f))
|
||||
|
||||
p(txrequests, "\t%lu ARP request%s sent\n");
|
||||
p2(txreplies, "\t%lu ARP repl%s sent\n");
|
||||
p(rxrequests, "\t%lu ARP request%s received\n");
|
||||
p2(rxreplies, "\t%lu ARP repl%s received\n");
|
||||
p(received, "\t%lu ARP packet%s received\n");
|
||||
p(dropped, "\t%lu total packet%s dropped due to no ARP entry\n");
|
||||
p(timeouts, "\t%lu ARP entry%s timed out\n");
|
||||
p(dupips, "\t%lu Duplicate IP%s seen\n");
|
||||
#undef p
|
||||
#undef p2
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const char *icmpnames[ICMP_MAXTYPE + 1] = {
|
||||
"echo reply", /* RFC 792 */
|
||||
"#1",
|
||||
|
|
|
|||
|
|
@ -184,6 +184,8 @@ static struct nlist nl[] = {
|
|||
{ .n_name = "_sctpstat" },
|
||||
#define N_MFCTABLESIZE 54
|
||||
{ .n_name = "_mfctablesize" },
|
||||
#define N_ARPSTAT 55
|
||||
{ .n_name = "_arpstat" },
|
||||
{ .n_name = NULL },
|
||||
};
|
||||
|
||||
|
|
@ -232,6 +234,8 @@ struct protox {
|
|||
carp_stats, NULL, "carp", 1, 0 },
|
||||
{ -1, N_PFSYNCSTAT, 1, NULL,
|
||||
pfsync_stats, NULL, "pfsync", 1, 0 },
|
||||
{ -1, N_ARPSTAT, 1, NULL,
|
||||
arp_stats, NULL, "arp", 1, 0 },
|
||||
{ -1, -1, 0, NULL,
|
||||
NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ void udp_stats(u_long, const char *, int, int);
|
|||
void sctp_protopr(u_long, const char *, int, int);
|
||||
void sctp_stats(u_long, const char *, int, int);
|
||||
#endif
|
||||
void arp_stats(u_long, const char *, int, int);
|
||||
void ip_stats(u_long, const char *, int, int);
|
||||
void icmp_stats(u_long, const char *, int, int);
|
||||
void igmp_stats(u_long, const char *, int, int);
|
||||
|
|
|
|||
Loading…
Reference in a new issue