summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2017-01-04 04:56:24 +0000
committerdlg <dlg@openbsd.org>2017-01-04 04:56:24 +0000
commit4fc2f7f95ff1257b483a6d30e53fd125113e9187 (patch)
treeeb78aafe02384e74586b751979763902307d2ef7
parentdont assume setting IFF_UP will succeed. (diff)
downloadwireguard-openbsd-4fc2f7f95ff1257b483a6d30e53fd125113e9187.tar.xz
wireguard-openbsd-4fc2f7f95ff1257b483a6d30e53fd125113e9187.zip
convert igmp_stat into per-cpu counters
it follows the same pattern used in previous conversions. from Dimitris Papastamos (thank you). ok mpi@
-rw-r--r--sys/netinet/igmp.c56
-rw-r--r--sys/netinet/igmp_var.h26
2 files changed, 62 insertions, 20 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index f1b142c093c..c59d03038c1 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: igmp.c,v 1.59 2016/12/19 09:22:24 rzalamena Exp $ */
+/* $OpenBSD: igmp.c,v 1.60 2017/01/04 04:56:24 dlg Exp $ */
/* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 christos Exp $ */
/*
@@ -101,13 +101,14 @@ int *igmpctl_vars[IGMPCTL_MAXID] = IGMPCTL_VARS;
int igmp_timers_are_running;
static struct router_info *rti_head;
static struct mbuf *router_alert;
-struct igmpstat igmpstat;
+struct cpumem *igmpcounters;
void igmp_checktimer(struct ifnet *);
void igmp_sendpkt(struct ifnet *, struct in_multi *, int, in_addr_t);
int rti_fill(struct in_multi *);
struct router_info * rti_find(struct ifnet *);
void igmp_input_if(struct ifnet *, struct mbuf *, int);
+int igmp_sysctl_igmpstat(void *, size_t *, void *);
void
igmp_init(void)
@@ -117,6 +118,7 @@ igmp_init(void)
igmp_timers_are_running = 0;
rti_head = 0;
+ igmpcounters = counters_alloc(igps_ncounters, M_COUNTERS);
router_alert = m_get(M_DONTWAIT, MT_DATA);
if (router_alert == NULL) {
printf("%s: no mbuf\n", __func__);
@@ -217,7 +219,7 @@ igmp_input(struct mbuf *m, ...)
iphlen = va_arg(ap, int);
va_end(ap);
- ++igmpstat.igps_rcv_total;
+ igmpstat_inc(igps_rcv_total);
ifp = if_get(m->m_pkthdr.ph_ifidx);
if (ifp == NULL) {
@@ -248,14 +250,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
* Validate lengths
*/
if (igmplen < IGMP_MINLEN) {
- ++igmpstat.igps_rcv_tooshort;
+ igmpstat_inc(igps_rcv_tooshort);
m_freem(m);
return;
}
minlen = iphlen + IGMP_MINLEN;
if ((m->m_flags & M_EXT || m->m_len < minlen) &&
(m = m_pullup(m, minlen)) == NULL) {
- ++igmpstat.igps_rcv_tooshort;
+ igmpstat_inc(igps_rcv_tooshort);
return;
}
@@ -266,7 +268,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
m->m_len -= iphlen;
igmp = mtod(m, struct igmp *);
if (in_cksum(m, igmplen)) {
- ++igmpstat.igps_rcv_badsum;
+ igmpstat_inc(igps_rcv_badsum);
m_freem(m);
return;
}
@@ -277,7 +279,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
switch (igmp->igmp_type) {
case IGMP_HOST_MEMBERSHIP_QUERY:
- ++igmpstat.igps_rcv_queries;
+ igmpstat_inc(igps_rcv_queries);
if (ifp->if_flags & IFF_LOOPBACK)
break;
@@ -292,7 +294,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
rti->rti_age = 0;
if (ip->ip_dst.s_addr != INADDR_ALLHOSTS_GROUP) {
- ++igmpstat.igps_rcv_badqueries;
+ igmpstat_inc(igps_rcv_badqueries);
m_freem(m);
return;
}
@@ -317,7 +319,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
}
} else {
if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
- ++igmpstat.igps_rcv_badqueries;
+ igmpstat_inc(igps_rcv_badqueries);
m_freem(m);
return;
}
@@ -367,14 +369,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
break;
case IGMP_v1_HOST_MEMBERSHIP_REPORT:
- ++igmpstat.igps_rcv_reports;
+ igmpstat_inc(igps_rcv_reports);
if (ifp->if_flags & IFF_LOOPBACK)
break;
if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
igmp->igmp_group.s_addr != ip->ip_dst.s_addr) {
- ++igmpstat.igps_rcv_badreports;
+ igmpstat_inc(igps_rcv_badreports);
m_freem(m);
return;
}
@@ -401,7 +403,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
if (inm != NULL) {
inm->inm_timer = 0;
- ++igmpstat.igps_rcv_ourreports;
+ igmpstat_inc(igps_rcv_ourreports);
switch (inm->inm_state) {
case IGMP_IDLE_MEMBER:
@@ -433,14 +435,14 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
break;
#endif
- ++igmpstat.igps_rcv_reports;
+ igmpstat_inc(igps_rcv_reports);
if (ifp->if_flags & IFF_LOOPBACK)
break;
if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
igmp->igmp_group.s_addr != ip->ip_dst.s_addr) {
- ++igmpstat.igps_rcv_badreports;
+ igmpstat_inc(igps_rcv_badreports);
m_freem(m);
return;
}
@@ -469,7 +471,7 @@ igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen)
IN_LOOKUP_MULTI(igmp->igmp_group, ifp, inm);
if (inm != NULL) {
inm->inm_timer = 0;
- ++igmpstat.igps_rcv_ourreports;
+ igmpstat_inc(igps_rcv_ourreports);
switch (inm->inm_state) {
case IGMP_DELAYING_MEMBER:
@@ -671,7 +673,7 @@ igmp_sendpkt(struct ifnet *ifp, struct in_multi *inm, int type,
ip_output(m, router_alert, NULL, IP_MULTICASTOPTS, &imo, NULL, 0);
- ++igmpstat.igps_snd_reports;
+ igmpstat_inc(igps_snd_reports);
}
/*
@@ -689,8 +691,7 @@ igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
case IGMPCTL_STATS:
if (newp != NULL)
return (EPERM);
- return (sysctl_struct(oldp, oldlenp, newp, newlen,
- &igmpstat, sizeof(igmpstat)));
+ return (igmp_sysctl_igmpstat(oldp, oldlenp, newp));
default:
if (name[0] < IGMPCTL_MAXID)
return (sysctl_int_arr(igmpctl_vars, name, namelen,
@@ -699,3 +700,22 @@ igmp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
}
/* NOTREACHED */
}
+
+int
+igmp_sysctl_igmpstat(void *oldp, size_t *oldlenp, void *newp)
+{
+ uint64_t counters[igps_ncounters];
+ struct igmpstat igmpstat;
+ u_long *words = (u_long *)&igmpstat;
+ int i;
+
+ KASSERT(sizeof(igmpstat) == (nitems(counters) * sizeof(u_long)));
+
+ counters_read(igmpcounters, counters, nitems(counters));
+
+ for (i = 0; i < nitems(counters); i++)
+ words[i] = (u_long)counters[i];
+
+ return (sysctl_rdstruct(oldp, oldlenp, newp,
+ &igmpstat, sizeof(igmpstat)));
+}
diff --git a/sys/netinet/igmp_var.h b/sys/netinet/igmp_var.h
index ea066093ec4..091022c8110 100644
--- a/sys/netinet/igmp_var.h
+++ b/sys/netinet/igmp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: igmp_var.h,v 1.9 2008/04/18 06:42:20 djm Exp $ */
+/* $OpenBSD: igmp_var.h,v 1.10 2017/01/04 04:56:24 dlg Exp $ */
/* $NetBSD: igmp_var.h,v 1.9 1996/02/13 23:41:31 christos Exp $ */
/*
@@ -78,7 +78,29 @@ struct igmpstat {
}
#ifdef _KERNEL
-extern struct igmpstat igmpstat;
+
+#include <sys/percpu.h>
+
+enum igmpstat_counters {
+ igps_rcv_total, /* total IGMP messages received */
+ igps_rcv_tooshort, /* received with too few bytes */
+ igps_rcv_badsum, /* received with bad checksum */
+ igps_rcv_queries, /* received membership queries */
+ igps_rcv_badqueries, /* received invalid queries */
+ igps_rcv_reports, /* received membership reports */
+ igps_rcv_badreports, /* received invalid reports */
+ igps_rcv_ourreports, /* received reports for our groups */
+ igps_snd_reports, /* sent membership reports */
+ igps_ncounters
+};
+
+extern struct cpumem *igmpcounters;
+
+static inline void
+igmpstat_inc(enum igmpstat_counters c)
+{
+ counters_inc(igmpcounters, c);
+}
/*
* Macro to compute a random timer value between 1 and (IGMP_MAX_REPORTING_