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"