Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net Add support for MP-safe network interface statistics...



details:   https://anonhg.NetBSD.org/src/rev/1278a21310fa
branches:  trunk
changeset: 744283:1278a21310fa
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Jan 29 03:16:28 2020 +0000

description:
Add support for MP-safe network interface statistics by maintaining them
in per-cpu storage, and collecting them for export in an if_data structure
when user-space wants them.

The new if_stat API is structured to make a gradual transition to the
new way in network drivers possible, and per-cpu stats are currently
disabled (thus there is no kernel ABI change).  Once all drivers have
been converted, the old ABI will be removed, and per-cpu stats will be
enabled universally.

diffstat:

 sys/net/Makefile   |    6 +-
 sys/net/files.net  |    3 +-
 sys/net/if.c       |   53 +++++++++-------
 sys/net/if.h       |   24 +++++++-
 sys/net/if_stats.c |  161 +++++++++++++++++++++++++++++++++++++++++++++++++++
 sys/net/if_stats.h |  165 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 384 insertions(+), 28 deletions(-)

diffs (truncated from 568 to 300 lines):

diff -r e40c35202c34 -r 1278a21310fa sys/net/Makefile
--- a/sys/net/Makefile  Wed Jan 29 03:04:55 2020 +0000
+++ b/sys/net/Makefile  Wed Jan 29 03:16:28 2020 +0000
@@ -1,12 +1,12 @@
-#      $NetBSD: Makefile,v 1.41 2020/01/20 18:38:18 thorpej Exp $
+#      $NetBSD: Makefile,v 1.42 2020/01/29 03:16:28 thorpej Exp $
 
 INCSDIR= /usr/include/net
 
 INCS=  bpf.h bpfjit.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \
        if_bridgevar.h if_dl.h if_ether.h if_gif.h \
        if_gre.h if_ieee1394.h if_ipsec.h if_llc.h if_media.h if_mpls.h \
-       if_pflog.h if_ppp.h if_pppoe.h if_l2tp.h if_sppp.h if_srt.h if_stf.h \
-       if_tap.h if_tun.h if_types.h if_vlanvar.h net_stats.h \
+       if_pflog.h if_ppp.h if_pppoe.h if_l2tp.h if_sppp.h if_srt.h if_stats.h \
+       if_stf.h if_tap.h if_tun.h if_types.h if_vlanvar.h net_stats.h \
        netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \
        raw_cb.h route.h slcompress.h slip.h zlib.h
 
diff -r e40c35202c34 -r 1278a21310fa sys/net/files.net
--- a/sys/net/files.net Wed Jan 29 03:04:55 2020 +0000
+++ b/sys/net/files.net Wed Jan 29 03:16:28 2020 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.net,v 1.24 2020/01/20 18:38:18 thorpej Exp $
+#      $NetBSD: files.net,v 1.25 2020/01/29 03:16:28 thorpej Exp $
 
 # XXX CLEANUP
 define net
@@ -25,6 +25,7 @@
 file   net/if_mpls.c                   mpls                    needs-flag
 file   net/if_ppp.c                    ppp                     needs-flag
 file   net/if_srt.c                    srt
+file   net/if_stats.c                  net
 file   net/if_stf.c                    stf & inet & inet6      needs-flag
 file   net/if_sl.c                     sl                      needs-flag
 file   net/if_spppsubr.c               sppp
diff -r e40c35202c34 -r 1278a21310fa sys/net/if.c
--- a/sys/net/if.c      Wed Jan 29 03:04:55 2020 +0000
+++ b/sys/net/if.c      Wed Jan 29 03:16:28 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.468 2020/01/20 18:38:18 thorpej Exp $ */
+/*     $NetBSD: if.c,v 1.469 2020/01/29 03:16:28 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.468 2020/01/20 18:38:18 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.469 2020/01/29 03:16:28 thorpej Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -733,6 +733,9 @@
        psref_target_init(&ifp->if_psref, ifnet_psref_class);
        ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
        LIST_INIT(&ifp->if_multiaddrs);
+       if ((rv = if_stats_init(ifp)) != 0) {
+               goto fail;
+       }
 
        IFNET_GLOBAL_LOCK();
        if_getindex(ifp);
@@ -816,7 +819,7 @@
        struct mbuf *m;
 
        while ((m = if_percpuq_dequeue(ipq)) != NULL) {
-               ifp->if_ipackets++;
+               if_statinc(ifp, if_ipackets);
                bpf_mtap(ifp, m, BPF_D_IN);
 
                ifp->_if_input(ifp, m);
@@ -1110,7 +1113,7 @@
        KASSERT(ifp->if_percpuq == NULL);
        KASSERT(!cpu_intr_p());
 
-       ifp->if_ipackets++;
+       if_statinc(ifp, if_ipackets);
        bpf_mtap(ifp, m, BPF_D_IN);
 
        ifp->_if_input(ifp, m);
@@ -1521,6 +1524,7 @@
        mutex_obj_free(ifp->if_ioctl_lock);
        ifp->if_ioctl_lock = NULL;
        mutex_obj_free(ifp->if_snd.ifq_lock);
+       if_stats_fini(ifp);
 
        splx(s);
 
@@ -2959,6 +2963,22 @@
        percpu_foreach(ro_percpu, if_tunnel_rtcache_free_pc, NULL);
 }
 
+void
+if_export_if_data(ifnet_t * const ifp, struct if_data *ifi, bool zero_stats)
+{
+
+       /* Collet the volatile stats first; this zeros *ifi. */
+       if_stats_to_if_data(ifp, ifi, zero_stats);
+
+       ifi->ifi_type = ifp->if_type;
+       ifi->ifi_addrlen = ifp->if_addrlen;
+       ifi->ifi_hdrlen = ifp->if_hdrlen;
+       ifi->ifi_link_state = ifp->if_link_state;
+       ifi->ifi_mtu = ifp->if_mtu;
+       ifi->ifi_metric = ifp->if_metric;
+       ifi->ifi_baudrate = ifp->if_baudrate;
+       ifi->ifi_lastchange = ifp->if_lastchange;
+}
 
 /* common */
 int
@@ -3083,7 +3103,7 @@
 
        case SIOCGIFDATA:
                ifdr = data;
-               ifdr->ifdr_data = ifp->if_data;
+               if_export_if_data(ifp, &ifdr->ifdr_data, false);
                break;
 
        case SIOCGIFINDEX:
@@ -3093,20 +3113,7 @@
 
        case SIOCZIFDATA:
                ifdr = data;
-               ifdr->ifdr_data = ifp->if_data;
-               /*
-                * Assumes that the volatile counters that can be
-                * zero'ed are at the end of if_data.
-                */
-               memset(&ifp->if_data.ifi_ipackets, 0, sizeof(ifp->if_data) -
-                   offsetof(struct if_data, ifi_ipackets));
-               /*
-                * The memset() clears to the bottm of if_data. In the area,
-                * if_lastchange is included. Please be careful if new entry
-                * will be added into if_data or rewite this.
-                *
-                * And also, update if_lastchnage.
-                */
+               if_export_if_data(ifp, &ifdr->ifdr_data, true);
                getnanotime(&ifp->if_lastchange);
                break;
        case SIOCSIFMTU:
@@ -3595,9 +3602,11 @@
                goto out;
        }
 
-       ifp->if_obytes += pktlen;
+       net_stat_ref_t nsr = IF_STAT_GETREF(ifp);
+       if_statadd_ref(nsr, if_obytes, pktlen);
        if (mcast)
-               ifp->if_omcasts++;
+               if_statinc_ref(nsr, if_omcasts);
+       IF_STAT_PUTREF(ifp);
 
        if ((ifp->if_flags & IFF_OACTIVE) == 0)
                if_start_lock(ifp);
@@ -3666,7 +3675,7 @@
        } else
                IFQ_ENQUEUE(&ifp->if_snd, m, error);
        if (error != 0) {
-               ++ifp->if_oerrors;
+               if_statinc(ifp, if_oerrors);
                return error;
        }
        return 0;
diff -r e40c35202c34 -r 1278a21310fa sys/net/if.h
--- a/sys/net/if.h      Wed Jan 29 03:04:55 2020 +0000
+++ b/sys/net/if.h      Wed Jan 29 03:16:28 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.h,v 1.277 2019/09/19 06:07:24 knakahara Exp $       */
+/*     $NetBSD: if.h,v 1.278 2020/01/29 03:16:28 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -173,6 +173,8 @@
 /*
  * Structure defining statistics and other data kept regarding a network
  * interface.
+ *
+ * Only used for exporting data from the interface.
  */
 struct if_data {
        /* generic interface information */
@@ -273,7 +275,20 @@
        short           if_timer;       /* ?: time 'til if_slowtimo called */
        unsigned short  if_flags;       /* i: up/down, broadcast, etc. */
        short           if_extflags;    /* :: if_output MP-safe, etc. */
-       struct if_data  if_data;        /* ?: statistics and other data about if */
+#ifdef __IF_STATS_PERCPU
+       u_char          if_type;        /* :: ethernet, tokenring, etc. */
+       u_char          if_addrlen;     /* :: media address length */
+       u_char          if_hdrlen;      /* :: media header length */
+       /* XXX audit :? fields here. */
+       int             if_link_state;  /* :? current link state */
+       uint64_t        if_mtu;         /* :? maximum transmission unit */
+       uint64_t        if_metric;      /* :? routing metric (external only) */
+       uint64_t        if_baudrate;    /* :? linespeed */
+       struct timespec if_lastchange;  /* :? last operational state change */
+       percpu_t        *if_stats;      /* :: statistics */
+#else /* ! __IF_STATS_PERCPU */
+       struct if_data  if_data;        /* ?: statistics and other data */
+#endif /* __IF_STATS_PERCPU */
        /*
         * Procedure handles.  If you add more of these, don't forget the
         * corresponding NULL stub in if.c.
@@ -393,7 +408,10 @@
                        if_multiaddrs;  /* 6: */
 #endif
 } ifnet_t;
+
+#include <net/if_stats.h>
  
+#ifndef __IF_STATS_PERCPU
 #define        if_mtu          if_data.ifi_mtu
 #define        if_type         if_data.ifi_type
 #define        if_addrlen      if_data.ifi_addrlen
@@ -413,6 +431,7 @@
 #define        if_iqdrops      if_data.ifi_iqdrops
 #define        if_noproto      if_data.ifi_noproto
 #define        if_lastchange   if_data.ifi_lastchange
+#endif /* __IF_STATS_PERCPU */
 #define        if_name(ifp)    ((ifp)->if_xname)
 
 #define        IFF_UP          0x0001          /* interface is up */
@@ -1090,6 +1109,7 @@
 void   if_attachdomain(void);
 void   if_deactivate(struct ifnet *);
 bool   if_is_deactivated(const struct ifnet *);
+void   if_export_if_data(struct ifnet *, struct if_data *, bool);
 void   if_purgeaddrs(struct ifnet *, int, void (*)(struct ifaddr *));
 void   if_detach(struct ifnet *);
 void   if_down(struct ifnet *);
diff -r e40c35202c34 -r 1278a21310fa sys/net/if_stats.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/net/if_stats.c        Wed Jan 29 03:16:28 2020 +0000
@@ -0,0 +1,161 @@
+/*     $NetBSD: if_stats.c,v 1.1 2020/01/29 03:16:28 thorpej Exp $     */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_stats.c,v 1.1 2020/01/29 03:16:28 thorpej Exp $");
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+
+#include <net/if.h>
+
+#define        IF_STATS_SIZE   (sizeof(uint64_t) * IF_NSTATS)
+
+/*
+ * if_stats_init --
+ *     Initialize statistics storage for a network interface.
+ */
+int
+if_stats_init(ifnet_t * const ifp)
+{
+#ifdef __IF_STATS_PERCPU
+       ifp->if_stats = percpu_alloc(IF_STATS_SIZE);
+       if (ifp->if_stats == NULL)
+               return ENOMEM;
+#endif /* __IF_STATS_PERCPU */
+       return 0;
+}
+
+/*
+ * if_stats_fini --
+ *     Tear down statistics storage for a network interface.
+ */
+void



Home | Main Index | Thread Index | Old Index