1*b578a8edSthorpej /* $NetBSD: net_stats.c,v 1.6 2020/02/07 12:35:33 thorpej Exp $ */
234908fe5Sthorpej
334908fe5Sthorpej /*-
434908fe5Sthorpej * Copyright (c) 2008 The NetBSD Foundation, Inc.
534908fe5Sthorpej * All rights reserved.
634908fe5Sthorpej *
734908fe5Sthorpej * This code is derived from software contributed to The NetBSD Foundation
834908fe5Sthorpej * by Jason R. Thorpe.
934908fe5Sthorpej *
1034908fe5Sthorpej * Redistribution and use in source and binary forms, with or without
1134908fe5Sthorpej * modification, are permitted provided that the following conditions
1234908fe5Sthorpej * are met:
1334908fe5Sthorpej * 1. Redistributions of source code must retain the above copyright
1434908fe5Sthorpej * notice, this list of conditions and the following disclaimer.
1534908fe5Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
1634908fe5Sthorpej * notice, this list of conditions and the following disclaimer in the
1734908fe5Sthorpej * documentation and/or other materials provided with the distribution.
1834908fe5Sthorpej *
1934908fe5Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2034908fe5Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2134908fe5Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2234908fe5Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2334908fe5Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2434908fe5Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2534908fe5Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2634908fe5Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2734908fe5Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2834908fe5Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2934908fe5Sthorpej * POSSIBILITY OF SUCH DAMAGE.
3034908fe5Sthorpej */
3134908fe5Sthorpej
3234908fe5Sthorpej #include <sys/cdefs.h>
33*b578a8edSthorpej __KERNEL_RCSID(0, "$NetBSD: net_stats.c,v 1.6 2020/02/07 12:35:33 thorpej Exp $");
3434908fe5Sthorpej
3534908fe5Sthorpej #include <sys/types.h>
3634908fe5Sthorpej #include <sys/systm.h>
3734908fe5Sthorpej #include <sys/sysctl.h>
38b129a80cSthorpej #include <sys/kmem.h>
39*b578a8edSthorpej #include <sys/xcall.h>
4034908fe5Sthorpej
4134908fe5Sthorpej #include <net/net_stats.h>
4234908fe5Sthorpej
43b129a80cSthorpej typedef struct {
44b129a80cSthorpej uint64_t *ctx_counters; /* pointer to collated counter array */
45b129a80cSthorpej u_int ctx_ncounters; /* number of counters in array */
46b129a80cSthorpej } netstat_sysctl_context;
47b129a80cSthorpej
4834908fe5Sthorpej /*
4934908fe5Sthorpej * netstat_convert_to_user_cb --
5034908fe5Sthorpej * Internal routine used as a call-back for percpu data enumeration.
5134908fe5Sthorpej */
5234908fe5Sthorpej static void
netstat_convert_to_user_cb(void * v1,void * v2,struct cpu_info * ci)5334908fe5Sthorpej netstat_convert_to_user_cb(void *v1, void *v2, struct cpu_info *ci)
5434908fe5Sthorpej {
5534908fe5Sthorpej const uint64_t *local_counters = v1;
5634908fe5Sthorpej netstat_sysctl_context *ctx = v2;
5734908fe5Sthorpej u_int i;
5834908fe5Sthorpej
5934908fe5Sthorpej for (i = 0; i < ctx->ctx_ncounters; i++)
6034908fe5Sthorpej ctx->ctx_counters[i] += local_counters[i];
6134908fe5Sthorpej }
6234908fe5Sthorpej
6334908fe5Sthorpej /*
6434908fe5Sthorpej * netstat_sysctl --
6534908fe5Sthorpej * Common routine for collating and reporting network statistics
6634908fe5Sthorpej * that are gathered per-CPU. Statistics counters are assumed
6734908fe5Sthorpej * to be arrays of uint64_t's.
6834908fe5Sthorpej */
6934908fe5Sthorpej int
netstat_sysctl(percpu_t * stat,u_int ncounters,SYSCTLFN_ARGS)70b129a80cSthorpej netstat_sysctl(percpu_t *stat, u_int ncounters, SYSCTLFN_ARGS)
7134908fe5Sthorpej {
72b129a80cSthorpej netstat_sysctl_context ctx;
7334908fe5Sthorpej struct sysctlnode node;
74b129a80cSthorpej uint64_t *counters;
75b129a80cSthorpej size_t countersize;
76b129a80cSthorpej int rv;
7734908fe5Sthorpej
78b129a80cSthorpej countersize = sizeof(uint64_t) * ncounters;
79b129a80cSthorpej
80b129a80cSthorpej counters = kmem_zalloc(countersize, KM_SLEEP);
81b129a80cSthorpej ctx.ctx_counters = counters;
82b129a80cSthorpej ctx.ctx_ncounters = ncounters;
83b129a80cSthorpej
84*b578a8edSthorpej percpu_foreach_xcall(stat, XC_HIGHPRI_IPL(IPL_SOFTNET),
85*b578a8edSthorpej netstat_convert_to_user_cb, &ctx);
86b129a80cSthorpej
8734908fe5Sthorpej node = *rnode;
88b129a80cSthorpej node.sysctl_data = counters;
89b129a80cSthorpej node.sysctl_size = countersize;
90b129a80cSthorpej rv = sysctl_lookup(SYSCTLFN_CALL(&node));
91b129a80cSthorpej
92b129a80cSthorpej kmem_free(counters, countersize);
93b129a80cSthorpej
94b129a80cSthorpej return (rv);
9534908fe5Sthorpej }
96