summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJeremie Courreges-Anglas <jca@cvs.openbsd.org>2017-02-09 15:23:36 +0000
committerJeremie Courreges-Anglas <jca@cvs.openbsd.org>2017-02-09 15:23:36 +0000
commit93353c70e288507c5e9d747dfbf7efbe3a95d142 (patch)
tree573e583759a7b0c075819c2c7d2a292aaebbf650 /sys
parent56f2e55e49aaf23d0837bf2acec5f2572233f640 (diff)
percpu counters for raw ipv6 and icmp6 stats
ok mpi@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/icmp6.h95
-rw-r--r--sys/netinet6/icmp6.c106
-rw-r--r--sys/netinet6/in6_var.h3
-rw-r--r--sys/netinet6/mld6.c6
-rw-r--r--sys/netinet6/nd6.c6
-rw-r--r--sys/netinet6/nd6_nbr.c14
-rw-r--r--sys/netinet6/nd6_rtr.c12
-rw-r--r--sys/netinet6/raw_ip6.c41
-rw-r--r--sys/netinet6/raw_ip6.h25
9 files changed, 188 insertions, 120 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 17f2c2638e9..5c58798db01 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: icmp6.h,v 1.42 2015/09/09 15:51:40 mpi Exp $ */
+/* $OpenBSD: icmp6.h,v 1.43 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */
/*
@@ -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 */
@@ -591,6 +569,51 @@ struct icmp6stat {
#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;
struct in6_multi;
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index d2e46d7c05d..c77c6584d79 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: icmp6.c,v 1.199 2017/02/05 16:04:14 jca Exp $ */
+/* $OpenBSD: icmp6.c,v 1.200 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
/*
@@ -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_redirect_timeout_q = NULL;
/* 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, int code, int param)
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, int code, int param)
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, int code, int param)
* 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, int code, int param)
/* 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, int code, int param)
*/
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, int proto)
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, int proto)
*/
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, int proto)
"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, int proto)
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, int proto)
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 off, int icmp6len, int code)
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 off, int icmp6len, int code)
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 off, int icmp6len, int code)
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 off, int icmp6len, int code)
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 off, int icmp6len, int code)
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 off, int icmp6len, int code)
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 *ip6cp, int validated)
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 off)
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 off)
bad:
if_put(ifp);
- icmp6stat.icp6s_badredirect++;
+ icmp6stat_inc(icp6s_badredirect);
m_freem(m);
}
@@ -1556,7 +1557,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
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 *rt, struct rttimer *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, void *oldp, size_t *oldlenp,
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);
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index 3dc4d8c0310..c6d6d1ef061 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_var.h,v 1.64 2016/07/05 10:17:14 mpi Exp $ */
+/* $OpenBSD: in6_var.h,v 1.65 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: in6_var.h,v 1.55 2001/02/16 12:49:45 itojun Exp $ */
/*
@@ -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
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 8b84d34c751..63d1d3e46b2 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mld6.c,v 1.49 2016/12/21 12:12:13 mpi Exp $ */
+/* $OpenBSD: mld6.c,v 1.50 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: mld6.c,v 1.26 2001/02/16 14:50:35 itojun Exp $ */
/*
@@ -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 type, const struct in6_addr *dst)
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);
}
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 082e93021a4..30d72dd6dfc 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6.c,v 1.202 2016/12/27 18:45:01 bluhm Exp $ */
+/* $OpenBSD: nd6.c,v 1.203 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */
/*
@@ -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;
}
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index d937598bbca..fef9d7e0a93 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_nbr.c,v 1.114 2017/01/03 13:32:51 bluhm Exp $ */
+/* $OpenBSD: nd6_nbr.c,v 1.115 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@@ -118,7 +118,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
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, int icmp6len)
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 in6_addr *daddr6,
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, int icmp6len)
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, int icmp6len)
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 in6_addr *daddr6,
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:
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 4885c37cdb9..8dd1a2ed0e9 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_rtr.c,v 1.154 2016/12/22 13:39:32 mpi Exp $ */
+/* $OpenBSD: nd6_rtr.c,v 1.155 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */
/*
@@ -150,7 +150,7 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
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, int icmp6len)
return;
bad:
- icmp6stat.icp6s_badrs++;
+ icmp6stat_inc(icp6s_badrs);
m_freem(m);
}
@@ -276,7 +276,7 @@ nd6_rs_output(struct ifnet* ifp, struct in6_ifaddr *ia6)
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, int icmp6len)
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, int icmp6len)
return;
bad:
- icmp6stat.icp6s_badra++;
+ icmp6stat_inc(icp6s_badra);
if_put(ifp);
m_freem(m);
}
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index fd1dc59b5a6..23c46ecb628 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.105 2017/02/05 16:04:14 jca Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.106 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -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, int proto)
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, int proto)
!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, int proto)
/* 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, int proto)
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, struct mbuf *m, struct mbuf *nam,
}
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, void *oldp, size_t *oldlenp,
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);
}
diff --git a/sys/netinet6/raw_ip6.h b/sys/netinet6/raw_ip6.h
index d81b1451b4d..d972e6a14e9 100644
--- a/sys/netinet6/raw_ip6.h
+++ b/sys/netinet6/raw_ip6.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.h,v 1.3 2007/12/14 18:33:42 deraadt Exp $ */
+/* $OpenBSD: raw_ip6.h,v 1.4 2017/02/09 15:23:35 jca Exp $ */
/* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $ */
/*
@@ -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