Download raw body.
mp-safe multicast counter
Hi,
This diff uses the per CPU counters infrastructure for mrtstats. While
here, I also moved the ip_mrouterq() call in a new mrt_init() function.
ok?
bye,
Jan
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
diff -u -p -r1.405 ip_input.c
--- netinet/ip_input.c 12 Mar 2025 23:27:17 -0000 1.405
+++ netinet/ip_input.c 8 May 2025 20:53:57 -0000
@@ -235,8 +235,7 @@ ip_init(void)
ipsec_init();
#endif
#ifdef MROUTING
- rt_timer_queue_init(&ip_mrouterq, MCAST_EXPIRE_FREQUENCY,
- &mfc_expire_route);
+ mrt_init();
#endif
}
@@ -1790,8 +1789,7 @@ ip_sysctl(int *name, u_int namelen, void
return (ip_sysctl_ipstat(oldp, oldlenp, newp));
#ifdef MROUTING
case IPCTL_MRTSTATS:
- return (sysctl_rdstruct(oldp, oldlenp, newp,
- &mrtstat, sizeof(mrtstat)));
+ return (mrt_sysctl_mrtstat(oldp, oldlenp, newp));
case IPCTL_MRTMFC:
if (newp)
return (EPERM);
Index: netinet/ip_mroute.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_mroute.c,v
diff -u -p -r1.144 ip_mroute.c
--- netinet/ip_mroute.c 11 Mar 2025 15:31:03 -0000 1.144
+++ netinet/ip_mroute.c 8 May 2025 21:04:05 -0000
@@ -64,6 +64,7 @@
#include <sys/protosw.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -100,7 +101,7 @@ struct rttimer_queue ip_mrouterq;
uint64_t mrt_count[RT_TABLEID_MAX + 1];
int ip_mrtproto = IGMP_DVMRP; /* for netstat only */
-struct mrtstat mrtstat;
+struct cpumem *mrtcounters;
struct rtentry *mfc_find(struct ifnet *, struct in_addr *,
struct in_addr *, unsigned int);
@@ -113,6 +114,7 @@ int get_version(struct mbuf *);
int add_vif(struct socket *, struct mbuf *);
int del_vif(struct socket *, struct mbuf *);
void update_mfc_params(struct mfcctl2 *, int, unsigned int);
+void mfc_expire_route(struct rtentry *, u_int);
int mfc_add(struct mfcctl2 *, struct in_addr *, struct in_addr *,
int, unsigned int, int);
int add_mfc(struct socket *, struct mbuf *);
@@ -140,8 +142,8 @@ static u_int32_t mrt_api_config = 0;
/*
* Find a route for a given origin IP address and Multicast group address
* Type of service parameter to be added in the future!!!
- * Statistics are updated by the caller if needed
- * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses)
+ * Statistics are updated by the caller if needed (mrts_mfc_lookups and
+ * mrts_mfc_misses)
*/
struct rtentry *
mfc_find(struct ifnet *ifp, struct in_addr *origin, struct in_addr *group,
@@ -249,6 +251,15 @@ ip_mrouter_get(struct socket *so, int op
return (error);
}
+void
+mrt_init(void)
+{
+ mrtcounters = counters_alloc(mrts_ncounters);
+
+ rt_timer_queue_init(&ip_mrouterq, MCAST_EXPIRE_FREQUENCY,
+ &mfc_expire_route);
+}
+
/*
* Handle ioctl commands to obtain information from the cache
*/
@@ -463,6 +474,38 @@ mrt_rtwalk_mfcsysctl(struct rtentry *rt,
}
int
+mrt_sysctl_mrtstat(void *oldp, size_t *oldlenp, void *newp)
+{
+ uint64_t counters[mrts_ncounters];
+ struct mrtstat mrtstat;
+ int i = 0;
+
+#define ASSIGN(field) do { mrtstat.field = counters[i++]; } while (0)
+
+ memset(&mrtstat, 0, sizeof mrtstat);
+ counters_read(mrtcounters, counters, nitems(counters), NULL);
+
+ ASSIGN(mrts_mfc_lookups);
+ ASSIGN(mrts_mfc_misses);
+ ASSIGN(mrts_upcalls);
+ ASSIGN(mrts_no_route);
+ ASSIGN(mrts_bad_tunnel);
+ ASSIGN(mrts_cant_tunnel);
+ ASSIGN(mrts_wrong_if);
+ ASSIGN(mrts_upq_ovflw);
+ ASSIGN(mrts_cache_cleanups);
+ ASSIGN(mrts_drop_sel);
+ ASSIGN(mrts_q_overflow);
+ ASSIGN(mrts_pkt2large);
+ ASSIGN(mrts_upq_sockfull);
+
+#undef ASSIGN
+
+ return (sysctl_rdstruct(oldp, oldlenp, newp,
+ &mrtstat, sizeof(mrtstat)));
+}
+
+int
mrt_sysctl_mfc(void *oldp, size_t *oldlenp)
{
unsigned int rtableid;
@@ -1116,7 +1159,7 @@ ip_mforward(struct mbuf *m, struct ifnet
/*
* Determine forwarding vifs from the forwarding cache table
*/
- ++mrtstat.mrts_mfc_lookups;
+ mrtstat_inc(mrts_mfc_lookups);
rt = mfc_find(NULL, &ip->ip_src, &ip->ip_dst, rtableid);
/* Entry exists, so forward if necessary */
@@ -1129,8 +1172,8 @@ ip_mforward(struct mbuf *m, struct ifnet
*/
int hlen = ip->ip_hl << 2;
- ++mrtstat.mrts_mfc_misses;
- mrtstat.mrts_no_route++;
+ mrtstat_inc(mrts_mfc_misses);
+ mrtstat_inc(mrts_no_route);
{
struct igmpmsg *im;
@@ -1161,13 +1204,13 @@ ip_mforward(struct mbuf *m, struct ifnet
im->im_mbz = 0;
im->im_vif = v->v_id;
- mrtstat.mrts_upcalls++;
+ mrtstat_inc(mrts_upcalls);
sin.sin_addr = ip->ip_src;
if (socket_send(ip_mrouter[rtableid], mm, &sin) < 0) {
log(LOG_WARNING, "ip_mforward: ip_mrouter "
"socket queue full\n");
- ++mrtstat.mrts_upq_sockfull;
+ mrtstat_inc(mrts_upq_sockfull);
return (ENOBUFS);
}
@@ -1203,7 +1246,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp
*/
if (mfc->mfc_parent != v->v_id) {
/* came in the wrong interface */
- ++mrtstat.mrts_wrong_if;
+ mrtstat_inc(mrts_wrong_if);
mfc->mfc_wrong_if++;
rtfree(rt);
return (0);
Index: netinet/ip_mroute.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_mroute.h,v
diff -u -p -r1.33 ip_mroute.h
--- netinet/ip_mroute.h 1 Jan 2025 13:44:22 -0000 1.33
+++ netinet/ip_mroute.h 9 May 2025 07:34:39 -0000
@@ -167,15 +167,36 @@ struct mrtstat {
u_long mrts_upq_sockfull; /* upcalls dropped - socket full */
};
-
#ifdef _KERNEL
+enum mrtstat_counters {
+ mrts_mfc_lookups,
+ mrts_mfc_misses,
+ mrts_upcalls,
+ mrts_no_route,
+ mrts_bad_tunnel,
+ mrts_cant_tunnel,
+ mrts_wrong_if,
+ mrts_upq_ovflw,
+ mrts_cache_cleanups,
+ mrts_drop_sel,
+ mrts_q_overflow,
+ mrts_pkt2large,
+ mrts_upq_sockfull,
+ mrts_ncounters
+};
+
+extern struct cpumem *mrtcounters;
+
+static inline void
+mrtstat_inc(enum mrtstat_counters c)
+{
+ counters_inc(mrtcounters, c);
+}
+
/* How frequent should we look for expired entries (in seconds). */
#define MCAST_EXPIRE_FREQUENCY 30
-extern struct rttimer_queue ip_mrouterq;
-void mfc_expire_route(struct rtentry *, u_int);
-
extern int ip_mrtproto;
/*
@@ -228,8 +249,10 @@ struct igmpmsg {
int ip_mrouter_set(struct socket *, int, struct mbuf *);
int ip_mrouter_get(struct socket *, int, struct mbuf *);
+void mrt_init(void);
int mrt_ioctl(struct socket *, u_long, caddr_t);
int mrt_sysctl_vif(void *, size_t *);
+int mrt_sysctl_mrtstat(void *, size_t *, void *);
int mrt_sysctl_mfc(void *, size_t *);
int ip_mrouter_done(struct socket *);
void vif_delete(struct ifnet *);
mp-safe multicast counter