summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Courreges-Anglas <jca@cvs.openbsd.org>2017-02-05 16:04:15 +0000
committerJeremie Courreges-Anglas <jca@cvs.openbsd.org>2017-02-05 16:04:15 +0000
commita0fe76973a89628bbcd7a93577076e67e111a4a4 (patch)
tree627e4d024b0b67aff06231ec1d2f58ae6f4b8a80
parentdaf9ee77f00685cfb1100181f3ecec6af00c6ee1 (diff)
Use percpu counters for ip6stat
Try to follow the existing examples. Some notes: - don't implement counters_dec() yet, which could be used in two similar chunks of code. Let's see if there are more users first. - stop incrementing IPv6-specific mbuf stats, IPv4 has no equivalent. Input from mpi@, ok bluhm@ mpi@
-rw-r--r--sys/net/if_bridge.c6
-rw-r--r--sys/net/pf.c4
-rw-r--r--sys/netinet/ipsec_input.c6
-rw-r--r--sys/netinet6/dest6.c4
-rw-r--r--sys/netinet6/frag6.c18
-rw-r--r--sys/netinet6/icmp6.c9
-rw-r--r--sys/netinet6/in6.c14
-rw-r--r--sys/netinet6/ip6_forward.c16
-rw-r--r--sys/netinet6/ip6_input.c118
-rw-r--r--sys/netinet6/ip6_mroute.c4
-rw-r--r--sys/netinet6/ip6_output.c18
-rw-r--r--sys/netinet6/ip6_var.h62
-rw-r--r--sys/netinet6/raw_ip6.c9
-rw-r--r--sys/netinet6/route6.c6
14 files changed, 180 insertions, 114 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 43c8e5e478c..4e27e3f249f 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.293 2017/01/24 10:08:30 krw Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.294 2017/02/05 16:04:14 jca Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -1692,7 +1692,7 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
if (m->m_len < sizeof(struct ip6_hdr)) {
if ((m = m_pullup(m, sizeof(struct ip6_hdr)))
== NULL) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
return (NULL);
}
}
@@ -1700,7 +1700,7 @@ bridge_ip(struct bridge_softc *sc, int dir, struct ifnet *ifp,
ip6 = mtod(m, struct ip6_hdr *);
if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
- ip6stat.ip6s_badvers++;
+ ip6stat_inc(ip6s_badvers);
goto dropit;
}
diff --git a/sys/net/pf.c b/sys/net/pf.c
index 3895dd18d4d..b4e598716e9 100644
--- a/sys/net/pf.c
+++ b/sys/net/pf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf.c,v 1.1013 2017/01/30 17:52:24 benno Exp $ */
+/* $OpenBSD: pf.c,v 1.1014 2017/02/05 16:04:14 jca Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -5974,7 +5974,7 @@ pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s)
rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
if (!rtisvalid(rt)) {
- ip6stat.ip6s_noroute++;
+ ip6stat_inc(ip6s_noroute);
goto bad;
}
diff --git a/sys/netinet/ipsec_input.c b/sys/netinet/ipsec_input.c
index c5952707aaa..188b21885ca 100644
--- a/sys/netinet/ipsec_input.c
+++ b/sys/netinet/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsec_input.c,v 1.141 2017/01/29 19:58:47 bluhm Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.142 2017/02/05 16:04:14 jca Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -985,7 +985,7 @@ ah6_input_cb(struct mbuf *m, int off, int protoff)
*/
while (nxt != IPPROTO_DONE) {
if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
- ip6stat.ip6s_toomanyhdr++;
+ ip6stat_inc(ip6s_toomanyhdr);
goto bad;
}
@@ -994,7 +994,7 @@ ah6_input_cb(struct mbuf *m, int off, int protoff)
* more sanity checks in header chain processing.
*/
if (m->m_pkthdr.len < off) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
goto bad;
}
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
diff --git a/sys/netinet6/dest6.c b/sys/netinet6/dest6.c
index f00e12e4352..05f0cc5edc7 100644
--- a/sys/netinet6/dest6.c
+++ b/sys/netinet6/dest6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dest6.c,v 1.15 2015/03/14 03:38:52 jsg Exp $ */
+/* $OpenBSD: dest6.c,v 1.16 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: dest6.c,v 1.25 2001/02/22 01:39:16 itojun Exp $ */
/*
@@ -73,7 +73,7 @@ dest6_input(struct mbuf **mp, int *offp, int proto)
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
if (*opt != IP6OPT_PAD1 &&
(dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
goto bad;
}
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index a8cff587aeb..395051928f8 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frag6.c,v 1.71 2016/11/28 11:12:45 mpi Exp $ */
+/* $OpenBSD: frag6.c,v 1.72 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: frag6.c,v 1.40 2002/05/27 21:40:31 itojun Exp $ */
/*
@@ -190,7 +190,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
return IPPROTO_DONE;
}
- ip6stat.ip6s_fragments++;
+ ip6stat_inc(ip6s_fragments);
/* offset now points to data portion */
offset += sizeof(struct ip6_frag);
@@ -203,7 +203,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
*/
fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
if (fragoff == 0 && !(ip6f->ip6f_offlg & IP6F_MORE_FRAG)) {
- ip6stat.ip6s_reassembled++;
+ ip6stat_inc(ip6s_reassembled);
*offp = offset;
return ip6f->ip6f_nxt;
}
@@ -496,7 +496,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
m->m_pkthdr.len = plen;
}
- ip6stat.ip6s_reassembled++;
+ ip6stat_inc(ip6s_reassembled);
/*
* Tell launch routine the next header
@@ -514,14 +514,14 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
m_freem(IP6_REASS_MBUF(af6));
free(af6, M_FTABLE, sizeof(*af6));
}
- ip6stat.ip6s_fragdropped += q6->ip6q_nfrag;
+ ip6stat_add(ip6s_fragdropped, q6->ip6q_nfrag);
TAILQ_REMOVE(&frag6_queue, q6, ip6q_queue);
frag6_nfrags -= q6->ip6q_nfrag;
free(q6, M_FTABLE, sizeof(*q6));
frag6_nfragpackets--;
dropfrag:
- ip6stat.ip6s_fragdropped++;
+ ip6stat_inc(ip6s_fragdropped);
m_freem(m);
IP6Q_UNLOCK();
return IPPROTO_DONE;
@@ -608,7 +608,7 @@ frag6_slowtimo(void)
IP6Q_LOCK();
TAILQ_FOREACH_SAFE(q6, &frag6_queue, ip6q_queue, nq6)
if (--q6->ip6q_ttl == 0) {
- ip6stat.ip6s_fragtimeout++;
+ ip6stat_inc(ip6s_fragtimeout);
frag6_freef(q6);
}
@@ -619,7 +619,7 @@ frag6_slowtimo(void)
*/
while (frag6_nfragpackets > (u_int)ip6_maxfragpackets &&
!TAILQ_EMPTY(&frag6_queue)) {
- ip6stat.ip6s_fragoverflow++;
+ ip6stat_inc(ip6s_fragoverflow);
frag6_freef(TAILQ_LAST(&frag6_queue, ip6q_head));
}
IP6Q_UNLOCK();
@@ -636,7 +636,7 @@ frag6_drain(void)
if (ip6q_lock_try() == 0)
return;
while ((q6 = TAILQ_FIRST(&frag6_queue)) != NULL) {
- ip6stat.ip6s_fragdropped++;
+ ip6stat_inc(ip6s_fragdropped);
frag6_freef(q6);
}
IP6Q_UNLOCK();
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 5041109341c..d2e46d7c05d 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: icmp6.c,v 1.198 2017/02/01 20:59:47 dhill Exp $ */
+/* $OpenBSD: icmp6.c,v 1.199 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
/*
@@ -1124,8 +1124,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
} else
sorwakeup(last->inp_socket);
} else {
+ struct counters_ref ref;
+ uint64_t *counters;
+
m_freem(m);
- ip6stat.ip6s_delivered--;
+ counters = counters_enter(&ref, ip6counters);
+ counters[ip6s_delivered]--;
+ counters_leave(&ref, ip6counters);
}
return IPPROTO_DONE;
}
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 97fdcbb500c..d67a1844d84 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6.c,v 1.196 2016/12/21 12:11:12 mpi Exp $ */
+/* $OpenBSD: in6.c,v 1.197 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: in6.c,v 1.372 2004/06/14 08:14:21 itojun Exp $ */
/*
@@ -1839,20 +1839,20 @@ in6_ifawithscope(struct ifnet *oifp, struct in6_addr *dst, u_int rdomain)
/* count statistics for future improvements */
if (ia6_best == NULL)
- ip6stat.ip6s_sources_none++;
+ ip6stat_inc(ip6s_sources_none);
else {
if (oifp == ia6_best->ia_ifp)
- ip6stat.ip6s_sources_sameif[best_scope]++;
+ ip6stat_inc(ip6s_sources_sameif + best_scope);
else
- ip6stat.ip6s_sources_otherif[best_scope]++;
+ ip6stat_inc(ip6s_sources_otherif + best_scope);
if (best_scope == dst_scope)
- ip6stat.ip6s_sources_samescope[best_scope]++;
+ ip6stat_inc(ip6s_sources_samescope + best_scope);
else
- ip6stat.ip6s_sources_otherscope[best_scope]++;
+ ip6stat_inc(ip6s_sources_otherscope + best_scope);
if ((ia6_best->ia6_flags & IN6_IFF_DEPRECATED) != 0)
- ip6stat.ip6s_sources_deprecated[best_scope]++;
+ ip6stat_inc(ip6s_sources_deprecated + best_scope);
}
return (ia6_best);
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index 9d9bfdccc97..81e2a80124d 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_forward.c,v 1.93 2016/10/03 12:33:21 mpi Exp $ */
+/* $OpenBSD: ip6_forward.c,v 1.94 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
@@ -103,7 +103,7 @@ ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt)
if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
if (ip6_log_time + ip6_log_interval < time_uptime) {
ip6_log_time = time_uptime;
inet_ntop(AF_INET6, &ip6->ip6_src, src6, sizeof(src6));
@@ -171,7 +171,7 @@ reroute:
rt = rtalloc_mpath(sin6tosa(dst), &ip6->ip6_src.s6_addr32[0],
m->m_pkthdr.ph_rtableid);
if (rt == NULL) {
- ip6stat.ip6s_noroute++;
+ ip6stat_inc(ip6s_noroute);
if (mcopy) {
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
@@ -190,8 +190,8 @@ reroute:
*/
if (in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &ip6->ip6_src) !=
in6_addr2scopeid(rt->rt_ifidx, &ip6->ip6_src)) {
- ip6stat.ip6s_cantforward++;
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_cantforward);
+ ip6stat_inc(ip6s_badscope);
if (ip6_log_time + ip6_log_interval < time_uptime) {
ip6_log_time = time_uptime;
@@ -316,11 +316,11 @@ reroute:
error = ifp->if_output(ifp, m, sin6tosa(dst), rt);
if (error) {
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
} else {
- ip6stat.ip6s_forward++;
+ ip6stat_inc(ip6s_forward);
if (type)
- ip6stat.ip6s_redirectsent++;
+ ip6stat_inc(ip6s_redirectsent);
else {
if (mcopy)
goto freecopy;
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 5e7949f1065..f1f902107e5 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_input.c,v 1.175 2017/01/29 19:58:47 bluhm Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.176 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@@ -117,7 +117,7 @@
struct in6_ifaddrhead in6_ifaddr;
struct niqueue ip6intrq = NIQUEUE_INITIALIZER(IFQ_MAXLEN, NETISR_IPV6);
-struct ip6stat ip6stat;
+struct cpumem *ip6counters;
int ip6_check_rh0hdr(struct mbuf *, int *);
@@ -158,6 +158,8 @@ ip6_init(void)
frag6_init();
mq_init(&ip6send_mq, 64, IPL_SOFTNET);
+
+ ip6counters = counters_alloc(ip6s_ncounters, M_COUNTERS);
}
/*
@@ -191,29 +193,11 @@ ip6_input(struct mbuf *m)
if (ifp == NULL)
goto bad;
- if (m->m_flags & M_EXT) {
- if (m->m_next)
- ip6stat.ip6s_mext2m++;
- else
- ip6stat.ip6s_mext1++;
- } else {
- if (m->m_next) {
- int ifidx = m->m_pkthdr.ph_ifidx;
- if (m->m_flags & M_LOOP)
- ifidx = rtable_loindex(m->m_pkthdr.ph_rtableid);
- if (ifidx < nitems(ip6stat.ip6s_m2m))
- ip6stat.ip6s_m2m[ifidx]++;
- else
- ip6stat.ip6s_m2m[0]++;
- } else
- ip6stat.ip6s_m1++;
- }
-
- ip6stat.ip6s_total++;
+ ip6stat_inc(ip6s_total);
if (m->m_len < sizeof(struct ip6_hdr)) {
if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
if_put(ifp);
return;
}
@@ -222,7 +206,7 @@ ip6_input(struct mbuf *m)
ip6 = mtod(m, struct ip6_hdr *);
if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
- ip6stat.ip6s_badvers++;
+ ip6stat_inc(ip6s_badvers);
goto bad;
}
@@ -232,7 +216,7 @@ ip6_input(struct mbuf *m)
ip6->ip6_dst.s6_addr32))
goto bad;
#endif
- ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
+ ip6stat_inc(ip6s_nxthist + ip6->ip6_nxt);
/*
* Check against address spoofing/corruption.
@@ -242,20 +226,20 @@ ip6_input(struct mbuf *m)
/*
* XXX: "badscope" is not very suitable for a multicast source.
*/
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
(ifp->if_flags & IFF_LOOPBACK) == 0) {
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
/* Drop packets if interface ID portion is already filled. */
if (((IN6_IS_SCOPE_EMBED(&ip6->ip6_src) && ip6->ip6_src.s6_addr16[1]) ||
(IN6_IS_SCOPE_EMBED(&ip6->ip6_dst) && ip6->ip6_dst.s6_addr16[1])) &&
(ifp->if_flags & IFF_LOOPBACK) == 0) {
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
@@ -266,7 +250,7 @@ ip6_input(struct mbuf *m)
* because ip6_mloopback() passes the "actual" interface
* as the outgoing/incoming interface.
*/
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
@@ -284,7 +268,7 @@ ip6_input(struct mbuf *m)
*/
if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
@@ -295,7 +279,7 @@ ip6_input(struct mbuf *m)
*/
if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
@@ -351,7 +335,7 @@ ip6_input(struct mbuf *m)
*/
if (!(m->m_pkthdr.pf.flags & PF_TAG_PROCESSED) &&
ip6_check_rh0hdr(m, &off)) {
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, off);
/* m is already freed */
if_put(ifp);
@@ -408,7 +392,7 @@ ip6_input(struct mbuf *m)
* must be discarded, else it may be accepted below.
*/
if (ip6_mforward(ip6, ifp, m)) {
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
goto bad;
}
@@ -418,9 +402,9 @@ ip6_input(struct mbuf *m)
}
#endif
if (!ours) {
- ip6stat.ip6s_notmember++;
+ ip6stat_inc(ip6s_notmember);
if (!IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst))
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
goto bad;
}
goto hbhcheck;
@@ -478,7 +462,7 @@ ip6_input(struct mbuf *m)
* and we're not a router.
*/
if (!ip6_forwarding) {
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
goto bad;
}
@@ -512,12 +496,12 @@ ip6_input(struct mbuf *m)
/*
* Tell launch routine the next header
*/
- ip6stat.ip6s_delivered++;
+ ip6stat_inc(ip6s_delivered);
nest = 0;
while (nxt != IPPROTO_DONE) {
if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
- ip6stat.ip6s_toomanyhdr++;
+ ip6stat_inc(ip6s_toomanyhdr);
goto bad;
}
@@ -526,7 +510,7 @@ ip6_input(struct mbuf *m)
* more sanity checks in header chain processing.
*/
if (m->m_pkthdr.len < off) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
goto bad;
}
@@ -588,7 +572,7 @@ ip6_hbhchcheck(struct mbuf *m, int *offp, int *nxtp, int *oursp)
* contained, ip6_hopopts_input() must set a valid
* (non-zero) payload length to the variable plen.
*/
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
(caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
@@ -597,7 +581,7 @@ ip6_hbhchcheck(struct mbuf *m, int *offp, int *nxtp, int *oursp)
IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
sizeof(struct ip6_hbh));
if (hbh == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return (-1);
}
*nxtp = hbh->ip6h_nxt;
@@ -618,7 +602,7 @@ ip6_hbhchcheck(struct mbuf *m, int *offp, int *nxtp, int *oursp)
* Drop packet if shorter than we expect.
*/
if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
m_freem(m);
return (-1);
}
@@ -721,14 +705,14 @@ ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, struct mbuf **mp,
IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
if (hbh == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return -1;
}
hbhlen = (hbh->ip6h_len + 1) << 3;
IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
hbhlen);
if (hbh == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return -1;
}
off += hbhlen;
@@ -771,7 +755,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
break;
case IP6OPT_PADN:
if (hbhlen < IP6OPT_MINLEN) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
goto bad;
}
optlen = *(opt + 1) + 2;
@@ -779,7 +763,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
case IP6OPT_ROUTER_ALERT:
/* XXX may need check for alignment */
if (hbhlen < IP6OPT_RTALERT_LEN) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
goto bad;
}
if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
@@ -796,7 +780,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
case IP6OPT_JUMBO:
/* XXX may need check for alignment */
if (hbhlen < IP6OPT_JUMBO_LEN) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
goto bad;
}
if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
@@ -814,7 +798,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
*/
ip6 = mtod(m, struct ip6_hdr *);
if (ip6->ip6_plen) {
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
erroff + opt - opthead);
@@ -838,7 +822,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
* there's no explicit mention in specification.
*/
if (*plenp != 0) {
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
erroff + opt + 2 - opthead);
@@ -850,7 +834,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
* jumbo payload length must be larger than 65535.
*/
if (jumboplen <= IPV6_MAXPACKET) {
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
erroff + opt + 2 - opthead);
@@ -861,7 +845,7 @@ ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
break;
default: /* unknown option */
if (hbhlen < IP6OPT_MINLEN) {
- ip6stat.ip6s_toosmall++;
+ ip6stat_inc(ip6s_toosmall);
goto bad;
}
optlen = ip6_unknown_opt(opt, m,
@@ -898,11 +882,11 @@ ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off)
m_freem(m);
return (-1);
case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
return (-1);
case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
ip6 = mtod(m, struct ip6_hdr *);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
(m->m_flags & (M_BCAST|M_MCAST)))
@@ -1005,14 +989,14 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
ip6->ip6_nxt);
if (ext == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return;
}
hbh = mtod(ext, struct ip6_hbh *);
hbhlen = (hbh->ip6h_len + 1) << 3;
if (hbhlen != ext->m_len) {
m_freem(ext);
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return;
}
@@ -1065,7 +1049,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
ext = ip6_pullexthdr(m, off, nxt);
if (ext == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return;
}
ip6e = mtod(ext, struct ip6_ext *);
@@ -1075,7 +1059,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
elen = (ip6e->ip6e_len + 1) << 3;
if (elen != ext->m_len) {
m_freem(ext);
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return;
}
@@ -1350,6 +1334,23 @@ u_char inet6ctlerrmap[PRC_NCMDS] = {
int *ipv6ctl_vars[IPV6CTL_MAXID] = IPV6CTL_VARS;
int
+ip6_sysctl_ip6stat(void *oldp, size_t *oldlenp, void *newp)
+{
+ struct ip6stat *ip6stat;
+ int ret;
+
+ CTASSERT(sizeof(*ip6stat) == (ip6s_ncounters * sizeof(uint64_t)));
+
+ ip6stat = malloc(sizeof(*ip6stat), M_TEMP, M_WAITOK);
+ counters_read(ip6counters, (uint64_t *)ip6stat, ip6s_ncounters);
+ ret = sysctl_rdstruct(oldp, oldlenp, newp,
+ ip6stat, sizeof(*ip6stat));
+ free(ip6stat, M_TEMP, sizeof(*ip6stat));
+
+ return (ret);
+}
+
+int
ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
{
@@ -1369,10 +1370,7 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
case IPV6CTL_DAD_PENDING:
return sysctl_rdint(oldp, oldlenp, newp, ip6_dad_pending);
case IPV6CTL_STATS:
- if (newp != NULL)
- return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &ip6stat, sizeof(ip6stat)));
+ return (ip6_sysctl_ip6stat(oldp, oldlenp, newp));
#ifdef MROUTING
case IPV6CTL_MRTSTATS:
if (newp != NULL)
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index 0abe20f8094..f767c07e198 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -873,7 +873,7 @@ ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
* (although such packets must normally set 1 to the hop limit field).
*/
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
- ip6stat.ip6s_cantforward++;
+ ip6stat_inc(ip6s_cantforward);
if (ip6_log_time + ip6_log_interval < time_uptime) {
char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
@@ -1158,7 +1158,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *ifp, struct mf6c *rt)
in6_addr2scopeid(ifp->if_index, &ip6->ip6_src) !=
in6_addr2scopeid(mif6table[mifi].m6_ifp->if_index,
&ip6->ip6_src))) {
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
continue;
}
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 9d35a8a4c5d..3a11852780f 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_output.c,v 1.223 2017/02/01 20:59:47 dhill Exp $ */
+/* $OpenBSD: ip6_output.c,v 1.224 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@@ -361,16 +361,16 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro,
* we explicitly check the address here for safety.
*/
error = EOPNOTSUPP;
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
error = EOPNOTSUPP;
- ip6stat.ip6s_badscope++;
+ ip6stat_inc(ip6s_badscope);
goto bad;
}
- ip6stat.ip6s_localout++;
+ ip6stat_inc(ip6s_localout);
/*
* Route packet.
@@ -455,7 +455,7 @@ reroute:
if (ifp == NULL) {
rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
if (rt == NULL) {
- ip6stat.ip6s_noroute++;
+ ip6stat_inc(ip6s_noroute);
error = EHOSTUNREACH;
goto bad;
}
@@ -484,7 +484,7 @@ reroute:
* Confirm that the outgoing interface supports multicast.
*/
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
- ip6stat.ip6s_noroute++;
+ ip6stat_inc(ip6s_noroute);
error = ENETUNREACH;
goto bad;
}
@@ -738,7 +738,7 @@ reroute:
m0 = m;
error = ip6_fragment(m0, hlen, nextproto, mtu);
if (error)
- ip6stat.ip6s_odropped++;
+ ip6stat_inc(ip6s_odropped);
}
/*
@@ -751,7 +751,7 @@ reroute:
m0 = m->m_nextpkt;
m->m_nextpkt = 0;
if (error == 0) {
- ip6stat.ip6s_ofragments++;
+ ip6stat_inc(ip6s_ofragments);
error = ifp->if_output(ifp, m, sin6tosa(dst),
ro->ro_rt);
} else
@@ -759,7 +759,7 @@ reroute:
}
if (error == 0)
- ip6stat.ip6s_fragmented++;
+ ip6stat_inc(ip6s_fragmented);
done:
if_put(ifp);
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 11ff0524bd3..24af0456d50 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_var.h,v 1.66 2017/02/01 20:59:47 dhill Exp $ */
+/* $OpenBSD: ip6_var.h,v 1.67 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
@@ -203,6 +203,65 @@ struct ip6stat {
};
#ifdef _KERNEL
+
+#include <sys/percpu.h>
+
+enum ip6stat_counters {
+ ip6s_total,
+ ip6s_tooshort,
+ ip6s_toosmall,
+ ip6s_fragments,
+ ip6s_fragdropped,
+ ip6s_fragtimeout,
+ ip6s_fragoverflow,
+ ip6s_forward,
+ ip6s_cantforward,
+ ip6s_redirectsent,
+ ip6s_delivered,
+ ip6s_localout,
+ ip6s_odropped,
+ ip6s_reassembled,
+ ip6s_fragmented,
+ ip6s_ofragments,
+ ip6s_cantfrag,
+ ip6s_badoptions,
+ ip6s_noroute,
+ ip6s_badvers,
+ ip6s_rawout,
+ ip6s_badscope,
+ ip6s_notmember,
+ ip6s_nxthist,
+ ip6s_m1 = ip6s_nxthist + 256,
+ ip6s_m2m,
+ ip6s_mext1 = ip6s_m2m + 32,
+ ip6s_mext2m,
+ ip6s_nogif,
+ ip6s_toomanyhdr,
+ ip6s_sources_none,
+ ip6s_sources_sameif,
+ ip6s_sources_otherif = ip6s_sources_sameif + 16,
+ ip6s_sources_samescope = ip6s_sources_otherif + 16,
+ ip6s_sources_otherscope = ip6s_sources_samescope + 16,
+ ip6s_sources_deprecated = ip6s_sources_otherscope + 16,
+ ip6s_forward_cachehit = ip6s_sources_deprecated + 16,
+ ip6s_forward_cachemiss,
+ ip6s_ncounters,
+};
+
+extern struct cpumem *ip6counters;
+
+static inline void
+ip6stat_inc(enum ip6stat_counters c)
+{
+ counters_inc(ip6counters, c);
+}
+
+static inline void
+ip6stat_add(enum ip6stat_counters c, uint64_t v)
+{
+ counters_add(ip6counters, c, v);
+}
+
/* flags passed to ip6_output as last parameter */
#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */
#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */
@@ -211,7 +270,6 @@ struct ip6stat {
extern int ip6_mtudisc_timeout; /* mtu discovery */
extern struct rttimer_queue *icmp6_mtudisc_timeout_q;
-extern struct ip6stat ip6stat; /* statistics */
extern int ip6_defhlim; /* default hop limit */
extern int ip6_defmcasthlim; /* default multicast hop limit */
extern int ip6_forwarding; /* act as router? */
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index c9da7afb9ba..fd1dc59b5a6 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.104 2017/02/01 20:59:47 dhill Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.105 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -211,6 +211,9 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
} else
sorwakeup(last->inp_socket);
} else {
+ struct counters_ref ref;
+ uint64_t *counters;
+
rip6stat.rip6s_nosock++;
if (m->m_flags & M_MCAST)
rip6stat.rip6s_nosockmcast++;
@@ -222,7 +225,9 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
ICMP6_PARAMPROB_NEXTHEADER,
prvnxtp - mtod(m, u_int8_t *));
}
- ip6stat.ip6s_delivered--;
+ counters = counters_enter(&ref, ip6counters);
+ counters[ip6s_delivered]--;
+ counters_leave(&ref, ip6counters);
}
return IPPROTO_DONE;
}
diff --git a/sys/netinet6/route6.c b/sys/netinet6/route6.c
index e64ad25f3fb..357fe45a78d 100644
--- a/sys/netinet6/route6.c
+++ b/sys/netinet6/route6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route6.c,v 1.19 2014/12/05 15:50:04 mpi Exp $ */
+/* $OpenBSD: route6.c,v 1.20 2017/02/05 16:04:14 jca Exp $ */
/* $KAME: route6.c,v 1.22 2000/12/03 00:54:00 itojun Exp $ */
/*
@@ -60,7 +60,7 @@ route6_input(struct mbuf **mp, int *offp, int proto)
ip6 = mtod(m, struct ip6_hdr *);
IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, sizeof(*rh));
if (rh == NULL) {
- ip6stat.ip6s_tooshort++;
+ ip6stat_inc(ip6s_tooshort);
return IPPROTO_DONE;
}
@@ -77,7 +77,7 @@ route6_input(struct mbuf **mp, int *offp, int proto)
rhlen = (rh->ip6r_len + 1) << 3;
break; /* Final dst. Just ignore the header. */
}
- ip6stat.ip6s_badoptions++;
+ ip6stat_inc(ip6s_badoptions);
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
(caddr_t)&rh->ip6r_type - (caddr_t)ip6);
return (IPPROTO_DONE);