From owner-svn-src-all@FreeBSD.ORG Tue Oct 15 11:37:59 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id C3B32968; Tue, 15 Oct 2013 11:37:59 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id A165827A3; Tue, 15 Oct 2013 11:37:59 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9FBbxtk053343; Tue, 15 Oct 2013 11:37:59 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9FBbw5E053329; Tue, 15 Oct 2013 11:37:58 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201310151137.r9FBbw5E053329@svn.freebsd.org> From: Gleb Smirnoff Date: Tue, 15 Oct 2013 11:37:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r256525 - in head/sys: net netinet netinet6 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Oct 2013 11:37:59 -0000 Author: glebius Date: Tue Oct 15 11:37:57 2013 New Revision: 256525 URL: http://svnweb.freebsd.org/changeset/base/256525 Log: - Utilize counter(9) to accumulate statistics on interface addresses. Add four counters to struct ifaddr. This kills '+=' on a variables shared between processors for every packet. - Nuke struct if_data from struct ifaddr. - In ip_input() do not put a reference on ifaddr, instead update statistics right now in place and do IN_IFADDR_RUNLOCK(). These removes atomic(9) for every packet. [1] - To properly support NET_RT_IFLISTL sysctl used by getifaddrs(3), in rtsock.c fill if_data fields using counter_u64_fetch(). - Accidentially fix bug in COMPAT_32 version of NET_RT_IFLISTL, which took if_data not from the ifaddr, but from ifaddr's ifnet. [2] Submitted by: melifaro [1], pluknet[2] Sponsored by: Netflix Sponsored by: Nginx, Inc. Modified: head/sys/net/if.c head/sys/net/if_var.h head/sys/net/rtsock.c head/sys/netinet/ip_input.c head/sys/netinet/ip_output.c head/sys/netinet6/ip6_input.c head/sys/netinet6/ip6_output.c Modified: head/sys/net/if.c ============================================================================== --- head/sys/net/if.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/net/if.c Tue Oct 15 11:37:57 2013 (r256525) @@ -1428,10 +1428,28 @@ ifa_alloc(size_t size, int flags) if (ifa == NULL) return (NULL); + if ((ifa->ifa_opackets = counter_u64_alloc(flags)) == NULL) + goto fail; + if ((ifa->ifa_ipackets = counter_u64_alloc(flags)) == NULL) + goto fail; + if ((ifa->ifa_obytes = counter_u64_alloc(flags)) == NULL) + goto fail; + if ((ifa->ifa_ibytes = counter_u64_alloc(flags)) == NULL) + goto fail; + refcount_init(&ifa->ifa_refcnt, 1); - ifa->if_data.ifi_datalen = sizeof(ifa->if_data); return (ifa); + +fail: + /* free(NULL) is okay */ + counter_u64_free(ifa->ifa_opackets); + counter_u64_free(ifa->ifa_ipackets); + counter_u64_free(ifa->ifa_obytes); + counter_u64_free(ifa->ifa_ibytes); + free(ifa, M_IFADDR); + + return (NULL); } void @@ -1446,6 +1464,10 @@ ifa_free(struct ifaddr *ifa) { if (refcount_release(&ifa->ifa_refcnt)) { + counter_u64_free(ifa->ifa_opackets); + counter_u64_free(ifa->ifa_ipackets); + counter_u64_free(ifa->ifa_obytes); + counter_u64_free(ifa->ifa_ibytes); free(ifa, M_IFADDR); } } Modified: head/sys/net/if_var.h ============================================================================== --- head/sys/net/if_var.h Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/net/if_var.h Tue Oct 15 11:37:57 2013 (r256525) @@ -83,6 +83,7 @@ struct vnet; #include #include #endif /* _KERNEL */ +#include #include /* XXX */ #include /* XXX */ #include /* XXX */ @@ -794,7 +795,6 @@ struct ifaddr { struct sockaddr *ifa_dstaddr; /* other end of p-to-p link */ #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ struct sockaddr *ifa_netmask; /* used to determine subnet */ - struct if_data if_data; /* not all members are meaningful */ struct ifnet *ifa_ifp; /* back-pointer to interface */ struct carp_softc *ifa_carp; /* pointer to CARP data */ TAILQ_ENTRY(ifaddr) ifa_link; /* queue macro glue */ @@ -805,6 +805,11 @@ struct ifaddr { int ifa_metric; /* cost of going out this interface */ int (*ifa_claim_addr) /* check if an addr goes to this if */ (struct ifaddr *, struct sockaddr *); + + counter_u64_t ifa_ipackets; + counter_u64_t ifa_opackets; + counter_u64_t ifa_ibytes; + counter_u64_t ifa_obytes; }; #endif Modified: head/sys/net/rtsock.c ============================================================================== --- head/sys/net/rtsock.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/net/rtsock.c Tue Oct 15 11:37:57 2013 (r256525) @@ -1751,7 +1751,17 @@ sysctl_iflist_ifaml(struct ifaddr *ifa, offsetof(struct ifa_msghdrl32, ifam_data); ifam32->ifam_metric = ifa->ifa_metric; - copy_ifdata32(&ifa->ifa_ifp->if_data, &ifam32->ifam_data); + bzero(&ifam32->ifam_data, sizeof(ifam32->ifam_data)); + ifam32->ifam_data.ifi_datalen = sizeof(struct if_data32); + ifam32->ifam_data.ifi_ipackets = + counter_u64_fetch(ifa->ifa_ipackets); + ifam32->ifam_data.ifi_opackets = + counter_u64_fetch(ifa->ifa_opackets); + ifam32->ifam_data.ifi_ibytes = + counter_u64_fetch(ifa->ifa_ibytes); + ifam32->ifam_data.ifi_obytes = + counter_u64_fetch(ifa->ifa_obytes); + /* Fixup if_data carp(4) vhid. */ if (carp_get_vhid_p != NULL) ifam32->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa); @@ -1769,7 +1779,13 @@ sysctl_iflist_ifaml(struct ifaddr *ifa, ifam->ifam_data_off = offsetof(struct ifa_msghdrl, ifam_data); ifam->ifam_metric = ifa->ifa_metric; - ifam->ifam_data = ifa->if_data; + bzero(&ifam->ifam_data, sizeof(ifam->ifam_data)); + ifam->ifam_data.ifi_datalen = sizeof(struct if_data); + ifam->ifam_data.ifi_ipackets = counter_u64_fetch(ifa->ifa_ipackets); + ifam->ifam_data.ifi_opackets = counter_u64_fetch(ifa->ifa_opackets); + ifam->ifam_data.ifi_ibytes = counter_u64_fetch(ifa->ifa_ibytes); + ifam->ifam_data.ifi_obytes = counter_u64_fetch(ifa->ifa_obytes); + /* Fixup if_data carp(4) vhid. */ if (carp_get_vhid_p != NULL) ifam->ifam_data.ifi_vhid = (*carp_get_vhid_p)(ifa); Modified: head/sys/netinet/ip_input.c ============================================================================== --- head/sys/netinet/ip_input.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/netinet/ip_input.c Tue Oct 15 11:37:57 2013 (r256525) @@ -603,7 +603,9 @@ passin: */ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr && (!checkif || ia->ia_ifp == ifp)) { - ifa_ref(&ia->ia_ifa); + counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); + counter_u64_add(ia->ia_ifa.ifa_ibytes, + m->m_pkthdr.len); /* IN_IFADDR_RUNLOCK(); */ goto ours; } @@ -626,13 +628,17 @@ passin: ia = ifatoia(ifa); if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) { - ifa_ref(ifa); + counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); + counter_u64_add(ia->ia_ifa.ifa_ibytes, + m->m_pkthdr.len); IF_ADDR_RUNLOCK(ifp); goto ours; } #ifdef BOOTP_COMPAT if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) { - ifa_ref(ifa); + counter_u64_add(ia->ia_ifa.ifa_ipackets, 1); + counter_u64_add(ia->ia_ifa.ifa_ibytes, + m->m_pkthdr.len); IF_ADDR_RUNLOCK(ifp); goto ours; } @@ -717,20 +723,10 @@ ours: * IPSTEALTH: Process non-routing options only * if the packet is destined for us. */ - if (V_ipstealth && hlen > sizeof (struct ip) && ip_dooptions(m, 1)) { - if (ia != NULL) - ifa_free(&ia->ia_ifa); + if (V_ipstealth && hlen > sizeof (struct ip) && ip_dooptions(m, 1)) return; - } #endif /* IPSTEALTH */ - /* Count the packet in the ip address stats */ - if (ia != NULL) { - ia->ia_ifa.if_ipackets++; - ia->ia_ifa.if_ibytes += m->m_pkthdr.len; - ifa_free(&ia->ia_ifa); - } - /* * Attempt reassembly; if it succeeds, proceed. * ip_reass() will return a different mbuf. Modified: head/sys/netinet/ip_output.c ============================================================================== --- head/sys/netinet/ip_output.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/netinet/ip_output.c Tue Oct 15 11:37:57 2013 (r256525) @@ -610,11 +610,12 @@ passout: */ if (!(flags & IP_FORWARDING) && ia) { if (m->m_pkthdr.csum_flags & CSUM_TSO) - ia->ia_ifa.if_opackets += - m->m_pkthdr.len / m->m_pkthdr.tso_segsz; + counter_u64_add(ia->ia_ifa.ifa_opackets, + m->m_pkthdr.len / m->m_pkthdr.tso_segsz); else - ia->ia_ifa.if_opackets++; - ia->ia_ifa.if_obytes += m->m_pkthdr.len; + counter_u64_add(ia->ia_ifa.ifa_opackets, 1); + + counter_u64_add(ia->ia_ifa.ifa_obytes, m->m_pkthdr.len); } #ifdef MBUF_STRESS_TEST if (mbuf_frag_size && m->m_pkthdr.len > mbuf_frag_size) @@ -651,8 +652,9 @@ passout: if (error == 0) { /* Record statistics for this interface address. */ if (ia != NULL) { - ia->ia_ifa.if_opackets++; - ia->ia_ifa.if_obytes += m->m_pkthdr.len; + counter_u64_add(ia->ia_ifa.ifa_opackets, 1); + counter_u64_add(ia->ia_ifa.ifa_obytes, + m->m_pkthdr.len); } /* * Reset layer specific mbuf flags Modified: head/sys/netinet6/ip6_input.c ============================================================================== --- head/sys/netinet6/ip6_input.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/netinet6/ip6_input.c Tue Oct 15 11:37:57 2013 (r256525) @@ -724,8 +724,9 @@ passin: ia6 = (struct in6_ifaddr *)ifa; if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { /* Count the packet in the ip address stats */ - ia6->ia_ifa.if_ipackets++; - ia6->ia_ifa.if_ibytes += m->m_pkthdr.len; + counter_u64_add(ia6->ia_ifa.ifa_ipackets, 1); + counter_u64_add(ia6->ia_ifa.ifa_ibytes, + m->m_pkthdr.len); /* * record address information into m_tag. @@ -840,8 +841,9 @@ passin: ours = 1; deliverifp = ia6->ia_ifp; /* correct? */ /* Count the packet in the ip address stats */ - ia6->ia_ifa.if_ipackets++; - ia6->ia_ifa.if_ibytes += m->m_pkthdr.len; + counter_u64_add(ia6->ia_ifa.ifa_ipackets, 1); + counter_u64_add(ia6->ia_ifa.ifa_ibytes, + m->m_pkthdr.len); if (free_ia6) ifa_free(&ia6->ia_ifa); goto hbhcheck; Modified: head/sys/netinet6/ip6_output.c ============================================================================== --- head/sys/netinet6/ip6_output.c Tue Oct 15 11:25:12 2013 (r256524) +++ head/sys/netinet6/ip6_output.c Tue Oct 15 11:37:57 2013 (r256525) @@ -1021,8 +1021,9 @@ passout: ia6 = in6_ifawithifp(ifp, &ip6->ip6_src); if (ia6) { /* Record statistics for this interface address. */ - ia6->ia_ifa.if_opackets++; - ia6->ia_ifa.if_obytes += m->m_pkthdr.len; + counter_u64_add(ia6->ia_ifa.ifa_opackets, 1); + counter_u64_add(ia6->ia_ifa.ifa_obytes, + m->m_pkthdr.len); ifa_free(&ia6->ia_ifa); } error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); @@ -1177,8 +1178,9 @@ sendorfree: if (error == 0) { /* Record statistics for this interface address. */ if (ia) { - ia->ia_ifa.if_opackets++; - ia->ia_ifa.if_obytes += m->m_pkthdr.len; + counter_u64_add(ia->ia_ifa.ifa_opackets, 1); + counter_u64_add(ia->ia_ifa.ifa_obytes, + m->m_pkthdr.len); } error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); } else