svn commit: r249506 - head/sys/net

Alexander V. Chernikov melifaro at FreeBSD.org
Mon Apr 15 16:11:37 UTC 2013


On 15.04.2013 17:00, Gleb Smirnoff wrote:
> 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.
Lagg is probably the only interface where we really do not need to
account (most) per-packet traffic. It is probably better to import
statistics from underlying interfaces with callout.

Additionally, this approach allows us not to use lagg RX path at all
skipping lock (reference patch to ixgbe in the -net@ follows).

>   
>   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 */
>  };
> 


-- 
WBR, Alexander
-------------- next part --------------
Index: sys/net/if_lagg.c
===================================================================
--- sys/net/if_lagg.c	(revision 248704)
+++ sys/net/if_lagg.c	(working copy)
@@ -261,6 +261,41 @@ lagg_unregister_vlan(void *arg, struct ifnet *ifp,
         LAGG_RUNLOCK(sc);
 }
 
+#define	LAGG_UPDATE_COUNTER(_name)	do {		\
+	if (p_ifp->if_data._name >= lp->_name) {	\
+		i = p_ifp->if_data._name - lp->_name;	\
+		lagg_ifp->if_data._name += i;		\
+		lp->_name += i;				\
+	} else 						\
+		lp->_name = p_ifp->if_data._name;	\
+} while (0)
+
+static void
+lagg_update_counters(void *arg)
+{
+	struct lagg_softc	*sc = arg;
+        struct lagg_port        *lp;
+	struct ifnet		*lagg_ifp, *p_ifp;
+	u_long i;
+
+	lagg_ifp = sc->sc_ifp;
+
+	LAGG_RLOCK(sc);
+
+	SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
+		p_ifp = lp->lp_ifp;
+
+		LAGG_UPDATE_COUNTER(ifi_ipackets);
+		LAGG_UPDATE_COUNTER(ifi_opackets);
+		LAGG_UPDATE_COUNTER(ifi_ibytes);
+		LAGG_UPDATE_COUNTER(ifi_obytes);
+	}
+
+	LAGG_RUNLOCK(sc);
+
+	callout_reset(&sc->counters_sync, hz, lagg_update_counters, sc);
+}
+
 static int
 lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
 {
@@ -307,6 +342,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(&sc->counters_sync, 0);
 
 	/* Initialise pseudo media types */
 	ifmedia_init(&sc->sc_media, 0, lagg_media_change,
@@ -338,6 +374,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->counters_sync, hz / 10, lagg_update_counters, sc);
+
 	return (0);
 }
 
@@ -347,6 +385,9 @@ lagg_clone_destroy(struct ifnet *ifp)
 	struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc;
 	struct lagg_port *lp;
 
+	/* Stop collecting counters */
+	callout_drain(&sc->counters_sync);
+
 	LAGG_WLOCK(sc);
 
 	lagg_stop(sc);
@@ -571,6 +612,12 @@ lagg_port_create(struct lagg_softc *sc, struct ifn
 	lp->lp_ifp = ifp;
 	lp->lp_softc = sc;
 
+	/* Set counters */
+	lp->ifi_ibytes = ifp->if_ibytes;
+	lp->ifi_obytes = ifp->if_obytes;
+	lp->ifi_ipackets = ifp->if_ipackets;
+	lp->ifi_opackets = ifp->if_opackets;
+
 	/* Save port link layer address */
 	bcopy(IF_LLADDR(ifp), lp->lp_lladdr, ETHER_ADDR_LEN);
 
@@ -1243,9 +1290,7 @@ lagg_transmit(struct ifnet *ifp, struct mbuf *m)
 	LAGG_RUNLOCK(sc);
 
 	if (error == 0) {
-		ifp->if_opackets++;
 		ifp->if_omcasts += mcast;
-		ifp->if_obytes += len;
 	} else
 		ifp->if_oerrors++;
 
@@ -1281,9 +1326,6 @@ 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;
-
 		if (scifp->if_flags & IFF_MONITOR) {
 			m_freem(m);
 			m = NULL;
Index: sys/net/if_lagg.h
===================================================================
--- sys/net/if_lagg.h	(revision 248704)
+++ sys/net/if_lagg.h	(working copy)
@@ -219,6 +219,7 @@ struct lagg_softc {
 	eventhandler_tag vlan_detach;
 	struct sysctl_ctx_list		ctx;		/* sysctl variables */
 	int				use_flowid;	/* use M_FLOWID */
+	struct callout			counters_sync;	/* counters periodic */
 };
 
 struct lagg_port {
@@ -241,6 +242,11 @@ struct lagg_port {
 	int	(*lp_output)(struct ifnet *, struct mbuf *, struct sockaddr *,
 		     struct route *);
 
+	u_long				ifi_ipackets;	/* packets received on interface */
+	u_long				ifi_opackets;	/* packets sent on interface */
+	u_long				ifi_ibytes;	/* total number of octets received */
+	u_long				ifi_obytes;	/* total number of octets sent */
+
 	SLIST_ENTRY(lagg_port)		lp_entries;
 };
 
Index: sys/net/if_vlan.c
===================================================================
--- sys/net/if_vlan.c	(revision 248704)
+++ sys/net/if_vlan.c	(working copy)
@@ -138,6 +138,12 @@ static int soft_pad = 0;
 SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW, &soft_pad, 0,
 	   "pad short frames before tagging");
 
+static int sysctl_priority_val(SYSCTL_HANDLER_ARGS);
+static int priority = htons(1 << 13);
+SYSCTL_VNET_PROC(_net_link_vlan, OID_AUTO, dot1p_priority,
+    CTLTYPE_UINT|CTLFLAG_RW, 0, 0, sysctl_priority_val, "IU",
+	   "set dot1p priority");
+
 static const char vlanname[] = "vlan";
 static MALLOC_DEFINE(M_VLAN, vlanname, "802.1Q Virtual LAN Interface");
 
@@ -217,6 +223,27 @@ static VNET_DEFINE(struct if_clone *, vlan_cloner)
 #ifndef VLAN_ARRAY
 #define HASH(n, m)	((((n) >> 8) ^ ((n) >> 4) ^ (n)) & (m))
 
+/*
+ * Set maximum number of tables that can be used in given VNET ipfw instance.
+ */
+static int
+sysctl_priority_val(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	unsigned int nprio;
+
+	nprio = ntohs(priority) >> 13;
+
+	error = sysctl_handle_int(oidp, &nprio, 0, req);
+	/* Read operation or some error */
+	if ((error != 0) || (req->newptr == NULL))
+		return (error);
+	
+	priority = htons((nprio & 0x7) << 13);
+
+	return (0);
+}
+
 static void
 vlan_inithash(struct ifvlantrunk *trunk)
 {
@@ -1076,7 +1103,7 @@ vlan_transmit(struct ifnet *ifp, struct mbuf *m)
 	 * packet tag that holds it.
 	 */
 	if (p->if_capenable & IFCAP_VLAN_HWTAGGING) {
-		m->m_pkthdr.ether_vtag = ifv->ifv_vid;
+		m->m_pkthdr.ether_vtag = ifv->ifv_vid | priority;
 		m->m_flags |= M_VLANTAG;
 	} else {
 		m = ether_vlanencap(m, ifv->ifv_vid);


More information about the svn-src-all mailing list