Download raw body.
sysctl(2): push locking down to icmp_sysctl()
On Wed, Dec 04, 2024 at 10:04:33PM +0300, Vitaliy Makkoveev wrote:
> Keep locking only for ICMPCTL_REDIRTIMEOUT case. It is complicated, so
> left it as is.
>
> ICMPCTL_STATS loads per-CPU counters into local data, so no locking
> required.
>
> `icmpctl_vars' are atomically accessed integers. Except `icmperrppslim'
> they are simply booleans, so nothing special required. I used the local
> `icmperrppslim_local' variable to load `icmperrppslim' value because it
> it could have negative values. claudio@ proposed to always load such
> values to local variables, so I want to try this notation with this
> diff.
OK bluhm@
> Index: sys/netinet/in_proto.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/in_proto.c,v
> diff -u -p -r1.113 in_proto.c
> --- sys/netinet/in_proto.c 22 Aug 2024 10:58:31 -0000 1.113
> +++ sys/netinet/in_proto.c 4 Dec 2024 18:55:34 -0000
> @@ -219,7 +219,7 @@ const struct protosw inetsw[] = {
> .pr_type = SOCK_RAW,
> .pr_domain = &inetdomain,
> .pr_protocol = IPPROTO_ICMP,
> - .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET,
> + .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSOCKET|PR_MPSYSCTL,
> .pr_input = icmp_input,
> .pr_ctloutput = rip_ctloutput,
> .pr_usrreqs = &rip_usrreqs,
> Index: sys/netinet/ip_icmp.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
> diff -u -p -r1.196 ip_icmp.c
> --- sys/netinet/ip_icmp.c 14 Jul 2024 18:53:39 -0000 1.196
> +++ sys/netinet/ip_icmp.c 4 Dec 2024 18:55:34 -0000
> @@ -105,16 +105,21 @@
> * host table maintenance routines.
> */
>
> +/*
> + * Locks used to protect data:
> + * a atomic
> + */
> +
> #ifdef ICMPPRINTFS
> int icmpprintfs = 0; /* Settable from ddb */
> #endif
>
> /* values controllable via sysctl */
> -int icmpmaskrepl = 0;
> -int icmpbmcastecho = 0;
> -int icmptstamprepl = 1;
> -int icmperrppslim = 100;
> -int icmp_rediraccept = 0;
> +int icmpmaskrepl = 0; /* [a] */
> +int icmpbmcastecho = 0; /* [a] */
> +int icmptstamprepl = 1; /* [a] */
> +int icmperrppslim = 100; /* [a] */
> +int icmp_rediraccept = 0; /* [a] */
> int icmp_redirtimeout = 10 * 60;
>
> static int icmperrpps_count = 0;
> @@ -506,7 +511,7 @@ icmp_input_if(struct ifnet *ifp, struct
> break;
>
> case ICMP_ECHO:
> - if (!icmpbmcastecho &&
> + if (atomic_load_int(&icmpbmcastecho) == 0 &&
> (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
> icmpstat_inc(icps_bmcastecho);
> break;
> @@ -515,10 +520,10 @@ icmp_input_if(struct ifnet *ifp, struct
> goto reflect;
>
> case ICMP_TSTAMP:
> - if (icmptstamprepl == 0)
> + if (atomic_load_int(&icmptstamprepl) == 0)
> break;
>
> - if (!icmpbmcastecho &&
> + if (atomic_load_int(&icmpbmcastecho) == 0 &&
> (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
> icmpstat_inc(icps_bmcastecho);
> break;
> @@ -533,7 +538,7 @@ icmp_input_if(struct ifnet *ifp, struct
> goto reflect;
>
> case ICMP_MASKREQ:
> - if (icmpmaskrepl == 0)
> + if (atomic_load_int(&icmpmaskrepl) == 0)
> break;
> if (icmplen < ICMP_MASKLEN) {
> icmpstat_inc(icps_badlen);
> @@ -590,7 +595,7 @@ reflect:
> struct rtentry *newrt = NULL;
> int i_am_router = (atomic_load_int(&ip_forwarding) != 0);
>
> - if (icmp_rediraccept == 0 || i_am_router)
> + if (atomic_load_int(&icmp_rediraccept) == 0 || i_am_router)
> goto freeit;
> if (code > 3)
> goto badcode;
> @@ -884,24 +889,27 @@ icmp_sysctl(int *name, u_int namelen, vo
> return (ENOTDIR);
>
> switch (name[0]) {
> - case ICMPCTL_REDIRTIMEOUT:
> + case ICMPCTL_REDIRTIMEOUT: {
> + size_t savelen = *oldlenp;
> +
> + if ((error = sysctl_vslock(oldp, savelen)))
> + break;
> NET_LOCK();
> error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
> &icmp_redirtimeout, 0, INT_MAX);
> rt_timer_queue_change(&icmp_redirect_timeout_q,
> icmp_redirtimeout);
> NET_UNLOCK();
> + sysctl_vsunlock(oldp, savelen);
> break;
> -
> + }
> case ICMPCTL_STATS:
> error = icmp_sysctl_icmpstat(oldp, oldlenp, newp);
> break;
>
> default:
> - NET_LOCK();
> error = sysctl_bounded_arr(icmpctl_vars, nitems(icmpctl_vars),
> name, namelen, oldp, oldlenp, newp, newlen);
> - NET_UNLOCK();
> break;
> }
>
> @@ -1098,9 +1106,10 @@ icmp_mtudisc_timeout(struct rtentry *rt,
> int
> icmp_ratelimit(const struct in_addr *dst, const int type, const int code)
> {
> + int icmperrppslim_local = atomic_load_int(&icmperrppslim);
> /* PPS limit */
> if (!ppsratecheck(&icmperrppslim_last, &icmperrpps_count,
> - icmperrppslim))
> + icmperrppslim_local))
> return 1; /* The packet is subject to rate limit */
> return 0; /* okay to send */
> }
sysctl(2): push locking down to icmp_sysctl()