Module Name: src Committed By: martin Date: Mon Jul 8 16:30:58 UTC 2019
Modified Files: src/sys/netinet6 [netbsd-8]: nd6.c src/tests/net/ndp [netbsd-8]: t_ndp.sh Log Message: Pull up following revision(s) (requested by ozaki-r in ticket #1285): sys/netinet6/nd6.c: revision 1.255 tests/net/ndp/t_ndp.sh: revision 1.32 nd6: restore a missing reachability confirmation On sending a packet over a STALE cache, the cache should be tried a reachability confirmation, which is described in RFC 2461/4861 7.3.3. On the fast path in nd6_resolve, however, the treatment for STALE caches has been skipped accidentally. So STALE caches never be back to the REACHABLE state. To fix the issue, branch to the fast path only when the cache entry is the REACHABLE state and leave other caches to the slow path that includes the treatment. To this end we need to allow to return a link-layer address if a valid address is available on the slow path too, which is the same behavior as FreeBSD and OpenBSD. tests: test state transitions of neighbor caches To generate a diff of this commit: cvs rdiff -u -r1.232.2.9 -r1.232.2.10 src/sys/netinet6/nd6.c cvs rdiff -u -r1.19.2.2 -r1.19.2.3 src/tests/net/ndp/t_ndp.sh Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netinet6/nd6.c diff -u src/sys/netinet6/nd6.c:1.232.2.9 src/sys/netinet6/nd6.c:1.232.2.10 --- src/sys/netinet6/nd6.c:1.232.2.9 Tue Nov 6 14:38:58 2018 +++ src/sys/netinet6/nd6.c Mon Jul 8 16:30:58 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: nd6.c,v 1.232.2.9 2018/11/06 14:38:58 martin Exp $ */ +/* $NetBSD: nd6.c,v 1.232.2.10 2019/07/08 16:30:58 martin Exp $ */ /* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */ /* @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232.2.9 2018/11/06 14:38:58 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.232.2.10 2019/07/08 16:30:58 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_net_mpsafe.h" @@ -2311,8 +2311,8 @@ nd6_resolve(struct ifnet *ifp, const str /* Look up the neighbor cache for the nexthop */ ln = nd6_lookup(&dst->sin6_addr, ifp, false); - if (ln != NULL && (ln->la_flags & LLE_VALID) != 0) { - KASSERT(ln->ln_state > ND6_LLINFO_INCOMPLETE); + if (ln != NULL && (ln->la_flags & LLE_VALID) != 0 && + ln->ln_state == ND6_LLINFO_REACHABLE) { /* Fast path */ memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); LLE_RUNLOCK(ln); @@ -2375,6 +2375,18 @@ nd6_resolve(struct ifnet *ifp, const str } /* + * If the neighbor cache entry has a state other than INCOMPLETE + * (i.e. its link-layer address is already resolved), just + * send the packet. + */ + if (ln->ln_state > ND6_LLINFO_INCOMPLETE) { + KASSERT((ln->la_flags & LLE_VALID) != 0); + memcpy(lldst, &ln->ll_addr, MIN(dstsize, ifp->if_addrlen)); + LLE_WUNLOCK(ln); + return 0; + } + + /* * There is a neighbor cache entry, but no ethernet address * response yet. Append this latest packet to the end of the * packet queue in the mbuf, unless the number of the packet Index: src/tests/net/ndp/t_ndp.sh diff -u src/tests/net/ndp/t_ndp.sh:1.19.2.2 src/tests/net/ndp/t_ndp.sh:1.19.2.3 --- src/tests/net/ndp/t_ndp.sh:1.19.2.2 Mon Apr 2 09:51:58 2018 +++ src/tests/net/ndp/t_ndp.sh Mon Jul 8 16:30:58 2019 @@ -1,4 +1,4 @@ -# $NetBSD: t_ndp.sh,v 1.19.2.2 2018/04/02 09:51:58 martin Exp $ +# $NetBSD: t_ndp.sh,v 1.19.2.3 2019/07/08 16:30:58 martin Exp $ # # Copyright (c) 2015 The NetBSD Foundation, Inc. # All rights reserved. @@ -675,6 +675,81 @@ ndp_stray_entries_cleanup() cleanup } +atf_test_case ndp_cache_state cleanup +ndp_stray_entries_head() +{ + + atf_set "descr" "Tests states of neighbor cache entries" + atf_set "require.progs" "rump_server" +} + +check_cache_state() +{ + local dst=$1 + local state=$2 + + $DEBUG && rump.ndp -n $dst + atf_check -s exit:0 -o match:"^$dst.*$state " rump.ndp -n $dst +} + +wait_until_stalled() +{ + local dst=$1 + local state=$2 + + $DEBUG && rump.ndp -n $dst + while true; do + rump.ndp -n $dst | grep -q "^$dst.*S " && break + sleep 1 + done + $DEBUG && rump.ndp -n $dst +} + +ndp_cache_state_body() +{ + + rump_server_start $SOCKSRC netinet6 + rump_server_start $SOCKDST netinet6 + + setup_dst_server + setup_src_server + + export RUMP_SERVER=$SOCKSRC + + # + # Reachability confirmation (RFC 4861 7.3.3) + # + atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST + + # Receiving a solicited NA packet changes the state of the cache to REACHABLE + check_cache_state $IP6DST R + + # The state of the cache transits to STALE after a while + wait_until_stalled $IP6DST + + # Sending a packet on the cache will run a reachability confirmation + atf_check -s exit:0 -o ignore rump.ping6 -n -X $TIMEOUT -c 1 $IP6DST + + sleep 1 + + # The state of the cache is changed to DELAY and stay for 5s, then + # send a NS packet and change the state to PROBE + check_cache_state $IP6DST D + + sleep $((5 + 1)) + + # If the reachability confirmation is success, the state of the cache + # is changed to REACHABLE + check_cache_state $IP6DST R +} + +ndp_cache_state_cleanup() +{ + + $DEBUG && dump + cleanup +} + atf_init_test_cases() { atf_add_test_case ndp_cache_expiration @@ -687,4 +762,5 @@ atf_init_test_cases() atf_add_test_case ndp_purge_on_route_delete atf_add_test_case ndp_purge_on_ifdown atf_add_test_case ndp_stray_entries + atf_add_test_case ndp_cache_state }