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