CVS commit: src/sys
"Ryota Ozaki" <[email protected]>
| Newsgroups | gmane.os.netbsd.devel.cvs |
|---|---|
| Message-ID | <[email protected]> |
Module Name: src Committed By: ozaki-r Date: Thu Mar 26 04:35:17 UTC 2026 Modified Files: src/sys/net: if_llatbl.h nd.c src/sys/netinet: if_arp.c src/sys/netinet6: nd6.c Log Message: commit 27c3de6c8063a7850ef0efbea0d83f314e541ce8 Author: Ryota Ozaki <[email protected]> Date: Thu Mar 12 12:42:03 2026 +0900 nd: reset ln_asked on state reset Even if a userland program such as ping continuously sends packets to a (temporarily) unreachable host, the ND resolver only sends request packets up to nd_mmaxtries times. This change allows ND request packets to continue being sent while the userland process is still sending packets. Additionally, introduce LLE_UNRESOLVED to fix another issue. nd_resolve may incorrectly return an error immediately after sending the last ND request packet. For example, if nd_mmaxtries = 1 and two packets arrive simultaneously, nd_resolve returns an error for the second packet. This occurs because ln_asked is used to determine whether the ND resolution is still in progress. Instead, use the new LLE_UNRESOLVED state. It is set when the state transitions to WAITDELETE, i.e., one second after the last request is sent without successful address resolution. PR kern/60071 diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h index a83f31cac70..31a3ebef30b 100644 --- a/sys/net/if_llatbl.h +++ b/sys/net/if_llatbl.h @@ -249,6 +249,7 @@ MALLOC_DECLARE(M_LLTABLE); #define LLE_VALID 0x0008 /* ll_addr is valid */ #define LLE_PUB 0x0020 /* publish entry ??? */ #define LLE_LINKED 0x0040 /* linked to lookup structure */ +#define LLE_UNRESOLVED 0x0080 /* address unresolved */ /* LLE request flags */ #define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */ diff --git a/sys/net/nd.c b/sys/net/nd.c index 8ebc5fe5338..8d12c1d7b58 100644 --- a/sys/net/nd.c +++ b/sys/net/nd.c @@ -113,6 +113,7 @@ nd_timer(void *arg) missed = ND_LLINFO_INCOMPLETE; ln->ln_state = ND_LLINFO_WAITDELETE; + ln->la_flags |= LLE_UNRESOLVED; break; case ND_LLINFO_REACHABLE: @@ -360,8 +361,10 @@ nd_resolve(struct llentry *ln, const struct rtentry *rt, struct mbuf *m, * the oldest packet in the queue will be removed. */ if (ln->ln_state == ND_LLINFO_NOSTATE || - ln->ln_state == ND_LLINFO_WAITDELETE) + ln->ln_state == ND_LLINFO_WAITDELETE) { + ln->ln_asked = 0; ln->ln_state = ND_LLINFO_INCOMPLETE; + } #ifdef MBUFTRACE m_claimm(m, ln->lle_tbl->llt_mowner); @@ -398,7 +401,7 @@ nd_resolve(struct llentry *ln, const struct rtentry *rt, struct mbuf *m, ln->la_numheld, nd->nd_maxqueuelen); ln->la_numheld++; - if (ln->ln_asked >= nd->nd_mmaxtries) + if ((ln->la_flags & LLE_UNRESOLVED) != 0) error = (rt != NULL && rt->rt_flags & RTF_GATEWAY) ? EHOSTUNREACH : EHOSTDOWN; else diff --git a/sys/netinet/if_arp.c b/sys/netinet/if_arp.c index 2934534efb1..fc4d0252a74 100644 --- a/sys/netinet/if_arp.c +++ b/sys/netinet/if_arp.c @@ -1056,6 +1056,7 @@ again: KASSERT(sizeof(la->ll_addr) >= ifp->if_addrlen); memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen); la->la_flags |= LLE_VALID; + la->la_flags &= ~LLE_UNRESOLVED; la->ln_asked = 0; if (new_state != 0) { la->ln_state = new_state; diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index aeaef609a79..1920759ecbc 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1400,6 +1400,7 @@ nd6_cache_lladdr( */ memcpy(&ln->ll_addr, lladdr, ifp->if_addrlen); ln->la_flags |= LLE_VALID; + ln->la_flags &= ~LLE_UNRESOLVED; } if (!is_newentry) { To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/net/if_llatbl.h cvs rdiff -u -r1.9 -r1.10 src/sys/net/nd.c cvs rdiff -u -r1.318 -r1.319 src/sys/netinet/if_arp.c cvs rdiff -u -r1.285 -r1.286 src/sys/netinet6/nd6.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.