aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorGeorge V. Neville-Neil <gnn@FreeBSD.org>2009-09-03 21:10:57 +0000
committerGeorge V. Neville-Neil <gnn@FreeBSD.org>2009-09-03 21:10:57 +0000
commit54fc657d59324e260dd5cde0d6e7f60d43a41c60 (patch)
treeadac442cdf92025f0d2ded02f1a96f79bc1b1cfc /sys
parentce531e6b836398fff1633185f8413543b693a673 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_arp.h27
-rw-r--r--sys/netinet/if_ether.c31
2 files changed, 51 insertions, 7 deletions
diff --git a/sys/net/if_arp.h b/sys/net/if_arp.h
index 1e18804ffde33..2bb63582800a2 100644
--- a/sys/net/if_arp.h
+++ b/sys/net/if_arp.h
@@ -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_ */
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index e118cec0fa3e4..c170c7ab711d1 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -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 */
@@ -89,10 +90,12 @@ static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20
* minutes */
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_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,
@@ -107,6 +110,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 *,
@@ -163,20 +169,23 @@ 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_DELETED)
- || (time_second >= lle->la_expire))
- && (!callout_pending(&lle->la_timer) &&
- callout_active(&lle->la_timer)))
+ if (((lle->la_flags & LLE_DELETED) ||
+ (time_second >= lle->la_expire)) &&
+ (!callout_pending(&lle->la_timer) &&
+ callout_active(&lle->la_timer))) {
(void) llentry_free(lle);
- else {
+ ARPSTAT_INC(timeouts);
+ } else {
/*
* Still valid, just drop our reference
*/
LLE_FREE_LOCKED(lle);
}
IF_AFDATA_UNLOCK(ifp);
+ CURVNET_RESTORE();
}
/*
@@ -238,6 +247,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);
}
/*
@@ -339,8 +349,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;
@@ -413,6 +425,7 @@ arpintr(struct mbuf *m)
ar = mtod(m, struct arphdr *);
}
+ ARPSTAT_INC(received);
switch (ntohs(ar->ar_pro)) {
#ifdef INET
case ETHERTYPE_IP:
@@ -493,6 +506,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
@@ -603,6 +619,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)
@@ -686,6 +703,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. */
@@ -774,6 +792,7 @@ reply:
sa.sa_family = AF_ARP;
sa.sa_len = 2;
(*ifp->if_output)(ifp, m, &sa, NULL);
+ ARPSTAT_INC(txreplies);
return;
drop: