> On 18 Nov 2016, at 20:11, Jonathan Matthew <jonat...@d14n.org> wrote: > > This is much like the other per cpu counter conversions, except the counter > enum has gaps in it to match the arrays in struct icmpstat.
ok by me > > Index: icmp_var.h > =================================================================== > RCS file: /cvs/src/sys/netinet/icmp_var.h,v > retrieving revision 1.14 > diff -u -p -u -p -r1.14 icmp_var.h > --- icmp_var.h 19 Jan 2014 05:01:50 -0000 1.14 > +++ icmp_var.h 18 Nov 2016 09:02:48 -0000 > @@ -91,6 +91,32 @@ struct icmpstat { > } > > #ifdef _KERNEL > -extern struct icmpstat icmpstat; > + > +#include <sys/percpu.h> > + > +enum icmpstat_counters { > + icps_error, > + icps_toofreq, > + icps_oldshort, > + icps_oldicmp, > + icps_outhist, > + icps_badcode = icps_outhist + ICMP_MAXTYPE + 1, > + icps_tooshort, > + icps_checksum, > + icps_badlen, > + icps_reflect, > + icps_bmcastecho, > + icps_inhist, > + icps_ncounters = icps_inhist + ICMP_MAXTYPE + 1 > +}; > + > +static inline void > +icmpstat_inc(enum icmpstat_counters c) > +{ > + extern struct cpumem *icmpcounters; > + counters_inc(icmpcounters, c); > +} > + > +extern struct cpumem *icmpcounters; > #endif /* _KERNEL */ > #endif /* _NETINET_ICMP_VAR_H_ */ > Index: ip_icmp.c > =================================================================== > RCS file: /cvs/src/sys/netinet/ip_icmp.c,v > retrieving revision 1.156 > diff -u -p -u -p -r1.156 ip_icmp.c > --- ip_icmp.c 16 Nov 2016 12:48:19 -0000 1.156 > +++ ip_icmp.c 18 Nov 2016 09:02:48 -0000 > @@ -121,7 +121,7 @@ static int icmperrpps_count = 0; > static struct timeval icmperrppslim_last; > > static struct rttimer_queue *icmp_redirect_timeout_q = NULL; > -struct icmpstat icmpstat; > +struct cpumem *icmpcounters; > > int *icmpctl_vars[ICMPCTL_MAXID] = ICMPCTL_VARS; > > @@ -129,10 +129,12 @@ void icmp_mtudisc_timeout(struct rtentry > int icmp_ratelimit(const struct in_addr *, const int, const int); > void icmp_redirect_timeout(struct rtentry *, struct rttimer *); > void icmp_input_if(struct ifnet *, struct mbuf *, int); > +int icmp_sysctl_icmpstat(void *, size_t *, void *); > > void > icmp_init(void) > { > + icmpcounters = counters_alloc(icps_ncounters, M_COUNTERS); > /* > * This is only useful if the user initializes redirtimeout to > * something other than zero. > @@ -157,7 +159,7 @@ icmp_do_error(struct mbuf *n, int type, > printf("icmp_error(%x, %d, %d)\n", oip, type, code); > #endif > if (type != ICMP_REDIRECT) > - icmpstat.icps_error++; > + icmpstat_inc(icps_error); > /* > * Don't send error if not the first fragment of message. > * Don't error if the old packet protocol was ICMP > @@ -169,7 +171,7 @@ icmp_do_error(struct mbuf *n, int type, > n->m_len >= oiplen + ICMP_MINLEN && > !ICMP_INFOTYPE(((struct icmp *) > ((caddr_t)oip + oiplen))->icmp_type)) { > - icmpstat.icps_oldicmp++; > + icmpstat_inc(icps_oldicmp); > goto freeit; > } > /* Don't send error in response to a multicast or broadcast packet */ > @@ -180,7 +182,7 @@ icmp_do_error(struct mbuf *n, int type, > * First, do a rate limitation check. > */ > if (icmp_ratelimit(&oip->ip_src, type, code)) { > - icmpstat.icps_toofreq++; > + icmpstat_inc(icps_toofreq); > goto freeit; > } > > @@ -227,7 +229,7 @@ icmp_do_error(struct mbuf *n, int type, > icp = mtod(m, struct icmp *); > if ((u_int)type > ICMP_MAXTYPE) > panic("icmp_error"); > - icmpstat.icps_outhist[type]++; > + icmpstat_inc(icps_outhist + type); > icp->icmp_type = type; > if (type == ICMP_REDIRECT) > icp->icmp_gwaddr.s_addr = dest; > @@ -351,17 +353,17 @@ icmp_input_if(struct ifnet *ifp, struct > } > #endif > if (icmplen < ICMP_MINLEN) { > - icmpstat.icps_tooshort++; > + icmpstat_inc(icps_tooshort); > goto freeit; > } > i = hlen + min(icmplen, ICMP_ADVLENMIN); > if (m->m_len < i && (m = m_pullup(m, i)) == NULL) { > - icmpstat.icps_tooshort++; > + icmpstat_inc(icps_tooshort); > return; > } > ip = mtod(m, struct ip *); > if (in4_cksum(m, 0, hlen, icmplen)) { > - icmpstat.icps_checksum++; > + icmpstat_inc(icps_checksum); > goto freeit; > } > > @@ -399,7 +401,7 @@ icmp_input_if(struct ifnet *ifp, struct > } > } > #endif /* NPF */ > - icmpstat.icps_inhist[icp->icmp_type]++; > + icmpstat_inc(icps_inhist + icp->icmp_type); > code = icp->icmp_code; > switch (icp->icmp_type) { > > @@ -464,7 +466,7 @@ icmp_input_if(struct ifnet *ifp, struct > */ > if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || > icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { > - icmpstat.icps_badlen++; > + icmpstat_inc(icps_badlen); > goto freeit; > } > if (IN_MULTICAST(icp->icmp_ip.ip_dst.s_addr)) > @@ -474,12 +476,12 @@ icmp_input_if(struct ifnet *ifp, struct > if (icp->icmp_ip.ip_p == IPPROTO_IPV6) { > if (icmplen < ICMP_V6ADVLENMIN || > icmplen < ICMP_V6ADVLEN(icp)) { > - icmpstat.icps_badlen++; > + icmpstat_inc(icps_badlen); > goto freeit; > } else { > if ((m = m_pullup(m, (ip->ip_hl << 2) + > ICMP_V6ADVLEN(icp))) == NULL) { > - icmpstat.icps_tooshort++; > + icmpstat_inc(icps_tooshort); > return; > } > ip = mtod(m, struct ip *); > @@ -513,13 +515,13 @@ icmp_input_if(struct ifnet *ifp, struct > break; > > badcode: > - icmpstat.icps_badcode++; > + icmpstat_inc(icps_badcode); > break; > > case ICMP_ECHO: > if (!icmpbmcastecho && > (m->m_flags & (M_MCAST | M_BCAST)) != 0) { > - icmpstat.icps_bmcastecho++; > + icmpstat_inc(icps_bmcastecho); > break; > } > icp->icmp_type = ICMP_ECHOREPLY; > @@ -531,11 +533,11 @@ icmp_input_if(struct ifnet *ifp, struct > > if (!icmpbmcastecho && > (m->m_flags & (M_MCAST | M_BCAST)) != 0) { > - icmpstat.icps_bmcastecho++; > + icmpstat_inc(icps_bmcastecho); > break; > } > if (icmplen < ICMP_TSLEN) { > - icmpstat.icps_badlen++; > + icmpstat_inc(icps_badlen); > break; > } > icp->icmp_type = ICMP_TSTAMPREPLY; > @@ -547,7 +549,7 @@ icmp_input_if(struct ifnet *ifp, struct > if (icmpmaskrepl == 0) > break; > if (icmplen < ICMP_MASKLEN) { > - icmpstat.icps_badlen++; > + icmpstat_inc(icps_badlen); > break; > } > /* > @@ -590,8 +592,8 @@ reflect: > if (m->m_flags & M_PKTHDR) > m_tag_delete_chain(m); > > - icmpstat.icps_reflect++; > - icmpstat.icps_outhist[icp->icmp_type]++; > + icmpstat_inc(icps_reflect); > + icmpstat_inc(icps_outhist + icp->icmp_type); > if (!icmp_reflect(m, &opts, NULL)) > icmp_send(m, opts); > return; > @@ -612,7 +614,7 @@ reflect: > goto badcode; > if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) || > icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) { > - icmpstat.icps_badlen++; > + icmpstat_inc(icps_badlen); > break; > } > /* > @@ -908,8 +910,7 @@ icmp_sysctl(int *name, u_int namelen, vo > error = EPERM; > break; > } > - error = sysctl_struct(oldp, oldlenp, newp, newlen, > - &icmpstat, sizeof(icmpstat)); > + error = icmp_sysctl_icmpstat(oldp, oldlenp, newp); > break; > > default: > @@ -926,6 +927,24 @@ icmp_sysctl(int *name, u_int namelen, vo > return (error); > } > > +int > +icmp_sysctl_icmpstat(void *oldp, size_t *oldlenp, void *newp) > +{ > + uint64_t counters[icps_ncounters]; > + struct icmpstat icmpstat; > + u_long *words = (u_long *)&icmpstat; > + int i; > + > + KASSERT(sizeof(icmpstat) == (nitems(counters) * sizeof(u_long))); > + > + counters_read(icmpcounters, counters, nitems(counters)); > + > + for (i = 0; i < nitems(counters); i++) > + words[i] = (u_long)counters[i]; > + > + return (sysctl_rdstruct(oldp, oldlenp, newp, > + &icmpstat, sizeof(icmpstat))); > +} > > struct rtentry * > icmp_mtudisc_clone(struct in_addr dst, u_int rtableid) >