In icmp6_errcount() we could save a few function calls but I preferred to keep the conversion as mechanical as possible. Works fine here on amd64 (I can test armv7 soon).
ok? Index: netinet/icmp6.h =================================================================== RCS file: /d/cvs/src/sys/netinet/icmp6.h,v retrieving revision 1.42 diff -u -p -r1.42 icmp6.h --- netinet/icmp6.h 9 Sep 2015 15:51:40 -0000 1.42 +++ netinet/icmp6.h 6 Feb 2017 07:10:21 -0000 @@ -457,22 +457,6 @@ struct icmp6_filter { * Variables related to this implementation * of the internet control message protocol version 6. */ -struct icmp6errstat { - u_int64_t icp6errs_dst_unreach_noroute; - u_int64_t icp6errs_dst_unreach_admin; - u_int64_t icp6errs_dst_unreach_beyondscope; - u_int64_t icp6errs_dst_unreach_addr; - u_int64_t icp6errs_dst_unreach_noport; - u_int64_t icp6errs_packet_too_big; - u_int64_t icp6errs_time_exceed_transit; - u_int64_t icp6errs_time_exceed_reassembly; - u_int64_t icp6errs_paramprob_header; - u_int64_t icp6errs_paramprob_nextheader; - u_int64_t icp6errs_paramprob_option; - u_int64_t icp6errs_redirect; /* we regard redirect as an error here */ - u_int64_t icp6errs_unknown; -}; - struct icmp6stat { /* statistics related to icmp6 packets generated */ u_int64_t icp6s_error; /* # of calls to icmp6_error */ @@ -491,25 +475,19 @@ struct icmp6stat { u_int64_t icp6s_reflect; u_int64_t icp6s_inhist[256]; u_int64_t icp6s_nd_toomanyopt; /* too many ND options */ - struct icmp6errstat icp6s_outerrhist; -#define icp6s_odst_unreach_noroute \ - icp6s_outerrhist.icp6errs_dst_unreach_noroute -#define icp6s_odst_unreach_admin icp6s_outerrhist.icp6errs_dst_unreach_admin -#define icp6s_odst_unreach_beyondscope \ - icp6s_outerrhist.icp6errs_dst_unreach_beyondscope -#define icp6s_odst_unreach_addr icp6s_outerrhist.icp6errs_dst_unreach_addr -#define icp6s_odst_unreach_noport icp6s_outerrhist.icp6errs_dst_unreach_noport -#define icp6s_opacket_too_big icp6s_outerrhist.icp6errs_packet_too_big -#define icp6s_otime_exceed_transit \ - icp6s_outerrhist.icp6errs_time_exceed_transit -#define icp6s_otime_exceed_reassembly \ - icp6s_outerrhist.icp6errs_time_exceed_reassembly -#define icp6s_oparamprob_header icp6s_outerrhist.icp6errs_paramprob_header -#define icp6s_oparamprob_nextheader \ - icp6s_outerrhist.icp6errs_paramprob_nextheader -#define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option -#define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect -#define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown + u_int64_t icp6s_odst_unreach_noroute; + u_int64_t icp6s_odst_unreach_admin; + u_int64_t icp6s_odst_unreach_beyondscope; + u_int64_t icp6s_odst_unreach_addr; + u_int64_t icp6s_odst_unreach_noport; + u_int64_t icp6s_opacket_too_big; + u_int64_t icp6s_otime_exceed_transit; + u_int64_t icp6s_otime_exceed_reassembly; + u_int64_t icp6s_oparamprob_header; + u_int64_t icp6s_oparamprob_nextheader; + u_int64_t icp6s_oparamprob_option; + u_int64_t icp6s_oredirect; /* we regard redirect as an error here */ + u_int64_t icp6s_ounknown; u_int64_t icp6s_pmtuchg; /* path MTU changes */ u_int64_t icp6s_nd_badopt; /* bad ND options */ u_int64_t icp6s_badns; /* bad neighbor solicitation */ @@ -590,6 +568,51 @@ struct icmp6stat { #define RTF_PROBEMTU RTF_PROTO1 #ifdef _KERNEL + +#include <sys/percpu.h> + +enum icmp6stat_counters { + icp6s_error, + icp6s_canterror, + icp6s_toofreq, + icp6s_outhist, + icp6s_badcode = icp6s_outhist + 256, + icp6s_tooshort, + icp6s_checksum, + icp6s_badlen, + icp6s_reflect, + icp6s_inhist, + icp6s_nd_toomanyopt = icp6s_inhist + 256, + icp6s_odst_unreach_noroute, + icp6s_odst_unreach_admin, + icp6s_odst_unreach_beyondscope, + icp6s_odst_unreach_addr, + icp6s_odst_unreach_noport, + icp6s_opacket_too_big, + icp6s_otime_exceed_transit, + icp6s_otime_exceed_reassembly, + icp6s_oparamprob_header, + icp6s_oparamprob_nextheader, + icp6s_oparamprob_option, + icp6s_oredirect, + icp6s_ounknown, + icp6s_pmtuchg, + icp6s_nd_badopt, + icp6s_badns, + icp6s_badna, + icp6s_badrs, + icp6s_badra, + icp6s_badredirect, + icp6s_ncounters, +}; + +extern struct cpumem *icmp6counters; + +static inline void +icmp6stat_inc(enum icmp6stat_counters c) +{ + counters_inc(icmp6counters, c); +} struct rtentry; struct rttimer; Index: netinet6/icmp6.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/icmp6.c,v retrieving revision 1.199 diff -u -p -r1.199 icmp6.c --- netinet6/icmp6.c 5 Feb 2017 16:04:14 -0000 1.199 +++ netinet6/icmp6.c 6 Feb 2017 08:25:47 -0000 @@ -102,7 +102,7 @@ #include <net/pfvar.h> #endif -struct icmp6stat icmp6stat; +struct cpumem *icmp6counters; extern struct inpcbtable rawin6pcbtable; extern int icmp6errppslim; @@ -134,7 +134,7 @@ static struct rttimer_queue *icmp6_redir /* XXX experimental, turned off */ static int icmp6_redirect_lowat = -1; -void icmp6_errcount(struct icmp6errstat *, int, int); +void icmp6_errcount(int, int); int icmp6_rip6_input(struct mbuf **, int); int icmp6_ratelimit(const struct in6_addr *, const int, const int); const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, @@ -150,62 +150,63 @@ icmp6_init(void) mld6_init(); icmp6_mtudisc_timeout_q = rt_timer_queue_create(ip6_mtudisc_timeout); icmp6_redirect_timeout_q = rt_timer_queue_create(icmp6_redirtimeout); + icmp6counters = counters_alloc(icp6s_ncounters); } void -icmp6_errcount(struct icmp6errstat *stat, int type, int code) +icmp6_errcount(int type, int code) { switch (type) { case ICMP6_DST_UNREACH: switch (code) { case ICMP6_DST_UNREACH_NOROUTE: - stat->icp6errs_dst_unreach_noroute++; + icmp6stat_inc(icp6s_odst_unreach_noroute); return; case ICMP6_DST_UNREACH_ADMIN: - stat->icp6errs_dst_unreach_admin++; + icmp6stat_inc(icp6s_odst_unreach_admin); return; case ICMP6_DST_UNREACH_BEYONDSCOPE: - stat->icp6errs_dst_unreach_beyondscope++; + icmp6stat_inc(icp6s_odst_unreach_beyondscope); return; case ICMP6_DST_UNREACH_ADDR: - stat->icp6errs_dst_unreach_addr++; + icmp6stat_inc(icp6s_odst_unreach_addr); return; case ICMP6_DST_UNREACH_NOPORT: - stat->icp6errs_dst_unreach_noport++; + icmp6stat_inc(icp6s_odst_unreach_noport); return; } break; case ICMP6_PACKET_TOO_BIG: - stat->icp6errs_packet_too_big++; + icmp6stat_inc(icp6s_opacket_too_big); return; case ICMP6_TIME_EXCEEDED: switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: - stat->icp6errs_time_exceed_transit++; + icmp6stat_inc(icp6s_otime_exceed_transit); return; case ICMP6_TIME_EXCEED_REASSEMBLY: - stat->icp6errs_time_exceed_reassembly++; + icmp6stat_inc(icp6s_otime_exceed_reassembly); return; } break; case ICMP6_PARAM_PROB: switch (code) { case ICMP6_PARAMPROB_HEADER: - stat->icp6errs_paramprob_header++; + icmp6stat_inc(icp6s_oparamprob_header); return; case ICMP6_PARAMPROB_NEXTHEADER: - stat->icp6errs_paramprob_nextheader++; + icmp6stat_inc(icp6s_oparamprob_nextheader); return; case ICMP6_PARAMPROB_OPTION: - stat->icp6errs_paramprob_option++; + icmp6stat_inc(icp6s_oparamprob_option); return; } break; case ND_REDIRECT: - stat->icp6errs_redirect++; + icmp6stat_inc(icp6s_oredirect); return; } - stat->icp6errs_unknown++; + icmp6stat_inc(icp6s_ounknown); } /* @@ -241,10 +242,10 @@ icmp6_error(struct mbuf *m, int type, in int off; int nxt; - icmp6stat.icp6s_error++; + icmp6stat_inc(icp6s_error); /* count per-type-code statistics */ - icmp6_errcount(&icmp6stat.icp6s_outerrhist, type, code); + icmp6_errcount(type, code); if (m->m_len < sizeof(struct ip6_hdr)) { m = m_pullup(m, sizeof(struct ip6_hdr)); @@ -291,7 +292,7 @@ icmp6_error(struct mbuf *m, int type, in IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off, sizeof(*icp)); if (icp == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return; } if (icp->icmp6_type < ICMP6_ECHO_REQUEST || @@ -301,7 +302,7 @@ icmp6_error(struct mbuf *m, int type, in * Special case: for redirect (which is * informational) we must not send icmp6 error. */ - icmp6stat.icp6s_canterror++; + icmp6stat_inc(icp6s_canterror); goto freeit; } else { /* ICMPv6 informational - send the error */ @@ -315,7 +316,7 @@ icmp6_error(struct mbuf *m, int type, in /* Finally, do rate limitation check. */ if (icmp6_ratelimit(&oip6->ip6_src, type, code)) { - icmp6stat.icp6s_toofreq++; + icmp6stat_inc(icp6s_toofreq); goto freeit; } @@ -358,7 +359,7 @@ icmp6_error(struct mbuf *m, int type, in */ m->m_pkthdr.ph_ifidx = 0; - icmp6stat.icp6s_outhist[type]++; + icmp6stat_inc(icp6s_outhist + type); icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */ return; @@ -394,7 +395,7 @@ icmp6_input(struct mbuf **mp, int *offp, ip6 = mtod(m, struct ip6_hdr *); if (icmp6len < sizeof(struct icmp6_hdr)) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); goto freeit; } @@ -403,7 +404,7 @@ icmp6_input(struct mbuf **mp, int *offp, */ IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6)); if (icmp6 == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return IPPROTO_DONE; } code = icmp6->icmp6_code; @@ -413,7 +414,7 @@ icmp6_input(struct mbuf **mp, int *offp, "ICMP6 checksum error(%d|%x) %s\n", icmp6->icmp6_type, sum, inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)))); - icmp6stat.icp6s_checksum++; + icmp6stat_inc(icp6s_checksum); goto freeit; } @@ -450,7 +451,7 @@ icmp6_input(struct mbuf **mp, int *offp, if_put(ifp); #endif - icmp6stat.icp6s_inhist[icmp6->icmp6_type]++; + icmp6stat_inc(icp6s_inhist + icmp6->icmp6_type); switch (icmp6->icmp6_type) { case ICMP6_DST_UNREACH: @@ -595,8 +596,8 @@ icmp6_input(struct mbuf **mp, int *offp, nicmp6->icmp6_type = ICMP6_ECHO_REPLY; nicmp6->icmp6_code = 0; if (n) { - icmp6stat.icp6s_reflect++; - icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++; + icmp6stat_inc(icp6s_reflect); + icmp6stat_inc(icp6s_outhist + ICMP6_ECHO_REPLY); icmp6_reflect(n, noff); } if (!m) @@ -745,11 +746,11 @@ deliver: break; badcode: - icmp6stat.icp6s_badcode++; + icmp6stat_inc(icp6s_badcode); break; badlen: - icmp6stat.icp6s_badlen++; + icmp6stat_inc(icp6s_badlen); break; } @@ -775,13 +776,13 @@ icmp6_notify_error(struct mbuf *m, int o struct sockaddr_in6 icmp6src, icmp6dst; if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); goto freeit; } IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6) + sizeof(struct ip6_hdr)); if (icmp6 == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } eip6 = (struct ip6_hdr *)(icmp6 + 1); @@ -810,7 +811,7 @@ icmp6_notify_error(struct mbuf *m, int o IP6_EXTHDR_GET(eh, struct ip6_ext *, m, eoff, sizeof(*eh)); if (eh == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } @@ -832,7 +833,7 @@ icmp6_notify_error(struct mbuf *m, int o IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m, eoff, sizeof(*rth)); if (rth == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } rthlen = (rth->ip6r_len + 1) << 3; @@ -852,7 +853,7 @@ icmp6_notify_error(struct mbuf *m, int o struct ip6_rthdr0 *, m, eoff, rthlen); if (rth0 == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } /* just ignore a bogus header */ @@ -867,7 +868,7 @@ icmp6_notify_error(struct mbuf *m, int o IP6_EXTHDR_GET(fh, struct ip6_frag *, m, eoff, sizeof(*fh)); if (fh == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } /* @@ -898,7 +899,7 @@ icmp6_notify_error(struct mbuf *m, int o IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6) + sizeof(struct ip6_hdr)); if (icmp6 == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return (-1); } @@ -1022,7 +1023,7 @@ icmp6_mtudisc_update(struct ip6ctlparam ifp = if_get(rt->rt_ifidx); if (ifp != NULL && mtu < ifp->if_mtu) { - icmp6stat.icp6s_pmtuchg++; + icmp6stat_inc(icp6s_pmtuchg); rt->rt_rmx.rmx_mtu = mtu; } if_put(ifp); @@ -1357,7 +1358,7 @@ icmp6_redirect_input(struct mbuf *m, int IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len); if (nd_rd == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } @@ -1538,7 +1539,7 @@ icmp6_redirect_input(struct mbuf *m, int bad: if_put(ifp); - icmp6stat.icp6s_badredirect++; + icmp6stat_inc(icp6s_badredirect); m_freem(m); } @@ -1556,7 +1557,7 @@ icmp6_redirect_output(struct mbuf *m0, s u_char *p; struct sockaddr_in6 src_sa; - icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0); + icmp6_errcount(ND_REDIRECT, 0); /* if we are not router, we don't send icmp6 redirect */ if (!ip6_forwarding) @@ -1791,7 +1792,7 @@ noredhdropt: /* send the packet to outside... */ ip6_output(m, NULL, NULL, 0, NULL, NULL); - icmp6stat.icp6s_outhist[ND_REDIRECT]++; + icmp6stat_inc(icp6s_outhist + ND_REDIRECT); if_put(ifp); return; @@ -1987,6 +1988,22 @@ icmp6_redirect_timeout(struct rtentry *r int *icmpv6ctl_vars[ICMPV6CTL_MAXID] = ICMPV6CTL_VARS; int +icmp6_sysctl_icmp6stat(void *oldp, size_t *oldlenp, void *newp) +{ + struct icmp6stat *icmp6stat; + int ret; + + CTASSERT(sizeof(*icmp6stat) == icp6s_ncounters * sizeof(uint64_t)); + icmp6stat = malloc(sizeof(*icmp6stat), M_TEMP, M_WAITOK); + counters_read(icmp6counters, (uint64_t *)icmp6stat, icp6s_ncounters); + ret = sysctl_rdstruct(oldp, oldlenp, newp, + icmp6stat, sizeof(*icmp6stat)); + free(icmp6stat, M_TEMP, sizeof(*icmp6stat)); + + return (ret); +} + +int icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { @@ -1997,8 +2014,7 @@ icmp6_sysctl(int *name, u_int namelen, v switch (name[0]) { case ICMPV6CTL_STATS: - return sysctl_rdstruct(oldp, oldlenp, newp, - &icmp6stat, sizeof(icmp6stat)); + return icmp6_sysctl_icmp6stat(oldp, oldlenp, newp); case ICMPV6CTL_ND6_DRLIST: case ICMPV6CTL_ND6_PRLIST: return nd6_sysctl(name[0], oldp, oldlenp, newp, newlen); Index: netinet6/in6_var.h =================================================================== RCS file: /d/cvs/src/sys/netinet6/in6_var.h,v retrieving revision 1.64 diff -u -p -r1.64 in6_var.h --- netinet6/in6_var.h 5 Jul 2016 10:17:14 -0000 1.64 +++ netinet6/in6_var.h 6 Feb 2017 07:10:21 -0000 @@ -334,7 +334,6 @@ struct in6_aliasreq { TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr); extern struct in6_ifaddrhead in6_ifaddr; -extern struct icmp6stat icmp6stat; /* * Multi-cast membership entry. One for each group/ifp that a PCB Index: netinet6/mld6.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/mld6.c,v retrieving revision 1.49 diff -u -p -r1.49 mld6.c --- netinet6/mld6.c 21 Dec 2016 12:12:13 -0000 1.49 +++ netinet6/mld6.c 6 Feb 2017 07:10:21 -0000 @@ -165,7 +165,7 @@ mld6_input(struct mbuf *m, int off) IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh)); if (mldh == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return; } @@ -454,7 +454,7 @@ mld6_sendpkt(struct in6_multi *in6m, int im6o.im6o_loop = (ip6_mrouter != NULL); #endif - icmp6stat.icp6s_outhist[type]++; + icmp6stat_inc(icp6s_outhist + type); ip6_output(mh, &ip6_opts, NULL, ia6 ? 0 : IPV6_UNSPECSRC, &im6o, NULL); } Index: netinet6/nd6.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/nd6.c,v retrieving revision 1.202 diff -u -p -r1.202 nd6.c --- netinet6/nd6.c 27 Dec 2016 18:45:01 -0000 1.202 +++ netinet6/nd6.c 6 Feb 2017 07:10:21 -0000 @@ -249,7 +249,7 @@ nd6_options(union nd_opts *ndopts) * Message validation requires that all included * options have a length that is greater than zero. */ - icmp6stat.icp6s_nd_badopt++; + icmp6stat_inc(icp6s_nd_badopt); bzero(ndopts, sizeof(*ndopts)); return -1; } @@ -293,7 +293,7 @@ nd6_options(union nd_opts *ndopts) skip1: i++; if (i > nd6_maxndopt) { - icmp6stat.icp6s_nd_toomanyopt++; + icmp6stat_inc(icp6s_nd_toomanyopt); nd6log((LOG_INFO, "too many loop in nd opt\n")); break; } Index: netinet6/nd6_nbr.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/nd6_nbr.c,v retrieving revision 1.114 diff -u -p -r1.114 nd6_nbr.c --- netinet6/nd6_nbr.c 3 Jan 2017 13:32:51 -0000 1.114 +++ netinet6/nd6_nbr.c 6 Feb 2017 07:10:21 -0000 @@ -118,7 +118,7 @@ nd6_ns_input(struct mbuf *m, int off, in IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len); if (nd_ns == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } @@ -339,7 +339,7 @@ nd6_ns_input(struct mbuf *m, int off, in inet_ntop(AF_INET6, &daddr6, addr, sizeof(addr)))); nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n", inet_ntop(AF_INET6, &taddr6, addr, sizeof(addr)))); - icmp6stat.icp6s_badns++; + icmp6stat_inc(icp6s_badns); m_freem(m); if_put(ifp); } @@ -532,7 +532,7 @@ nd6_ns_output(struct ifnet *ifp, struct m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; ip6_output(m, NULL, NULL, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL); - icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++; + icmp6stat_inc(icp6s_outhist + ND_NEIGHBOR_SOLICIT); return; bad: @@ -589,7 +589,7 @@ nd6_na_input(struct mbuf *m, int off, in IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len); if (nd_na == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } @@ -875,7 +875,7 @@ nd6_na_input(struct mbuf *m, int off, in return; bad: - icmp6stat.icp6s_badna++; + icmp6stat_inc(icp6s_badna); m_freem(m); if_put(ifp); } @@ -1037,7 +1037,7 @@ nd6_na_output(struct ifnet *ifp, struct m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT; ip6_output(m, NULL, NULL, 0, &im6o, NULL); - icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++; + icmp6stat_inc(icp6s_outhist+ ND_NEIGHBOR_ADVERT); return; bad: Index: netinet6/nd6_rtr.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/nd6_rtr.c,v retrieving revision 1.154 diff -u -p -r1.154 nd6_rtr.c --- netinet6/nd6_rtr.c 22 Dec 2016 13:39:32 -0000 1.154 +++ netinet6/nd6_rtr.c 6 Feb 2017 07:10:21 -0000 @@ -150,7 +150,7 @@ nd6_rs_input(struct mbuf *m, int off, in IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len); if (nd_rs == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); return; } @@ -190,7 +190,7 @@ nd6_rs_input(struct mbuf *m, int off, in return; bad: - icmp6stat.icp6s_badrs++; + icmp6stat_inc(icp6s_badrs); m_freem(m); } @@ -276,7 +276,7 @@ nd6_rs_output(struct ifnet* ifp, struct ip6_output(m, NULL, NULL, 0, &im6o, NULL); - icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]++; + icmp6stat_inc(icp6s_outhist + ND_ROUTER_SOLICIT); } void @@ -412,7 +412,7 @@ nd6_ra_input(struct mbuf *m, int off, in IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len); if (nd_ra == NULL) { - icmp6stat.icp6s_tooshort++; + icmp6stat_inc(icp6s_tooshort); if_put(ifp); return; } @@ -570,7 +570,7 @@ nd6_ra_input(struct mbuf *m, int off, in return; bad: - icmp6stat.icp6s_badra++; + icmp6stat_inc(icp6s_badra); if_put(ifp); m_freem(m); } Index: netinet6/raw_ip6.c =================================================================== RCS file: /d/cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.105 diff -u -p -r1.105 raw_ip6.c --- netinet6/raw_ip6.c 5 Feb 2017 16:04:14 -0000 1.105 +++ netinet6/raw_ip6.c 6 Feb 2017 07:14:10 -0000 @@ -103,7 +103,7 @@ struct inpcbtable rawin6pcbtable; -struct rip6stat rip6stat; +struct cpumem *rip6counters; /* * Initialize raw connection block queue. @@ -111,8 +111,8 @@ struct rip6stat rip6stat; void rip6_init(void) { - in_pcbinit(&rawin6pcbtable, 1); + rip6counters = counters_alloc(rip6s_ncounters); } int @@ -125,7 +125,7 @@ rip6_input(struct mbuf **mp, int *offp, struct sockaddr_in6 rip6src; struct mbuf *opts = NULL; - rip6stat.rip6s_ipackets++; + rip6stat_inc(rip6s_ipackets); /* Be proactive about malicious use of IPv4 mapped address */ if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || @@ -171,10 +171,10 @@ rip6_input(struct mbuf **mp, int *offp, !IN6_ARE_ADDR_EQUAL(&in6p->inp_faddr6, &ip6->ip6_src)) continue; if (in6p->inp_cksum6 != -1) { - rip6stat.rip6s_isum++; + rip6stat_inc(rip6s_isum); if (in6_cksum(m, proto, *offp, m->m_pkthdr.len - *offp)) { - rip6stat.rip6s_badsum++; + rip6stat_inc(rip6s_badsum); continue; } } @@ -190,7 +190,7 @@ rip6_input(struct mbuf **mp, int *offp, /* should notify about lost packet */ m_freem(n); m_freem(opts); - rip6stat.rip6s_fullsock++; + rip6stat_inc(rip6s_fullsock); } else sorwakeup(last->inp_socket); opts = NULL; @@ -207,16 +207,16 @@ rip6_input(struct mbuf **mp, int *offp, sin6tosa(&rip6src), m, opts) == 0) { m_freem(m); m_freem(opts); - rip6stat.rip6s_fullsock++; + rip6stat_inc(rip6s_fullsock); } else sorwakeup(last->inp_socket); } else { struct counters_ref ref; uint64_t *counters; - rip6stat.rip6s_nosock++; + rip6stat_inc(rip6s_nosock); if (m->m_flags & M_MCAST) - rip6stat.rip6s_nosockmcast++; + rip6stat_inc(rip6s_nosockmcast); if (proto == IPPROTO_NONE) m_freem(m); else { @@ -457,9 +457,9 @@ rip6_output(struct mbuf *m, ...) error = ip6_output(m, optp, &in6p->inp_route6, flags, in6p->inp_moptions6, in6p); if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { - icmp6stat.icp6s_outhist[type]++; + icmp6stat_inc(icp6s_outhist + type); } else - rip6stat.rip6s_opackets++; + rip6stat_inc(rip6s_opackets); goto freectl; @@ -769,6 +769,18 @@ rip6_usrreq(struct socket *so, int req, } int +rip6_sysctl_rip6stat(void *oldp, size_t *oldplen, void *newp) +{ + struct rip6stat rip6stat; + + CTASSERT(sizeof(rip6stat) == rip6s_ncounters * sizeof(uint64_t)); + counters_read(ip6counters, (uint64_t *)&rip6stat, rip6s_ncounters); + + return (sysctl_rdstruct(oldp, oldplen, newp, + &rip6stat, sizeof(rip6stat))); +} + +int rip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) { @@ -778,10 +790,7 @@ rip6_sysctl(int *name, u_int namelen, vo switch (name[0]) { case RIPV6CTL_STATS: - if (newp != NULL) - return (EPERM); - return (sysctl_struct(oldp, oldlenp, newp, newlen, - &rip6stat, sizeof(rip6stat))); + return (rip6_sysctl_rip6stat(oldp, oldlenp, newp)); default: return (EOPNOTSUPP); } Index: netinet6/raw_ip6.h =================================================================== RCS file: /d/cvs/src/sys/netinet6/raw_ip6.h,v retrieving revision 1.3 diff -u -p -r1.3 raw_ip6.h --- netinet6/raw_ip6.h 14 Dec 2007 18:33:42 -0000 1.3 +++ netinet6/raw_ip6.h 6 Feb 2017 07:10:21 -0000 @@ -59,7 +59,28 @@ struct rip6stat { } #ifdef _KERNEL -extern struct rip6stat rip6stat; + +#include <sys/percpu.h> + +enum rip6stat_counters { + rip6s_ipackets, + rip6s_isum, + rip6s_badsum, + rip6s_nosock, + rip6s_nosockmcast, + rip6s_fullsock, + rip6s_opackets, + rip6s_ncounters, +}; + +extern struct cpumem *rip6counters; + +static inline void +rip6stat_inc(enum rip6stat_counters c) +{ + counters_inc(rip6counters, c); +} + #endif #endif -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE