Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Apr 2013 15:22:34 +0400
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        current@FreeBSD.org
Subject:   counter(9) for lagg(4)
Message-ID:  <20130412112234.GQ76816@glebius.int.ru>

next in thread | raw e-mail | index | archive | help

--5EqXjnbnoPR4rQBx
Content-Type: text/plain; charset=koi8-r
Content-Disposition: inline

  Hello,

  the patch removes memory contention and data loss on packets/bytes
statistics in lagg(4) driver, utilizing counter(9).

  Any benchmarking reports with trunk built upon 10Gbit interfaces
would be much appreciated.

  Sorry, but patch isn't tested except compiling. I don't have a
lab to build a LACP trunk.

-- 
Totus tuus, Glebius.

--5EqXjnbnoPR4rQBx
Content-Type: text/x-diff; charset=koi8-r
Content-Disposition: attachment; filename="lagg.counters.diff"

Index: if_lagg.c
===================================================================
--- if_lagg.c	(revision 249398)
+++ if_lagg.c	(working copy)
@@ -153,6 +153,8 @@ static struct mbuf *lagg_lacp_input(struct lagg_so
 		    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, int unit,
 		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, int unit,
 	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, int unit,
 	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 mbuf *m)
 	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 mbuf *m)
 	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, struct lagg
 	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);
+}
Index: if_lagg.h
===================================================================
--- if_lagg.h	(revision 249398)
+++ if_lagg.h	(working copy)
@@ -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 */
 };

--5EqXjnbnoPR4rQBx--



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