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
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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to