summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2016-11-18 02:53:48 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2016-11-18 02:53:48 +0000
commit0ae660dcbaff7b8a9bd7b2202bf2e9d1048a0bd5 (patch)
tree660fcb34e09fada55ca30adb0cc39c8a54c93c3e /sys/netinet
parente17cf2d921bb1a57075cc8e40b97e3ac34736c66 (diff)
turn ipstat into a set of percpu counters.
each counter is identified by an enum value which correspond to the original members of the udpstat struct. udpstat_inc(udps_foo) replaces udpstat.udps_foo++ for the actual updates. udpstat_inc is a thin wrapper around counters_inc. counters are still returned to userland via the udpstat struct for now. ok mpi@ mikeb@ deraadt@
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/ip_output.c4
-rw-r--r--sys/netinet/udp_usrreq.c67
-rw-r--r--sys/netinet/udp_var.h33
3 files changed, 78 insertions, 26 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 86ec40e56c7..c28cacabd07 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.329 2016/11/14 10:32:46 mpi Exp $ */
+/* $OpenBSD: ip_output.c,v 1.330 2016/11/18 02:53:47 dlg Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -1811,7 +1811,7 @@ in_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
} else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
ip->ip_hl != 5 || ifp->if_bridgeport != NULL) {
- udpstat.udps_outswcsum++;
+ udpstat_inc(udps_outswcsum);
in_delayed_cksum(m);
m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
}
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 200a6368246..957f01a595f 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.220 2016/11/03 18:42:35 mikeb Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.221 2016/11/18 02:53:47 dlg Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -130,10 +130,11 @@ u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
int *udpctl_vars[UDPCTL_MAXID] = UDPCTL_VARS;
struct inpcbtable udbtable;
-struct udpstat udpstat;
+struct cpumem *udpcounters;
int udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *);
void udp_notify(struct inpcb *, int);
+int udp_sysctl_udpstat(void *, size_t *, void *);
#ifndef UDB_INITIAL_HASH_SIZE
#define UDB_INITIAL_HASH_SIZE 128
@@ -142,6 +143,7 @@ void udp_notify(struct inpcb *, int);
void
udp_init(void)
{
+ udpcounters = counters_alloc(udps_ncounters, M_COUNTERS);
in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE);
}
@@ -189,7 +191,7 @@ udp_input(struct mbuf *m, ...)
iphlen = va_arg(ap, int);
va_end(ap);
- udpstat.udps_ipackets++;
+ udpstat_inc(udps_ipackets);
switch (mtod(m, struct ip *)->ip_v) {
case 4:
@@ -212,13 +214,13 @@ udp_input(struct mbuf *m, ...)
IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
if (!uh) {
- udpstat.udps_hdrops++;
+ udpstat_inc(udps_hdrops);
return;
}
/* Check for illegal destination port 0 */
if (uh->uh_dport == 0) {
- udpstat.udps_noport++;
+ udpstat_inc(udps_noport);
goto bad;
}
@@ -231,7 +233,7 @@ udp_input(struct mbuf *m, ...)
if (m->m_pkthdr.len - iphlen != len) {
if (len > (m->m_pkthdr.len - iphlen) ||
len < sizeof(struct udphdr)) {
- udpstat.udps_badlen++;
+ udpstat_inc(udps_badlen);
goto bad;
}
m_adj(m, len - (m->m_pkthdr.len - iphlen));
@@ -243,7 +245,7 @@ udp_input(struct mbuf *m, ...)
if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)
len = m->m_pkthdr.len - iphlen;
if (len != m->m_pkthdr.len - iphlen) {
- udpstat.udps_badlen++;
+ udpstat_inc(udps_badlen);
goto bad;
}
}
@@ -276,7 +278,7 @@ udp_input(struct mbuf *m, ...)
*/
savesum = uh->uh_sum;
if (uh->uh_sum == 0) {
- udpstat.udps_nosum++;
+ udpstat_inc(udps_nosum);
#ifdef INET6
/*
* In IPv6, the UDP checksum is ALWAYS used.
@@ -287,10 +289,10 @@ udp_input(struct mbuf *m, ...)
} else {
if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) {
if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) {
- udpstat.udps_badsum++;
+ udpstat_inc(udps_badsum);
goto bad;
}
- udpstat.udps_inswcsum++;
+ udpstat_inc(udps_inswcsum);
if (ip)
uh->uh_sum = in4_cksum(m, IPPROTO_UDP,
@@ -301,7 +303,7 @@ udp_input(struct mbuf *m, ...)
iphlen, len);
#endif /* INET6 */
if (uh->uh_sum != 0) {
- udpstat.udps_badsum++;
+ udpstat_inc(udps_badsum);
goto bad;
}
}
@@ -328,7 +330,7 @@ udp_input(struct mbuf *m, ...)
*/
if (spi != 0) {
if ((m = m_pullup(m, skip)) == NULL) {
- udpstat.udps_hdrops++;
+ udpstat_inc(udps_hdrops);
return;
}
@@ -497,7 +499,7 @@ udp_input(struct mbuf *m, ...)
&srcsa.sa, n, opts) == 0) {
m_freem(n);
m_freem(opts);
- udpstat.udps_fullsock++;
+ udpstat_inc(udps_fullsock);
} else
sorwakeup(last->inp_socket);
opts = NULL;
@@ -523,7 +525,7 @@ udp_input(struct mbuf *m, ...)
* (No need to send an ICMP Port Unreachable
* for a broadcast or multicast datgram.)
*/
- udpstat.udps_noportbcast++;
+ udpstat_inc(udps_noportbcast);
goto bad;
}
@@ -539,7 +541,7 @@ udp_input(struct mbuf *m, ...)
m_adj(m, iphlen);
if (sbappendaddr(&last->inp_socket->so_rcv,
&srcsa.sa, m, opts) == 0) {
- udpstat.udps_fullsock++;
+ udpstat_inc(udps_fullsock);
goto bad;
}
sorwakeup(last->inp_socket);
@@ -566,7 +568,7 @@ udp_input(struct mbuf *m, ...)
int inpl_reverse = 0;
if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST)
inpl_reverse = 1;
- ++udpstat.udps_pcbhashmiss;
+ udpstat_inc(udps_pcbhashmiss);
#ifdef INET6
if (ip6) {
inp = in6_pcblookup_listen(&udbtable,
@@ -578,9 +580,9 @@ udp_input(struct mbuf *m, ...)
ip->ip_dst, uh->uh_dport, inpl_reverse, m,
m->m_pkthdr.ph_rtableid);
if (inp == 0) {
- udpstat.udps_noport++;
+ udpstat_inc(udps_noport);
if (m->m_flags & (M_BCAST | M_MCAST)) {
- udpstat.udps_noportbcast++;
+ udpstat_inc(udps_noportbcast);
goto bad;
}
#ifdef INET6
@@ -628,7 +630,7 @@ udp_input(struct mbuf *m, ...)
ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error,
IPSP_DIRECTION_IN, tdb, inp, 0);
if (error) {
- udpstat.udps_nosec++;
+ udpstat_inc(udps_nosec);
goto bad;
}
/* create ipsec options while we know that tdb cannot be modified */
@@ -690,7 +692,7 @@ udp_input(struct mbuf *m, ...)
iphlen += sizeof(struct udphdr);
m_adj(m, iphlen);
if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) {
- udpstat.udps_fullsock++;
+ udpstat_inc(udps_fullsock);
goto bad;
}
sorwakeup(inp->inp_socket);
@@ -1073,7 +1075,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct mbuf *addr,
if (udpcksum)
m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
- udpstat.udps_opackets++;
+ udpstat_inc(udps_opackets);
/* force routing table */
m->m_pkthdr.ph_rtableid = inp->inp_rtableid;
@@ -1341,8 +1343,8 @@ udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
case UDPCTL_STATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &udpstat, sizeof(udpstat)));
+
+ return (udp_sysctl_udpstat(oldp, oldlenp, newp));
default:
if (name[0] < UDPCTL_MAXID)
@@ -1352,3 +1354,22 @@ udp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
}
/* NOTREACHED */
}
+
+int
+udp_sysctl_udpstat(void *oldp, size_t *oldlenp, void *newp)
+{
+ uint64_t counters[udps_ncounters];
+ struct udpstat udpstat;
+ u_long *words = (u_long *)&udpstat;
+ int i;
+
+ KASSERT(sizeof(udpstat) == (nitems(counters) * sizeof(u_long)));
+
+ counters_read(udpcounters, counters, nitems(counters));
+
+ for (i = 0; i < nitems(counters); i++)
+ words[i] = (u_long)counters[i];
+
+ return (sysctl_rdstruct(oldp, oldlenp, newp,
+ &udpstat, sizeof(udpstat)));
+}
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 0473df1bc28..5ebaa0fcbf2 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_var.h,v 1.27 2016/06/18 10:36:13 vgross Exp $ */
+/* $OpenBSD: udp_var.h,v 1.28 2016/11/18 02:53:47 dlg Exp $ */
/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */
/*
@@ -102,6 +102,37 @@ struct udpstat {
}
#ifdef _KERNEL
+
+#include <sys/percpu.h>
+
+enum udpstat_counters {
+ /* input statistics: */
+ udps_ipackets, /* total input packets */
+ udps_hdrops, /* packet shorter than header */
+ udps_badsum, /* checksum error */
+ udps_nosum, /* no checksum */
+ udps_badlen, /* data length larger than packet */
+ udps_noport, /* no socket on port */
+ udps_noportbcast, /* of above, arrived as broadcast */
+ udps_nosec, /* dropped for lack of ipsec */
+ udps_fullsock, /* not delivered, input socket full */
+ udps_pcbhashmiss, /* input packets missing pcb hash */
+ udps_inswcsum, /* input software-csummed packets */
+ /* output statistics: */
+ udps_opackets, /* total output packets */
+ udps_outswcsum, /* output software-csummed packets */
+
+ udps_ncounters
+};
+
+extern struct cpumem *udpcounters;
+
+static inline void
+udpstat_inc(enum udpstat_counters c)
+{
+ counters_inc(udpcounters, c);
+}
+
extern struct inpcbtable udbtable;
extern struct udpstat udpstat;