On 09/11/16(Wed) 14:55, David Gwynne wrote: > since counters are an array of uint64_t values, this uses an enum > to list the indexes into such an array. > > we still export an ipstat struct to userland (which you can see > with netstat -sp ip). the export cheats a bit because we know that > the struct is a collection of u_longs, so we just iterate over the > coutners and the struct as an array and assign values.
What about introducing a new type for counters instead of using M_PCB? This way we can easily track how much memory we use for per-CPU counters. > ok? ok mpi@ > > Index: net/if_bridge.c > =================================================================== > RCS file: /cvs/src/sys/net/if_bridge.c,v > retrieving revision 1.287 > diff -u -p -r1.287 if_bridge.c > --- net/if_bridge.c 3 Oct 2016 15:53:09 -0000 1.287 > +++ net/if_bridge.c 9 Nov 2016 04:45:23 -0000 > @@ -1603,25 +1603,25 @@ bridge_ip(struct bridge_softc *sc, int d > /* Copy minimal header, and drop invalids */ > if (m->m_len < sizeof(struct ip) && > (m = m_pullup(m, sizeof(struct ip))) == NULL) { > - ipstat.ips_toosmall++; > + ipstat_inc(ips_toosmall); > return (NULL); > } > ip = mtod(m, struct ip *); > > if (ip->ip_v != IPVERSION) { > - ipstat.ips_badvers++; > + ipstat_inc(ips_badvers); > goto dropit; > } > > hlen = ip->ip_hl << 2; /* get whole header length */ > if (hlen < sizeof(struct ip)) { > - ipstat.ips_badhlen++; > + ipstat_inc(ips_badhlen); > goto dropit; > } > > if (hlen > m->m_len) { > if ((m = m_pullup(m, hlen)) == NULL) { > - ipstat.ips_badhlen++; > + ipstat_inc(ips_badhlen); > return (NULL); > } > ip = mtod(m, struct ip *); > @@ -1629,13 +1629,13 @@ bridge_ip(struct bridge_softc *sc, int d > > if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) { > if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) { > - ipstat.ips_badsum++; > + ipstat_inc(ips_badsum); > goto dropit; > } > > - ipstat.ips_inswcsum++; > + ipstat_inc(ips_inswcsum); > if (in_cksum(m, hlen) != 0) { > - ipstat.ips_badsum++; > + ipstat_inc(ips_badsum); > goto dropit; > } > } > @@ -1678,7 +1678,7 @@ bridge_ip(struct bridge_softc *sc, int d > if (0 && (ifp->if_capabilities & IFCAP_CSUM_IPv4)) > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > else { > - ipstat.ips_outswcsum++; > + ipstat_inc(ips_outswcsum); > ip->ip_sum = in_cksum(m, hlen); > } > > @@ -1848,7 +1848,7 @@ bridge_fragment(struct bridge_softc *sc, > } > > if (error == 0) > - ipstat.ips_fragmented++; > + ipstat_inc(ips_fragmented); > > return; > dropit: > Index: net/if_etherip.c > =================================================================== > RCS file: /cvs/src/sys/net/if_etherip.c,v > retrieving revision 1.7 > diff -u -p -r1.7 if_etherip.c > --- net/if_etherip.c 13 Apr 2016 11:41:15 -0000 1.7 > +++ net/if_etherip.c 9 Nov 2016 04:45:23 -0000 > @@ -430,7 +430,7 @@ ip_etherip_input(struct mbuf *m, ...) > > if (ip->ip_p != IPPROTO_ETHERIP) { > m_freem(m); > - ipstat.ips_noproto++; > + ipstat_inc(ips_noproto); > return; > } > > Index: net/pf.c > =================================================================== > RCS file: /cvs/src/sys/net/pf.c,v > retrieving revision 1.996 > diff -u -p -r1.996 pf.c > --- net/pf.c 28 Oct 2016 07:54:19 -0000 1.996 > +++ net/pf.c 9 Nov 2016 04:45:23 -0000 > @@ -5825,7 +5825,7 @@ pf_route(struct mbuf **m, struct pf_pdes > if (!r->rt) { > rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); > if (rt == NULL) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > goto bad; > } > > @@ -5859,7 +5859,7 @@ pf_route(struct mbuf **m, struct pf_pdes > > rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); > if (rt == NULL) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > goto bad; > } > } > @@ -5887,7 +5887,7 @@ pf_route(struct mbuf **m, struct pf_pdes > if (ifp->if_capabilities & IFCAP_CSUM_IPv4) > m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > else { > - ipstat.ips_outswcsum++; > + ipstat_inc(ips_outswcsum); > ip->ip_sum = in_cksum(m0, ip->ip_hl << 2); > } > error = ifp->if_output(ifp, m0, sintosa(dst), rt); > @@ -5899,7 +5899,7 @@ pf_route(struct mbuf **m, struct pf_pdes > * Must be able to put at least 8 bytes per fragment. > */ > if (ip->ip_off & htons(IP_DF)) { > - ipstat.ips_cantfrag++; > + ipstat_inc(ips_cantfrag); > if (r->rt != PF_DUPTO) { > icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0, > ifp->if_mtu); > @@ -5925,7 +5925,7 @@ pf_route(struct mbuf **m, struct pf_pdes > } > > if (error == 0) > - ipstat.ips_fragmented++; > + ipstat_inc(ips_fragmented); > > done: > if (r->rt != PF_DUPTO) > Index: netinet/ip_icmp.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_icmp.c,v > retrieving revision 1.152 > diff -u -p -r1.152 ip_icmp.c > --- netinet/ip_icmp.c 22 Aug 2016 15:37:23 -0000 1.152 > +++ netinet/ip_icmp.c 9 Nov 2016 04:45:23 -0000 > @@ -751,7 +751,7 @@ icmp_reflect(struct mbuf *m, struct mbuf > /* keep packet in the original virtual instance */ > rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid); > if (rt == NULL) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > m_freem(m); > return (EHOSTUNREACH); > } > Index: netinet/ip_input.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_input.c,v > retrieving revision 1.282 > diff -u -p -r1.282 ip_input.c > --- netinet/ip_input.c 22 Sep 2016 10:12:25 -0000 1.282 > +++ netinet/ip_input.c 9 Nov 2016 04:45:23 -0000 > @@ -120,7 +120,9 @@ struct niqueue ipintrq = NIQUEUE_INITIAL > struct pool ipqent_pool; > struct pool ipq_pool; > > -struct ipstat ipstat; > +struct cpumem *ipcounters; > + > +int ip_sysctl_ipstat(void *, size_t *, void *); > > static struct mbuf_queue ipsend_mq; > > @@ -132,7 +134,7 @@ void ip_forward(struct mbuf *, struct if > int ip_input_ipsec_fwd_check(struct mbuf *, int); > int ip_input_ipsec_ours_check(struct mbuf *, int); > #endif /* IPSEC */ > - > + > static void ip_send_dispatch(void *); > static struct task ipsend_task = TASK_INITIALIZER(ip_send_dispatch, > &ipsend_mq); > /* > @@ -166,6 +168,8 @@ ip_init(void) > const u_int16_t defrootonlyports_tcp[] = DEFROOTONLYPORTS_TCP; > const u_int16_t defrootonlyports_udp[] = DEFROOTONLYPORTS_UDP; > > + ipcounters = counters_alloc(ips_ncounters, M_PCB); > + > pool_init(&ipqent_pool, sizeof(struct ipqent), 0, > IPL_SOFTNET, 0, "ipqe", NULL); > pool_init(&ipq_pool, sizeof(struct ipq), 0, > @@ -247,25 +251,25 @@ ipv4_input(struct mbuf *m) > if (ifp == NULL) > goto bad; > > - ipstat.ips_total++; > + ipstat_inc(ips_total); > if (m->m_len < sizeof (struct ip) && > (m = m_pullup(m, sizeof (struct ip))) == NULL) { > - ipstat.ips_toosmall++; > + ipstat_inc(ips_toosmall); > goto out; > } > ip = mtod(m, struct ip *); > if (ip->ip_v != IPVERSION) { > - ipstat.ips_badvers++; > + ipstat_inc(ips_badvers); > goto bad; > } > hlen = ip->ip_hl << 2; > if (hlen < sizeof(struct ip)) { /* minimum header length */ > - ipstat.ips_badhlen++; > + ipstat_inc(ips_badhlen); > goto bad; > } > if (hlen > m->m_len) { > if ((m = m_pullup(m, hlen)) == NULL) { > - ipstat.ips_badhlen++; > + ipstat_inc(ips_badhlen); > goto out; > } > ip = mtod(m, struct ip *); > @@ -275,20 +279,20 @@ ipv4_input(struct mbuf *m) > if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || > (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { > if ((ifp->if_flags & IFF_LOOPBACK) == 0) { > - ipstat.ips_badaddr++; > + ipstat_inc(ips_badaddr); > goto bad; > } > } > > if ((m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_OK) == 0) { > if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_IN_BAD) { > - ipstat.ips_badsum++; > + ipstat_inc(ips_badsum); > goto bad; > } > > - ipstat.ips_inswcsum++; > + ipstat_inc(ips_inswcsum); > if (in_cksum(m, hlen) != 0) { > - ipstat.ips_badsum++; > + ipstat_inc(ips_badsum); > goto bad; > } > } > @@ -300,7 +304,7 @@ ipv4_input(struct mbuf *m) > * Convert fields to host representation. > */ > if (len < hlen) { > - ipstat.ips_badlen++; > + ipstat_inc(ips_badlen); > goto bad; > } > > @@ -311,7 +315,7 @@ ipv4_input(struct mbuf *m) > * Drop packet if shorter than we expect. > */ > if (m->m_pkthdr.len < len) { > - ipstat.ips_tooshort++; > + ipstat_inc(ips_tooshort); > goto bad; > } > if (m->m_pkthdr.len > len) { > @@ -370,7 +374,7 @@ ipv4_input(struct mbuf *m) > if (ipmforwarding && ip_mrouter) { > if (m->m_flags & M_EXT) { > if ((m = m_pullup(m, hlen)) == NULL) { > - ipstat.ips_toosmall++; > + ipstat_inc(ips_toosmall); > goto out; > } > ip = mtod(m, struct ip *); > @@ -391,7 +395,7 @@ ipv4_input(struct mbuf *m) > rv = ip_mforward(m, ifp); > KERNEL_UNLOCK(); > if (rv != 0) { > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > goto bad; > } > > @@ -404,7 +408,7 @@ ipv4_input(struct mbuf *m) > ip_ours(m); > goto out; > } > - ipstat.ips_forward++; > + ipstat_inc(ips_forward); > } > #endif > /* > @@ -412,9 +416,9 @@ ipv4_input(struct mbuf *m) > * arrival interface. > */ > if (!in_hasmulti(&ip->ip_dst, ifp)) { > - ipstat.ips_notmember++; > + ipstat_inc(ips_notmember); > if (!IN_LOCAL_GROUP(ip->ip_dst.s_addr)) > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > goto bad; > } > ip_ours(m); > @@ -436,7 +440,7 @@ ipv4_input(struct mbuf *m) > * Not for us; forward if possible and desirable. > */ > if (ipforwarding == 0) { > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > goto bad; > } > #ifdef IPSEC > @@ -445,7 +449,7 @@ ipv4_input(struct mbuf *m) > rv = ip_input_ipsec_fwd_check(m, hlen); > KERNEL_UNLOCK(); > if (rv != 0) { > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > goto bad; > } > /* > @@ -493,7 +497,7 @@ ip_ours(struct mbuf *m) > if (ip->ip_off &~ htons(IP_DF | IP_RF)) { > if (m->m_flags & M_EXT) { /* XXX */ > if ((m = m_pullup(m, hlen)) == NULL) { > - ipstat.ips_toosmall++; > + ipstat_inc(ips_toosmall); > return; > } > ip = mtod(m, struct ip *); > @@ -526,7 +530,7 @@ found: > */ > if (ntohs(ip->ip_len) == 0 || > (ntohs(ip->ip_len) & 0x7) != 0) { > - ipstat.ips_badfrags++; > + ipstat_inc(ips_badfrags); > goto bad; > } > } > @@ -538,16 +542,16 @@ found: > * attempt reassembly; if it succeeds, proceed. > */ > if (mff || ip->ip_off) { > - ipstat.ips_fragments++; > + ipstat_inc(ips_fragments); > if (ip_frags + 1 > ip_maxqueue) { > ip_flush(); > - ipstat.ips_rcvmemdrop++; > + ipstat_inc(ips_rcvmemdrop); > goto bad; > } > > ipqe = pool_get(&ipqent_pool, PR_NOWAIT); > if (ipqe == NULL) { > - ipstat.ips_rcvmemdrop++; > + ipstat_inc(ips_rcvmemdrop); > goto bad; > } > ip_frags++; > @@ -558,7 +562,7 @@ found: > if (m == NULL) { > return; > } > - ipstat.ips_reassembled++; > + ipstat_inc(ips_reassembled); > ip = mtod(m, struct ip *); > hlen = ip->ip_hl << 2; > ip->ip_len = htons(ntohs(ip->ip_len) + hlen); > @@ -570,7 +574,7 @@ found: > #ifdef IPSEC > if (ipsec_in_use) { > if (ip_input_ipsec_ours_check(m, hlen) != 0) { > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > goto bad; > } > } > @@ -580,7 +584,7 @@ found: > /* > * Switch out to protocol's input routine. > */ > - ipstat.ips_delivered++; > + ipstat_inc(ips_delivered); > (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen, NULL, 0); > return; > bad: > @@ -896,7 +900,7 @@ insert: > q = LIST_FIRST(&fp->ipq_fragq); > ip = q->ipqe_ip; > if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) { > - ipstat.ips_toolong++; > + ipstat_inc(ips_toolong); > ip_freef(fp); > return (0); > } > @@ -938,7 +942,7 @@ insert: > return (m); > > dropfrag: > - ipstat.ips_fragdropped++; > + ipstat_inc(ips_fragdropped); > m_freem(m); > pool_put(&ipqent_pool, ipqe); > ip_frags--; > @@ -979,7 +983,7 @@ ip_slowtimo(void) > for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) { > nfp = LIST_NEXT(fp, ipq_q); > if (--fp->ipq_ttl == 0) { > - ipstat.ips_fragtimeout++; > + ipstat_inc(ips_fragtimeout); > ip_freef(fp); > } > } > @@ -993,7 +997,7 @@ void > ip_drain(void) > { > while (!LIST_EMPTY(&ipq)) { > - ipstat.ips_fragdropped++; > + ipstat_inc(ips_fragdropped); > ip_freef(LIST_FIRST(&ipq)); > } > } > @@ -1008,7 +1012,7 @@ ip_flush(void) > > /* ipq already locked */ > while (!LIST_EMPTY(&ipq) && ip_frags > ip_maxqueue * 3 / 4 && --max) { > - ipstat.ips_fragdropped++; > + ipstat_inc(ips_fragdropped); > ip_freef(LIST_FIRST(&ipq)); > } > } > @@ -1263,7 +1267,7 @@ ip_dooptions(struct mbuf *m, struct ifne > bad: > KERNEL_UNLOCK(); > icmp_error(m, type, code, 0, 0); > - ipstat.ips_badoptions++; > + ipstat_inc(ips_badoptions); > return (1); > } > > @@ -1413,7 +1417,7 @@ ip_forward(struct mbuf *m, struct ifnet > > dest = 0; > if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) { > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > m_freem(m); > goto freecopy; > } > @@ -1494,11 +1498,11 @@ ip_forward(struct mbuf *m, struct ifnet > NULL, NULL, 0); > rt = ro.ro_rt; > if (error) > - ipstat.ips_cantforward++; > + ipstat_inc(ips_cantforward); > else { > - ipstat.ips_forward++; > + ipstat_inc(ips_forward); > if (type) > - ipstat.ips_redirectsent++; > + ipstat_inc(ips_redirectsent); > else > goto freecopy; > } > @@ -1538,7 +1542,7 @@ ip_forward(struct mbuf *m, struct ifnet > } > } > #endif /*IPSEC*/ > - ipstat.ips_cantfrag++; > + ipstat_inc(ips_cantfrag); > break; > > case EACCES: > @@ -1632,8 +1636,7 @@ ip_sysctl(int *name, u_int namelen, void > return (sysctl_niq(name + 1, namelen - 1, > oldp, oldlenp, newp, newlen, &ipintrq)); > case IPCTL_STATS: > - return (sysctl_rdstruct(oldp, oldlenp, newp, > - &ipstat, sizeof(ipstat))); > + return (ip_sysctl_ipstat(oldp, oldlenp, newp)); > #ifdef MROUTING > case IPCTL_MRTSTATS: > return (sysctl_rdstruct(oldp, oldlenp, newp, > @@ -1662,6 +1665,24 @@ ip_sysctl(int *name, u_int namelen, void > return (EOPNOTSUPP); > } > /* NOTREACHED */ > +} > + > +int > +ip_sysctl_ipstat(void *oldp, size_t *oldlenp, void *newp) > +{ > + uint64_t counters[ips_ncounters]; > + struct ipstat ipstat; > + u_long *words = (u_long *)&ipstat; > + int i; > + > + KASSERT(sizeof(ipstat) == (nitems(counters) * sizeof(u_long))); > + > + counters_read(ipcounters, counters, nitems(counters)); > + > + for (i = 0; i < nitems(counters); i++) > + words[i] = (u_long)counters[i]; > + > + return (sysctl_rdstruct(oldp, oldlenp, newp, &ipstat, sizeof(ipstat))); > } > > void > Index: netinet/ip_output.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_output.c,v > retrieving revision 1.327 > diff -u -p -r1.327 ip_output.c > --- netinet/ip_output.c 4 Sep 2016 17:18:56 -0000 1.327 > +++ netinet/ip_output.c 9 Nov 2016 04:45:23 -0000 > @@ -133,7 +133,7 @@ ip_output(struct mbuf *m0, struct mbuf * > ip->ip_off &= htons(IP_DF); > ip->ip_id = htons(ip_randomid()); > ip->ip_hl = hlen >> 2; > - ipstat.ips_localout++; > + ipstat_inc(ips_localout); > } else { > hlen = ip->ip_hl << 2; > } > @@ -204,7 +204,7 @@ reroute: > &ip->ip_src.s_addr, ro->ro_tableid); > > if (ro->ro_rt == NULL) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > error = EHOSTUNREACH; > goto bad; > } > @@ -284,7 +284,7 @@ reroute: > * output > */ > if (!ifp) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > error = EHOSTUNREACH; > goto bad; > } > @@ -298,7 +298,7 @@ reroute: > (ifp->if_flags & IFF_MULTICAST) == 0) || > ((m->m_flags & M_BCAST) && > (ifp->if_flags & IFF_BROADCAST) == 0)) && (tdb == NULL)) { > - ipstat.ips_noroute++; > + ipstat_inc(ips_noroute); > error = ENETUNREACH; > goto bad; > } > @@ -464,7 +464,7 @@ sendit: > (ifp->if_bridgeport == NULL)) > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > else { > - ipstat.ips_outswcsum++; > + ipstat_inc(ips_outswcsum); > ip->ip_sum = in_cksum(m, hlen); > } > > @@ -495,7 +495,7 @@ sendit: > (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) { > ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu; > } > - ipstat.ips_cantfrag++; > + ipstat_inc(ips_cantfrag); > goto bad; > } > > @@ -515,7 +515,7 @@ sendit: > } > > if (error == 0) > - ipstat.ips_fragmented++; > + ipstat_inc(ips_fragmented); > > done: > if (ro == &iproute && ro->ro_rt) > @@ -676,7 +676,7 @@ ip_fragment(struct mbuf *m, struct ifnet > for (off = hlen + len; off < ntohs(ip->ip_len); off += len) { > MGETHDR(m, M_DONTWAIT, MT_HEADER); > if (m == NULL) { > - ipstat.ips_odropped++; > + ipstat_inc(ips_odropped); > error = ENOBUFS; > goto sendorfree; > } > @@ -705,7 +705,7 @@ ip_fragment(struct mbuf *m, struct ifnet > mhip->ip_len = htons((u_int16_t)(len + mhlen)); > m->m_next = m_copym(m0, off, len, M_NOWAIT); > if (m->m_next == 0) { > - ipstat.ips_odropped++; > + ipstat_inc(ips_odropped); > error = ENOBUFS; > goto sendorfree; > } > @@ -718,10 +718,10 @@ ip_fragment(struct mbuf *m, struct ifnet > (ifp->if_bridgeport == NULL)) > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > else { > - ipstat.ips_outswcsum++; > + ipstat_inc(ips_outswcsum); > mhip->ip_sum = in_cksum(m, mhlen); > } > - ipstat.ips_ofragments++; > + ipstat_inc(ips_ofragments); > fragments++; > } > /* > @@ -739,7 +739,7 @@ ip_fragment(struct mbuf *m, struct ifnet > (ifp->if_bridgeport == NULL)) > m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT; > else { > - ipstat.ips_outswcsum++; > + ipstat_inc(ips_outswcsum); > ip->ip_sum = in_cksum(m, hlen); > } > sendorfree: > Index: netinet/ip_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_var.h,v > retrieving revision 1.62 > diff -u -p -r1.62 ip_var.h > --- netinet/ip_var.h 15 Apr 2016 11:18:40 -0000 1.62 > +++ netinet/ip_var.h 9 Nov 2016 04:45:23 -0000 > @@ -96,6 +96,53 @@ struct ipoption { > > #ifdef _KERNEL > > +#include <sys/percpu.h> > + > +enum ipstat_counters { > + ips_total, /* total packets received */ > + ips_badsum, /* checksum bad */ > + ips_tooshort, /* packet too short */ > + ips_toosmall, /* not enough data */ > + ips_badhlen, /* ip header length < data size */ > + ips_badlen, /* ip length < ip header length */ > + ips_fragments, /* fragments received */ > + ips_fragdropped, /* frags dropped (dups, out of space) */ > + ips_fragtimeout, /* fragments timed out */ > + ips_forward, /* packets forwarded */ > + ips_cantforward, /* packets rcvd for unreachable dest */ > + ips_redirectsent, /* packets forwarded on same net */ > + ips_noproto, /* unknown or unsupported protocol */ > + ips_delivered, /* datagrams delivered to upper level*/ > + ips_localout, /* total ip packets generated here */ > + ips_odropped, /* lost packets due to nobufs, etc. */ > + ips_reassembled, /* total packets reassembled ok */ > + ips_fragmented, /* datagrams successfully fragmented */ > + ips_ofragments, /* output fragments created */ > + ips_cantfrag, /* don't fragment flag was set, etc. */ > + ips_badoptions, /* error in option processing */ > + ips_noroute, /* packets discarded due to no route */ > + ips_badvers, /* ip version != 4 */ > + ips_rawout, /* total raw ip packets generated */ > + ips_badfrags, /* malformed fragments (bad length) */ > + ips_rcvmemdrop, /* frags dropped for lack of memory */ > + ips_toolong, /* ip length > max ip packet size */ > + ips_nogif, /* no match gif found */ > + ips_badaddr, /* invalid address on header */ > + ips_inswcsum, /* software checksummed on input */ > + ips_outswcsum, /* software checksummed on output */ > + ips_notmember, /* multicasts for unregistered groups */ > + > + ips_ncounters > +}; > + > +extern struct cpumem *ipcounters; > + > +static inline void > +ipstat_inc(enum ipstat_counters c) > +{ > + counters_inc(ipcounters, c); > +} > + > /* > * Structure attached to inpcb.ip_moptions and > * passed to ip_output when IP multicast options are in use. > Index: netinet/raw_ip.c > =================================================================== > RCS file: /cvs/src/sys/netinet/raw_ip.c,v > retrieving revision 1.86 > diff -u -p -r1.86 raw_ip.c > --- netinet/raw_ip.c 7 Mar 2016 18:44:00 -0000 1.86 > +++ netinet/raw_ip.c 9 Nov 2016 04:45:23 -0000 > @@ -126,6 +126,8 @@ rip_input(struct mbuf *m, ...) > struct ip *ip = mtod(m, struct ip *); > struct inpcb *inp, *last = NULL; > struct mbuf *opts = NULL; > + struct counters_ref ref; > + uint64_t *counters; > > ripsrc.sin_addr = ip->ip_src; > TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) { > @@ -195,8 +197,11 @@ rip_input(struct mbuf *m, ...) > icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, > 0); > else > m_freem(m); > - ipstat.ips_noproto++; > - ipstat.ips_delivered--; > + > + counters = counters_enter(&ref, ipcounters); > + counters[ips_noproto]++; > + counters[ips_delivered]--; > + counters_leave(&ref, ipcounters); > } > } > > @@ -267,7 +272,7 @@ rip_output(struct mbuf *m, ...) > } > /* XXX prevent ip_output from overwriting header fields */ > flags |= IP_RAWOUTPUT; > - ipstat.ips_rawout++; > + ipstat_inc(ips_rawout); > } > #ifdef INET6 > /* > Index: sys/percpu.h > =================================================================== > RCS file: /cvs/src/sys/sys/percpu.h,v > retrieving revision 1.3 > diff -u -p -r1.3 percpu.h > --- sys/percpu.h 24 Oct 2016 23:58:33 -0000 1.3 > +++ sys/percpu.h 9 Nov 2016 04:45:23 -0000 > @@ -138,6 +138,40 @@ counters_leave(struct counters_ref *ref, > cpumem_leave(cm, ref->c); > } > > +static inline void > +counters_inc(struct cpumem *cm, unsigned int c) > +{ > + struct counters_ref ref; > + uint64_t *counters; > + > + counters = counters_enter(&ref, cm); > + counters[c]++; > + counters_leave(&ref, cm); > +} > + > +static inline void > +counters_add(struct cpumem *cm, unsigned int c, uint64_t v) > +{ > + struct counters_ref ref; > + uint64_t *counters; > + > + counters = counters_enter(&ref, cm); > + counters[c] += v; > + counters_leave(&ref, cm); > +} > + > +static inline void > +counters_pkt(struct cpumem *cm, unsigned int c, unsigned int b, uint64_t v) > +{ > + struct counters_ref ref; > + uint64_t *counters; > + > + counters = counters_enter(&ref, cm); > + counters[c]++; > + counters[b] += v; > + counters_leave(&ref, cm); > +} > + > #ifdef MULTIPROCESSOR > #define COUNTERS_BOOT_MEMORY(_name, _n) > \ > CPUMEM_BOOT_MEMORY(_name, ((_n) + 1) * sizeof(uint64_t)) >