Author: mhorne
Date: Sun Nov  8 18:49:23 2020
New Revision: 367493
URL: https://svnweb.freebsd.org/changeset/base/367493

Log:
  igmp: convert igmpstat to use PCPU counters
  
  Currently there is no locking done to protect this structure. It is
  likely okay due to the low-volume nature of IGMP, but allows for
  the possibility of underflow. This appears to be one of the only
  holdouts of the conversion to counter(9) which was done for most
  protocol stat structures around 2013.
  
  This also updates the visibility of this stats structure so that it can
  be consumed from elsewhere in the kernel, consistent with the vast
  majority of VNET_PCPUSTAT structures.
  
  Reviewed by:  kp
  Sponsored by: NetApp, Inc.
  Sponsored by: Klara, Inc.
  Differential Revision:        https://reviews.freebsd.org/D27023

Modified:
  head/sys/netinet/igmp.c
  head/sys/netinet/igmp_var.h

Modified: head/sys/netinet/igmp.c
==============================================================================
--- head/sys/netinet/igmp.c     Sun Nov  8 18:47:05 2020        (r367492)
+++ head/sys/netinet/igmp.c     Sun Nov  8 18:49:23 2020        (r367493)
@@ -230,16 +230,15 @@ VNET_DEFINE_STATIC(int, current_state_timers_running);
 #define        V_state_change_timers_running   
VNET(state_change_timers_running)
 #define        V_current_state_timers_running  
VNET(current_state_timers_running)
 
+VNET_PCPUSTAT_DEFINE(struct igmpstat, igmpstat);
+VNET_PCPUSTAT_SYSINIT(igmpstat);
+VNET_PCPUSTAT_SYSUNINIT(igmpstat);
+
 VNET_DEFINE_STATIC(LIST_HEAD(, igmp_ifsoftc), igi_head) =
     LIST_HEAD_INITIALIZER(igi_head);
-VNET_DEFINE_STATIC(struct igmpstat, igmpstat) = {
-       .igps_version = IGPS_VERSION_3,
-       .igps_len = sizeof(struct igmpstat),
-};
 VNET_DEFINE_STATIC(struct timeval, igmp_gsrdelay) = {10, 0};
 
 #define        V_igi_head                      VNET(igi_head)
-#define        V_igmpstat                      VNET(igmpstat)
 #define        V_igmp_gsrdelay                 VNET(igmp_gsrdelay)
 
 VNET_DEFINE_STATIC(int, igmp_recvifkludge) = 1;
@@ -263,7 +262,8 @@ VNET_DEFINE_STATIC(int, igmp_default_version) = IGMP_V
  */
 SYSCTL_PROC(_net_inet_igmp, IGMPCTL_STATS, stats,
     CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_MPSAFE,
-    &VNET_NAME(igmpstat), 0, sysctl_igmp_stat, "S,igmpstat", "");
+    &VNET_NAME(igmpstat), 0, sysctl_igmp_stat, "S,igmpstat",
+    "IGMP statistics (struct igmpstat, netinet/igmp_var.h)");
 SYSCTL_INT(_net_inet_igmp, OID_AUTO, recvifkludge, CTLFLAG_VNET | CTLFLAG_RW,
     &VNET_NAME(igmp_recvifkludge), 0,
     "Rewrite IGMPv1/v2 reports from 0.0.0.0 to contain subnet address");
@@ -347,22 +347,31 @@ sysctl_igmp_stat(SYSCTL_HANDLER_ARGS)
        int error;
        char *p;
 
-       error = sysctl_wire_old_buffer(req, sizeof(V_igmpstat));
+       error = sysctl_wire_old_buffer(req, sizeof(struct igmpstat));
        if (error)
                return (error);
 
        if (req->oldptr != NULL) {
-               if (req->oldlen < sizeof(V_igmpstat))
+               if (req->oldlen < sizeof(struct igmpstat))
                        error = ENOMEM;
-               else 
-                       error = SYSCTL_OUT(req, &V_igmpstat,
-                           sizeof(V_igmpstat));
+               else {
+                       /*
+                        * Copy the counters, and explicitly set the struct's
+                        * version and length fields.
+                        */
+                       COUNTER_ARRAY_COPY(VNET(igmpstat), &igps0,
+                           sizeof(struct igmpstat) / sizeof(uint64_t));
+                       igps0.igps_version = IGPS_VERSION_3;
+                       igps0.igps_len = IGPS_VERSION3_LEN;
+                       error = SYSCTL_OUT(req, &igps0,
+                           sizeof(struct igmpstat));
+               }
        } else
-               req->validlen = sizeof(V_igmpstat);
+               req->validlen = sizeof(struct igmpstat);
        if (error)
                goto out;
        if (req->newptr != NULL) {
-               if (req->newlen < sizeof(V_igmpstat))
+               if (req->newlen < sizeof(struct igmpstat))
                        error = ENOMEM;
                else
                        error = SYSCTL_IN(req, &igps0,
@@ -379,12 +388,8 @@ sysctl_igmp_stat(SYSCTL_HANDLER_ARGS)
                        error = EINVAL;
                        goto out;
                }
-               /*
-                * Avoid overwrite of the version and length field.
-                */
-               igps0.igps_version = V_igmpstat.igps_version;
-               igps0.igps_len = V_igmpstat.igps_len;
-               bcopy(&igps0, &V_igmpstat, sizeof(V_igmpstat));
+               COUNTER_ARRAY_ZERO(VNET(igmpstat),
+                   sizeof(struct igmpstat) / sizeof(uint64_t));
        }
 out:
        return (error);

Modified: head/sys/netinet/igmp_var.h
==============================================================================
--- head/sys/netinet/igmp_var.h Sun Nov  8 18:47:05 2020        (r367492)
+++ head/sys/netinet/igmp_var.h Sun Nov  8 18:49:23 2020        (r367493)
@@ -54,6 +54,7 @@
 struct igmpstat {
        /*
         * Structure header (to insulate ABI changes).
+        * XXX: unset inside the kernel, exported via sysctl_igmp_stat().
         */
        uint32_t igps_version;          /* version of this structure */
        uint32_t igps_len;              /* length of this structure */
@@ -184,8 +185,12 @@ struct igmp_ifinfo {
 };
 
 #ifdef _KERNEL
-#define        IGMPSTAT_ADD(name, val)         V_igmpstat.name += (val)
-#define        IGMPSTAT_INC(name)              IGMPSTAT_ADD(name, 1)
+#include <sys/counter.h>
+
+VNET_PCPUSTAT_DECLARE(struct igmpstat, igmpstat);
+#define        IGMPSTAT_ADD(name, val) \
+    VNET_PCPUSTAT_ADD(struct igmpstat, igmpstat, name, (val))
+#define        IGMPSTAT_INC(name)      IGMPSTAT_ADD(name, 1)
 
 /*
  * Subsystem lock macros.
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to