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.

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)

Reply via email to