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
This commit is contained in:
parent
4d0770f172
commit
b02c4e5c78
@ -230,16 +230,15 @@ VNET_DEFINE_STATIC(int, current_state_timers_running); /* IGMPv1/v2 host
|
||||
#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_VERSION_3;
|
||||
*/
|
||||
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);
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user