Download raw body.
ip6_mroute mp-safe per cpu counter
Hi,
This diff uses per CPU counter infrastructure for IPv6 multicast
counter.
This netstat diff is needed to view the counter:
https://marc.info/?l=openbsd-tech&m=174761223518749&w=2
ok?
bye,
Jan
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
diff -u -p -r1.268 ip6_input.c
--- netinet6/ip6_input.c 2 Mar 2025 21:28:32 -0000 1.268
+++ netinet6/ip6_input.c 19 May 2025 02:02:17 -0000
@@ -161,8 +161,7 @@ ip6_init(void)
ip6counters = counters_alloc(ip6s_ncounters);
#ifdef MROUTING
- rt_timer_queue_init(&ip6_mrouterq, MCAST_EXPIRE_TIMEOUT,
- &mf6c_expire_route);
+ mrt6_init();
#endif
}
@@ -1536,13 +1535,7 @@ ip6_sysctl(int *name, u_int namelen, voi
return (ip6_sysctl_ip6stat(oldp, oldlenp, newp));
#ifdef MROUTING
case IPV6CTL_MRTSTATS:
- if (newp != NULL)
- return (EPERM);
- NET_LOCK();
- error = sysctl_struct(oldp, oldlenp, newp, newlen,
- &mrt6stat, sizeof(mrt6stat));
- NET_UNLOCK();
- return (error);
+ return mrt6_sysctl_mrt6stat(oldp, oldlenp, newp);
case IPV6CTL_MRTMIF:
if (newp)
return (EPERM);
Index: netinet6/ip6_mroute.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_mroute.c,v
diff -u -p -r1.145 ip6_mroute.c
--- netinet6/ip6_mroute.c 18 May 2025 23:27:29 -0000 1.145
+++ netinet6/ip6_mroute.c 19 May 2025 02:02:17 -0000
@@ -133,7 +133,7 @@ struct socket *ip6_mrouter[RT_TABLEID_M
struct rttimer_queue ip6_mrouterq;
int ip6_mrouter_ver = 0;
int ip6_mrtproto; /* for netstat only */
-struct mrt6stat mrt6stat;
+struct cpumem *mrt6counters;
int get_sg6_cnt(struct sioc_sg_req6 *, unsigned int);
int get_mif6_cnt(struct sioc_mif_req6 *, unsigned int);
@@ -142,6 +142,7 @@ int add_m6if(struct socket *, struct mif
int del_m6if(struct socket *, mifi_t *);
int add_m6fc(struct socket *, struct mf6cctl *);
int del_m6fc(struct socket *, struct mf6cctl *);
+void mf6c_expire_route(struct rtentry *, u_int);
struct ifnet *mrt6_iflookupbymif(mifi_t, unsigned int);
struct rtentry *mf6c_find(struct ifnet *, struct in6_addr *, unsigned int);
struct rtentry *mrt6_mcast_add(struct ifnet *, struct sockaddr *);
@@ -203,6 +204,15 @@ ip6_mrouter_get(int cmd, struct socket *
}
}
+void
+mrt6_init(void)
+{
+ mrt6counters = counters_alloc(mrt6s_ncounters);
+
+ rt_timer_queue_init(&ip6_mrouterq, MCAST_EXPIRE_TIMEOUT,
+ &mf6c_expire_route);
+}
+
/*
* Handle ioctl commands to obtain information from the cache
*/
@@ -410,6 +420,38 @@ mrt6_rtwalk_mf6csysctl(struct rtentry *r
}
int
+mrt6_sysctl_mrt6stat(void *oldp, size_t *oldlenp, void *newp)
+{
+ uint64_t counters[mrt6s_ncounters];
+ struct mrt6stat mrt6stat;
+ int i = 0;
+
+#define ASSIGN(field) do { mrt6stat.field = counters[i++]; } while (0)
+
+ memset(&mrt6stat, 0, sizeof mrt6stat);
+ counters_read(mrt6counters, counters, nitems(counters), NULL);
+
+ ASSIGN(mrt6s_mfc_lookups);
+ ASSIGN(mrt6s_mfc_misses);
+ ASSIGN(mrt6s_upcalls);
+ ASSIGN(mrt6s_no_route);
+ ASSIGN(mrt6s_bad_tunnel);
+ ASSIGN(mrt6s_cant_tunnel);
+ ASSIGN(mrt6s_wrong_if);
+ ASSIGN(mrt6s_upq_ovflw);
+ ASSIGN(mrt6s_cache_cleanups);
+ ASSIGN(mrt6s_drop_sel);
+ ASSIGN(mrt6s_q_overflow);
+ ASSIGN(mrt6s_pkt2large);
+ ASSIGN(mrt6s_upq_sockfull);
+
+#undef ASSIGN
+
+ return (sysctl_rdstruct(oldp, oldlenp, newp,
+ &mrt6stat, sizeof(mrt6stat)));
+}
+
+int
mrt6_sysctl_mfc(void *oldp, size_t *oldlenp)
{
unsigned int rtableid;
@@ -906,7 +948,7 @@ ip6_mforward(struct ip6_hdr *ip6, struct
* send message to routing daemon
*/
- mrt6stat.mrt6s_no_route++;
+ mrt6stat_inc(mrt6s_no_route);
{
struct mrt6msg *im;
@@ -947,11 +989,11 @@ ip6_mforward(struct ip6_hdr *ip6, struct
&sin6) < 0) {
log(LOG_WARNING, "ip6_mforward: ip6_mrouter "
"socket queue full\n");
- mrt6stat.mrt6s_upq_sockfull++;
+ mrt6stat_inc(mrt6s_upq_sockfull);
return ENOBUFS;
}
- mrt6stat.mrt6s_upcalls++;
+ mrt6stat_inc(mrt6s_upcalls);
mf6c_add(NULL, &ip6->ip6_src, &ip6->ip6_dst,
mifp->m6_mifi, rtableid, M_NOWAIT);
@@ -1012,7 +1054,7 @@ ip6_mdq(struct mbuf *m, struct ifnet *if
*/
if (mifp->m6_mifi != mf6c->mf6c_parent) {
/* came in the wrong interface */
- mrt6stat.mrt6s_wrong_if++;
+ mrt6stat_inc(mrt6s_wrong_if);
mf6c->mf6c_wrong_if++;
rtfree(rt);
return 0;
Index: netinet6/ip6_mroute.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_mroute.h,v
diff -u -p -r1.24 ip6_mroute.h
--- netinet6/ip6_mroute.h 1 Jan 2025 13:44:22 -0000 1.24
+++ netinet6/ip6_mroute.h 19 May 2025 02:02:17 -0000
@@ -191,12 +191,35 @@ struct sioc_mif_req6 {
};
#if defined(_KERNEL)
+
+enum mrt6stat_counters {
+ mrt6s_mfc_lookups,
+ mrt6s_mfc_misses,
+ mrt6s_upcalls,
+ mrt6s_no_route,
+ mrt6s_bad_tunnel,
+ mrt6s_cant_tunnel,
+ mrt6s_wrong_if,
+ mrt6s_upq_ovflw,
+ mrt6s_cache_cleanups,
+ mrt6s_drop_sel,
+ mrt6s_q_overflow,
+ mrt6s_pkt2large,
+ mrt6s_upq_sockfull,
+ mrt6s_ncounters
+};
+
+extern struct cpumem *mrt6counters;
+
+static inline void
+mrt6stat_inc(enum mrt6stat_counters c)
+{
+ counters_inc(mrt6counters, c);
+}
+
/* How frequent should we look for expired entries (in seconds). */
#define MCAST_EXPIRE_TIMEOUT 30
-extern struct rttimer_queue ip6_mrouterq;
-void mf6c_expire_route(struct rtentry *, u_int);
-
/*
* The kernel's multicast-interface structure.
*/
@@ -232,8 +255,10 @@ int ip6_mrouter_set(int, struct socket *
int ip6_mrouter_get(int, struct socket *, struct mbuf *);
int ip6_mrouter_done(struct socket *);
void ip6_mrouter_detach(struct ifnet *);
+void mrt6_init(void);
int mrt6_ioctl(struct socket *, u_long, caddr_t);
int mrt6_sysctl_mif(void *, size_t *);
+int mrt6_sysctl_mrt6stat(void *, size_t *, void *);
int mrt6_sysctl_mfc(void *, size_t *);
#endif /* _KERNEL */
ip6_mroute mp-safe per cpu counter