Download raw body.
Unlock ICMPV6CTL_ND6_MAXNUDHINT case of icmp6_sysctl()
Load value of `nd6_maxnudhint' to local variable and pass it to
nd6_nud_hint(). It called in loop in tcp_flush_queue(). Also it
called multiple times in tcp_input_solocked().
Index: sys/netinet/tcp_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/tcp_input.c,v
diff -u -p -r1.459 tcp_input.c
--- sys/netinet/tcp_input.c 11 Aug 2025 15:34:30 -0000 1.459
+++ sys/netinet/tcp_input.c 13 Aug 2025 15:42:28 -0000
@@ -129,16 +129,16 @@ struct timeval tcp_ackdrop_ppslim_last;
* Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint.
*/
#ifdef INET6
-#define ND6_HINT(tp) \
+#define ND6_HINT(tp, hint) \
do { \
if (tp && tp->t_inpcb && \
ISSET(tp->t_inpcb->inp_flags, INP_IPV6) && \
rtisvalid(tp->t_inpcb->inp_route.ro_rt)) { \
- nd6_nud_hint(tp->t_inpcb->inp_route.ro_rt); \
+ nd6_nud_hint(tp->t_inpcb->inp_route.ro_rt, hint); \
} \
} while (0)
#else
-#define ND6_HINT(tp)
+#define ND6_HINT(tp, hint)
#endif
#ifdef TCP_ECN
@@ -311,6 +311,9 @@ tcp_flush_queue(struct tcpcb *tp)
{
struct socket *so = tp->t_inpcb->inp_socket;
struct tcpqent *q, *nq;
+#ifdef INET6
+ int nd6_maxnudhint_local = atomic_load_int(&nd6_maxnudhint);
+#endif
int flags;
/*
@@ -330,7 +333,7 @@ tcp_flush_queue(struct tcpcb *tp)
nq = TAILQ_NEXT(q, tcpqe_q);
TAILQ_REMOVE(&tp->t_segq, q, tcpqe_q);
- ND6_HINT(tp);
+ ND6_HINT(tp, nd6_maxnudhint_local);
if (so->so_rcv.sb_state & SS_CANTRCVMORE)
m_freem(q->tcpqe_m);
else {
@@ -424,6 +427,9 @@ tcp_input_solocked(struct mbuf **mp, int
struct ip6_hdr *ip6 = NULL;
#endif /* INET6 */
int do_ecn = 0;
+#ifdef INET6
+ int nd6_maxnudhint_local = atomic_load_int(&nd6_maxnudhint);
+#endif
#ifdef TCP_ECN
u_char iptos;
#endif
@@ -1021,7 +1027,7 @@ findpcb:
tcpstat_pkt(tcps_rcvackpack, tcps_rcvackbyte,
acked);
tp->t_rcvacktime = now;
- ND6_HINT(tp);
+ ND6_HINT(tp, nd6_maxnudhint_local);
mtx_enter(&so->so_snd.sb_mtx);
sbdrop(&so->so_snd, acked);
@@ -1106,7 +1112,7 @@ findpcb:
/* Packet has most recent segment, no urgent exists. */
tp->rcv_up = tp->rcv_nxt;
tcpstat_pkt(tcps_rcvpack, tcps_rcvbyte, tlen);
- ND6_HINT(tp);
+ ND6_HINT(tp, nd6_maxnudhint_local);
TCP_SETUP_ACK(tp, tiflags, m);
/*
@@ -1811,7 +1817,7 @@ trimthenstep6:
tp->snd_cwnd = ulmin(cw + incr,
TCP_MAXWIN << tp->snd_scale);
}
- ND6_HINT(tp);
+ ND6_HINT(tp, nd6_maxnudhint_local);
if (acked > so->so_snd.sb_cc) {
if (tp->snd_wnd > so->so_snd.sb_cc)
tp->snd_wnd -= so->so_snd.sb_cc;
@@ -2041,7 +2047,7 @@ dodata: /* XXX */
tp->rcv_nxt += tlen;
tiflags = th->th_flags & TH_FIN;
tcpstat_pkt(tcps_rcvpack, tcps_rcvbyte, tlen);
- ND6_HINT(tp);
+ ND6_HINT(tp, nd6_maxnudhint_local);
if (so->so_rcv.sb_state & SS_CANTRCVMORE)
m_freem(m);
else {
Index: sys/netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
diff -u -p -r1.277 icmp6.c
--- sys/netinet6/icmp6.c 13 Aug 2025 11:30:31 -0000 1.277
+++ sys/netinet6/icmp6.c 13 Aug 2025 15:42:28 -0000
@@ -1781,12 +1781,12 @@ const struct sysctl_bounded_args icmpv6c
{ 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_ND6_MAXNUDHINT, &nd6_maxnudhint, 0, INT_MAX },
{ ICMPV6CTL_MTUDISC_LOWAT, &icmp6_mtudisc_lowat, 0, INT_MAX },
};
const struct sysctl_bounded_args icmpv6ctl_vars[] = {
{ ICMPV6CTL_ERRPPSLIMIT, &icmp6errppslim, -1, 1000 },
- { ICMPV6CTL_ND6_MAXNUDHINT, &nd6_maxnudhint, 0, INT_MAX },
};
int
@@ -1851,6 +1851,7 @@ icmp6_sysctl(int *name, u_int namelen, v
case ICMPV6CTL_ND6_DELAY:
case ICMPV6CTL_ND6_UMAXTRIES:
case ICMPV6CTL_ND6_MMAXTRIES:
+ case ICMPV6CTL_ND6_MAXNUDHINT:
case ICMPV6CTL_MTUDISC_HIWAT:
case ICMPV6CTL_MTUDISC_LOWAT:
error = sysctl_bounded_arr(icmpv6ctl_vars_unlocked,
Index: sys/netinet6/nd6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.c,v
diff -u -p -r1.299 nd6.c
--- sys/netinet6/nd6.c 4 Aug 2025 21:50:59 -0000 1.299
+++ sys/netinet6/nd6.c 13 Aug 2025 15:42:28 -0000
@@ -83,7 +83,7 @@ int nd6_gctimer = (60 * 60 * 24); /* 1 d
/* preventing too many loops in ND option parsing */
int nd6_maxndopt = 10; /* max # of ND options allowed */
-int nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */
+int nd6_maxnudhint = 0; /* [a] max # of subsequent upper layer hints */
/* llinfo_nd6 live time, rt_llinfo and RTF_LLINFO are protected by nd6_mtx */
struct mutex nd6_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
@@ -674,7 +674,7 @@ nd6_free(struct rtentry *rt, struct ifne
* XXX cost-effective methods?
*/
void
-nd6_nud_hint(struct rtentry *rt)
+nd6_nud_hint(struct rtentry *rt, int maxnudhint)
{
struct llinfo_nd6 *ln;
struct ifnet *ifp;
@@ -706,7 +706,7 @@ nd6_nud_hint(struct rtentry *rt)
* it is possible we have false information.
*/
ln->ln_byhint++;
- if (ln->ln_byhint > nd6_maxnudhint)
+ if (ln->ln_byhint > maxnudhint)
goto out;
ln->ln_state = ND6_LLINFO_REACHABLE;
Index: sys/netinet6/nd6.h
===================================================================
RCS file: /cvs/src/sys/netinet6/nd6.h,v
diff -u -p -r1.102 nd6.h
--- sys/netinet6/nd6.h 19 May 2025 06:50:00 -0000 1.102
+++ sys/netinet6/nd6.h 13 Aug 2025 15:42:28 -0000
@@ -125,7 +125,7 @@ struct rtentry *nd6_lookup(const struct
u_int);
void nd6_llinfo_settimer(const struct llinfo_nd6 *, unsigned int);
void nd6_purge(struct ifnet *);
-void nd6_nud_hint(struct rtentry *);
+void nd6_nud_hint(struct rtentry *, int);
void nd6_rtrequest(struct ifnet *, int, struct rtentry *);
int nd6_ioctl(u_long, caddr_t, struct ifnet *);
void nd6_cache_lladdr(struct ifnet *, const struct in6_addr *, char *,
Unlock ICMPV6CTL_ND6_MAXNUDHINT case of icmp6_sysctl()