Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 Apr 2013 13:00:42 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r249506 - head/sys/net
Message-ID:  <201304151300.r3FD0gDV021140@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Mon Apr 15 13:00:42 2013
New Revision: 249506
URL: http://svnweb.freebsd.org/changeset/base/249506

Log:
  Switch lagg(4) statistics to counter(9).
  
  The lagg(4) is often used to bond high speed links, so basic per-packet +=
  on statistics cause cache misses and statistics loss.
  
  Perfect solution would be to convert ifnet(9) to counters(9), but this
  requires much more work, and unfortunately ABI change, so temporarily
  patch lagg(4) manually.
  
  We store counters in the softc, and once per second push their values
  to legacy ifnet counters.
  
  Sponsored by:	Nginx, Inc.

Modified:
  head/sys/net/if_lagg.c
  head/sys/net/if_lagg.h

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c	Mon Apr 15 12:16:24 2013	(r249505)
+++ head/sys/net/if_lagg.c	Mon Apr 15 13:00:42 2013	(r249506)
@@ -153,6 +153,8 @@ static struct mbuf *lagg_lacp_input(stru
 		    struct mbuf *);
 static void	lagg_lacp_lladdr(struct lagg_softc *);
 
+static void	lagg_callout(void *);
+
 /* lagg protocol table */
 static const struct {
 	int			ti_proto;
@@ -278,6 +280,11 @@ lagg_clone_create(struct if_clone *ifc, 
 		return (ENOSPC);
 	}
 
+	sc->sc_ipackets = counter_u64_alloc(M_WAITOK);
+	sc->sc_opackets = counter_u64_alloc(M_WAITOK);
+	sc->sc_ibytes = counter_u64_alloc(M_WAITOK);
+	sc->sc_obytes = counter_u64_alloc(M_WAITOK);
+
 	sysctl_ctx_init(&sc->ctx);
 	snprintf(num, sizeof(num), "%u", unit);
 	sc->use_flowid = def_use_flowid;
@@ -307,6 +314,7 @@ lagg_clone_create(struct if_clone *ifc, 
 	LAGG_LOCK_INIT(sc);
 	SLIST_INIT(&sc->sc_ports);
 	TASK_INIT(&sc->sc_lladdr_task, 0, lagg_port_setlladdr, sc);
+	callout_init_rw(&sc->sc_callout, &sc->sc_mtx, CALLOUT_SHAREDLOCK);
 
 	/* Initialise pseudo media types */
 	ifmedia_init(&sc->sc_media, 0, lagg_media_change,
@@ -338,6 +346,8 @@ lagg_clone_create(struct if_clone *ifc, 
 	SLIST_INSERT_HEAD(&lagg_list, sc, sc_entries);
 	mtx_unlock(&lagg_list_mtx);
 
+	callout_reset(&sc->sc_callout, hz, lagg_callout, sc);
+
 	return (0);
 }
 
@@ -369,6 +379,12 @@ lagg_clone_destroy(struct ifnet *ifp)
 	ether_ifdetach(ifp);
 	if_free(ifp);
 
+	callout_drain(&sc->sc_callout);
+	counter_u64_free(sc->sc_ipackets);
+	counter_u64_free(sc->sc_opackets);
+	counter_u64_free(sc->sc_ibytes);
+	counter_u64_free(sc->sc_obytes);
+
 	mtx_lock(&lagg_list_mtx);
 	SLIST_REMOVE(&lagg_list, sc, lagg_softc, sc_entries);
 	mtx_unlock(&lagg_list_mtx);
@@ -1243,9 +1259,9 @@ lagg_transmit(struct ifnet *ifp, struct 
 	LAGG_RUNLOCK(sc);
 
 	if (error == 0) {
-		ifp->if_opackets++;
+		counter_u64_add(sc->sc_opackets, 1);
+		counter_u64_add(sc->sc_obytes, len);
 		ifp->if_omcasts += mcast;
-		ifp->if_obytes += len;
 	} else
 		ifp->if_oerrors++;
 
@@ -1281,8 +1297,8 @@ lagg_input(struct ifnet *ifp, struct mbu
 	m = (*sc->sc_input)(sc, lp, m);
 
 	if (m != NULL) {
-		scifp->if_ipackets++;
-		scifp->if_ibytes += m->m_pkthdr.len;
+		counter_u64_add(sc->sc_ipackets, 1);
+		counter_u64_add(sc->sc_ibytes, m->m_pkthdr.len);
 
 		if (scifp->if_flags & IFF_MONITOR) {
 			m_freem(m);
@@ -1892,3 +1908,17 @@ lagg_lacp_input(struct lagg_softc *sc, s
 	m->m_pkthdr.rcvif = ifp;
 	return (m);
 }
+
+static void
+lagg_callout(void *arg)
+{
+	struct lagg_softc *sc = (struct lagg_softc *)arg;
+	struct ifnet *ifp = sc->sc_ifp;
+
+	ifp->if_ipackets = counter_u64_fetch(sc->sc_ipackets);
+	ifp->if_opackets = counter_u64_fetch(sc->sc_opackets);
+	ifp->if_ibytes = counter_u64_fetch(sc->sc_ibytes);
+	ifp->if_obytes = counter_u64_fetch(sc->sc_obytes);
+
+	callout_reset(&sc->sc_callout, hz, lagg_callout, sc);
+}

Modified: head/sys/net/if_lagg.h
==============================================================================
--- head/sys/net/if_lagg.h	Mon Apr 15 12:16:24 2013	(r249505)
+++ head/sys/net/if_lagg.h	Mon Apr 15 13:00:42 2013	(r249506)
@@ -21,8 +21,6 @@
 #ifndef _NET_LAGG_H
 #define _NET_LAGG_H
 
-#include <sys/sysctl.h>
-
 /*
  * Global definitions
  */
@@ -137,6 +135,9 @@ struct lagg_reqflags {
 #define	SIOCSLAGGHASH		 _IOW('i', 146, struct lagg_reqflags)
 
 #ifdef _KERNEL
+
+#include <sys/counter.h>
+
 /*
  * Internal kernel part
  */
@@ -195,6 +196,11 @@ struct lagg_softc {
 	uint32_t			sc_seq;		/* sequence counter */
 	uint32_t			sc_flags;
 
+	counter_u64_t			sc_ipackets;
+	counter_u64_t			sc_opackets;
+	counter_u64_t			sc_ibytes;
+	counter_u64_t			sc_obytes;
+
 	SLIST_HEAD(__tplhd, lagg_port)	sc_ports;	/* list of interfaces */
 	SLIST_ENTRY(lagg_softc)	sc_entries;
 
@@ -217,6 +223,7 @@ struct lagg_softc {
 	void	(*sc_portreq)(struct lagg_port *, caddr_t);
 	eventhandler_tag vlan_attach;
 	eventhandler_tag vlan_detach;
+	struct callout			sc_callout;
 	struct sysctl_ctx_list		ctx;		/* sysctl variables */
 	int				use_flowid;	/* use M_FLOWID */
 };



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201304151300.r3FD0gDV021140>