Author: gnn
Date: Thu Jan 28 16:48:44 2010
New Revision: 203120
URL: http://svn.freebsd.org/changeset/base/203120

Log:
  MFC r196797:
  
  Add ARP statistics to the kernel and netstat.

Modified:
  stable/8/sys/net/if_arp.h
  stable/8/sys/netinet/if_ether.c
  stable/8/usr.bin/netstat/inet.c
  stable/8/usr.bin/netstat/main.c
  stable/8/usr.bin/netstat/netstat.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/usr.bin/netstat/   (props changed)

Modified: stable/8/sys/net/if_arp.h
==============================================================================
--- stable/8/sys/net/if_arp.h   Thu Jan 28 16:17:24 2010        (r203119)
+++ stable/8/sys/net/if_arp.h   Thu Jan 28 16:48:44 2010        (r203120)
@@ -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_ */

Modified: stable/8/sys/netinet/if_ether.c
==============================================================================
--- stable/8/sys/netinet/if_ether.c     Thu Jan 28 16:17:24 2010        
(r203119)
+++ stable/8/sys/netinet/if_ether.c     Thu Jan 28 16:48:44 2010        
(r203120)
@@ -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;
                                               * 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, OI
 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_
        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:

Modified: stable/8/usr.bin/netstat/inet.c
==============================================================================
--- stable/8/usr.bin/netstat/inet.c     Thu Jan 28 16:17:24 2010        
(r203119)
+++ stable/8/usr.bin/netstat/inet.c     Thu Jan 28 16:48:44 2010        
(r203120)
@@ -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, i
 #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",

Modified: stable/8/usr.bin/netstat/main.c
==============================================================================
--- stable/8/usr.bin/netstat/main.c     Thu Jan 28 16:17:24 2010        
(r203119)
+++ stable/8/usr.bin/netstat/main.c     Thu Jan 28 16:48:44 2010        
(r203120)
@@ -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 }
 };

Modified: stable/8/usr.bin/netstat/netstat.h
==============================================================================
--- stable/8/usr.bin/netstat/netstat.h  Thu Jan 28 16:17:24 2010        
(r203119)
+++ stable/8/usr.bin/netstat/netstat.h  Thu Jan 28 16:48:44 2010        
(r203120)
@@ -75,6 +75,7 @@ void  udp_stats(u_long, const char *, 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);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to