Download raw body.
Unlock ICMPV6CTL_ERRPPSLIMIT case of icmp6_sysctl()
The last one of locked `icmpv6ctl_vars'.
`icmp6errppslim' is the integer loaded once within icmp6_ratelimit()
which is accessed from two paths. The first one, icmp6_do_error() is
always the end of the error path. The usage of the second one, the
icmp6_redirect_output() is similar to already unlocked `ip6_forwarding',
except that icmp6_ratelimit() called only once. So we don't need to
cache `icmp6errppslim' anywhere.
Since icmp6_sysctl() became mp-safe, unlock it.
ok?
Index: sys/netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.279
diff -u -p -r1.279 icmp6.c
--- sys/netinet6/icmp6.c 16 Sep 2025 09:19:43 -0000 1.279
+++ sys/netinet6/icmp6.c 23 Oct 2025 20:35:03 -0000
@@ -1693,7 +1693,7 @@ icmp6_ratelimit(const struct in6_addr *d
{
/* PPS limit */
if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
- icmp6errppslim))
+ atomic_load_int(&icmp6errppslim)))
return 1; /* The packet is subject to rate limit */
return 0; /* okay to send */
}
@@ -1776,15 +1776,12 @@ icmp6_mtudisc_timeout(struct rtentry *rt
}
#ifndef SMALL_KERNEL
-const struct sysctl_bounded_args icmpv6ctl_vars_unlocked[] = {
+const struct sysctl_bounded_args icmpv6ctl_vars[] = {
{ ICMPV6CTL_ND6_DELAY, &nd6_delay, 0, INT_MAX },
{ ICMPV6CTL_ND6_UMAXTRIES, &nd6_umaxtries, 0, INT_MAX },
{ ICMPV6CTL_ND6_MMAXTRIES, &nd6_mmaxtries, 0, INT_MAX },
{ ICMPV6CTL_MTUDISC_HIWAT, &icmp6_mtudisc_hiwat, 0, INT_MAX },
{ ICMPV6CTL_MTUDISC_LOWAT, &icmp6_mtudisc_lowat, 0, INT_MAX },
-};
-
-const struct sysctl_bounded_args icmpv6ctl_vars[] = {
{ ICMPV6CTL_ERRPPSLIMIT, &icmp6errppslim, -1, 1000 },
};
@@ -1805,12 +1802,6 @@ icmp6_sysctl_icmp6stat(void *oldp, size_
return (ret);
}
-/*
- * Temporary, should be replaced with sysctl_lock after icmp6_sysctl()
- * unlocking.
- */
-struct rwlock icmp6_sysctl_lock = RWLOCK_INITIALIZER("icmp6rwl");
-
int
icmp6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen)
@@ -1829,11 +1820,11 @@ icmp6_sysctl(int *name, u_int namelen, v
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
&newval, 0, INT_MAX);
if (error == 0 && oldval != newval) {
- rw_enter_write(&icmp6_sysctl_lock);
+ rw_enter_write(&sysctl_lock);
atomic_store_int(&icmp6_redirtimeout, newval);
rt_timer_queue_change(&icmp6_redirect_timeout_q,
newval);
- rw_exit_write(&icmp6_sysctl_lock);
+ rw_exit_write(&sysctl_lock);
}
return (error);
@@ -1847,22 +1838,10 @@ icmp6_sysctl(int *name, u_int namelen, v
atomic_load_int(&ln_hold_total));
break;
- case ICMPV6CTL_ND6_DELAY:
- case ICMPV6CTL_ND6_UMAXTRIES:
- case ICMPV6CTL_ND6_MMAXTRIES:
- case ICMPV6CTL_MTUDISC_HIWAT:
- case ICMPV6CTL_MTUDISC_LOWAT:
- error = sysctl_bounded_arr(icmpv6ctl_vars_unlocked,
- nitems(icmpv6ctl_vars_unlocked), name, namelen,
- oldp, oldlenp, newp, newlen);
- break;
-
default:
- NET_LOCK();
error = sysctl_bounded_arr(icmpv6ctl_vars,
nitems(icmpv6ctl_vars), name, namelen, oldp, oldlenp, newp,
newlen);
- NET_UNLOCK();
break;
}
Index: sys/netinet6/in6_proto.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.152
diff -u -p -r1.152 in6_proto.c
--- sys/netinet6/in6_proto.c 16 Sep 2025 09:19:16 -0000 1.152
+++ sys/netinet6/in6_proto.c 23 Oct 2025 20:35:03 -0000
@@ -169,7 +169,7 @@ const struct protosw inet6sw[] = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_ICMPV6,
- .pr_flags = PR_ATOMIC|PR_ADDR,
+ .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPSYSCTL,
.pr_input = icmp6_input,
.pr_ctlinput = rip6_ctlinput,
.pr_ctloutput = rip6_ctloutput,
@@ -376,5 +376,5 @@ u_long rip6_recvspace = RIPV6RCVQ;
/* ICMPV6 parameters */
int icmp6_redirtimeout = 10 * 60; /* 10 minutes */
-int icmp6errppslim = 100; /* 100pps */
+int icmp6errppslim = 100; /* [a] 100pps */
int ip6_mtudisc_timeout = IPMTUDISCTIMEOUT; /* [a] */
Unlock ICMPV6CTL_ERRPPSLIMIT case of icmp6_sysctl()