Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Enable to remove multiple ARP/NDP entries for one destination



details:   https://anonhg.NetBSD.org/src/rev/a81d285459f8
branches:  trunk
changeset: 825057:a81d285459f8
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Wed Jun 28 08:17:50 2017 +0000

description:
Enable to remove multiple ARP/NDP entries for one destination

The kernel can have multiple ARP/NDP entries which have an indentical
destination on different interfaces. This is normal and can be
reproduce easily by ping -I or ping6 -S. We should be able to remove
such entries.

arp -d <ip> and ndp -d <ip> are changed to fetch all ARP/NDP entries
and remove matched entries. So we can remove multiple entries
described above. This fetch all and selective removal behavior is
the same as arp <ip> and ndp <ip>; they also do fetch all entries
and show only matched entries.

Related to PR 51179

diffstat:

 tests/net/arp/t_arp.sh |   92 ++++++++++++++++++++++++++++++++++++++----
 tests/net/ndp/t_ndp.sh |   94 ++++++++++++++++++++++++++++++++++++++----
 usr.sbin/arp/arp.c     |  107 ++++++++++++++++++++++--------------------------
 usr.sbin/ndp/ndp.c     |  104 +++++++++++++++++++++++++++--------------------
 4 files changed, 277 insertions(+), 120 deletions(-)

diffs (truncated from 731 to 300 lines):

diff -r a95e2550c761 -r a81d285459f8 tests/net/arp/t_arp.sh
--- a/tests/net/arp/t_arp.sh    Wed Jun 28 04:14:53 2017 +0000
+++ b/tests/net/arp/t_arp.sh    Wed Jun 28 08:17:50 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: t_arp.sh,v 1.32 2017/06/28 04:14:53 ozaki-r Exp $
+#      $NetBSD: t_arp.sh,v 1.33 2017/06/28 08:17:50 ozaki-r Exp $
 #
 # Copyright (c) 2015 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -654,7 +654,7 @@
        str="$IP4DST link#2"
        atf_check -s exit:0 -o match:"$str" cat $file
 
-       # Test arp -d and resulting routing messages (RTM_GET and RTM_DELETE)
+       # Test arp -d and resulting routing messages (RTM_DELETE)
        rump.route -n monitor -c 2 > $file &
        pid=$?
        sleep 1
@@ -662,13 +662,7 @@
        wait $pid
        $DEBUG && cat $file
 
-       str="RTM_GET.+<UP,DONE,LLINFO>"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="<DST,GATEWAY>"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="$IP4DST $macaddr_dst"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="RTM_DELETE.+<DONE,LLINFO>"
+       str="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>"
        atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
        str="<DST,GATEWAY>"
        atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
@@ -803,6 +797,85 @@
        cleanup
 }
 
+atf_test_case arp_stray_entries cleanup
+arp_stray_entries_head()
+{
+
+       atf_set "descr" "Tests if ARP entries are removed on route change"
+       atf_set "require.progs" "rump_server"
+}
+
+arp_stray_entries_body()
+{
+
+       rump_server_start $SOCKSRC
+       rump_server_start $SOCKDST
+
+       setup_dst_server
+       setup_src_server
+
+       rump_server_add_iface $SOCKSRC shmif1 bus1
+
+       export RUMP_SERVER=$SOCKSRC
+       atf_check -s exit:0 rump.ifconfig shmif1 inet $IP4SRC2/24
+       atf_check -s exit:0 rump.ifconfig -w 10
+
+       $DEBUG && rump.netstat -nr -f inet
+       atf_check -s exit:0 -o ignore rump.ping -n -w 1 -c 1 $IP4DST
+       $DEBUG && rump.arp -na
+       atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
+       atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST
+
+       # Clean up
+       atf_check -s exit:0 -o ignore rump.arp -da
+       atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
+
+       # ping from a different source address
+       atf_check -s exit:0 -o ignore \
+           rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
+       $DEBUG && rump.arp -na
+       atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
+       # ARP reply goes back via shmif1, so a cache is created on shmif1
+       atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST
+
+       # Clean up by arp -da
+       atf_check -s exit:0 -o ignore rump.arp -da
+       atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
+
+       # ping from a different source address again
+       atf_check -s exit:0 -o ignore \
+           rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
+       atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
+       # ARP reply doen't come
+       atf_check -s exit:0 -o not-match:'shmif1' rump.arp -n $IP4DST
+
+       # Cleanup caches on the destination
+       export RUMP_SERVER=$SOCKDST
+       atf_check -s exit:0 -o ignore rump.arp -da
+       export RUMP_SERVER=$SOCKSRC
+
+       # ping from a different source address again
+       atf_check -s exit:0 -o ignore \
+           rump.ping -n -w 1 -c 1 -I $IP4SRC2 $IP4DST
+       atf_check -s exit:0 -o match:'shmif0' rump.arp -n $IP4DST
+       # ARP reply goes back via shmif1
+       atf_check -s exit:0 -o match:'shmif1' rump.arp -n $IP4DST
+
+       # Clean up by arp -d <ip>
+       atf_check -s exit:0 -o ignore rump.arp -d $IP4DST
+       # Both entries should be deleted
+       atf_check -s not-exit:0 -e match:'no entry' rump.arp -n $IP4DST
+
+       rump_server_destroy_ifaces
+}
+
+arp_stray_entries_cleanup()
+{
+
+       $DEBUG && dump
+       cleanup
+}
+
 atf_init_test_cases()
 {
        atf_add_test_case arp_cache_expiration_5s
@@ -818,4 +891,5 @@
        atf_add_test_case arp_purge_on_route_change
        atf_add_test_case arp_purge_on_route_delete
        atf_add_test_case arp_purge_on_ifdown
+       atf_add_test_case arp_stray_entries
 }
diff -r a95e2550c761 -r a81d285459f8 tests/net/ndp/t_ndp.sh
--- a/tests/net/ndp/t_ndp.sh    Wed Jun 28 04:14:53 2017 +0000
+++ b/tests/net/ndp/t_ndp.sh    Wed Jun 28 08:17:50 2017 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: t_ndp.sh,v 1.28 2017/06/28 04:14:53 ozaki-r Exp $
+#      $NetBSD: t_ndp.sh,v 1.29 2017/06/28 08:17:50 ozaki-r Exp $
 #
 # Copyright (c) 2015 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -446,7 +446,7 @@
        str="$IP6DST link#2"
        atf_check -s exit:0 -o match:"$str" cat $file
 
-       # Test ndp -d and resulting routing messages (RTM_GET and RTM_DELETE)
+       # Test ndp -d and resulting routing messages (RTM_DELETE)
        rump.route -n monitor -c 2 > $file &
        pid=$?
        sleep 1
@@ -454,13 +454,7 @@
        wait $pid
        $DEBUG && cat $file
 
-       str="RTM_GET.+<UP,DONE,LLINFO>"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="<DST,GATEWAY>"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="$IP6DST $macaddr_dst"
-       atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_GET $file
-       str="RTM_DELETE.+<DONE,LLINFO>"
+       str="RTM_DELETE.+<HOST,DONE,LLINFO,CLONED>"
        atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
        str="<DST,GATEWAY>"
        atf_check -s exit:0 -o match:"$str" grep -A 3 RTM_DELETE $file
@@ -600,6 +594,87 @@
        cleanup
 }
 
+atf_test_case ndp_stray_entries cleanup
+ndp_stray_entries_head()
+{
+
+       atf_set "descr" "Tests if NDP entries are removed on route change"
+       atf_set "require.progs" "rump_server"
+}
+
+ndp_stray_entries_body()
+{
+
+       rump_server_start $SOCKSRC netinet6
+       rump_server_start $SOCKDST netinet6
+
+       setup_dst_server
+       setup_src_server
+
+       rump_server_add_iface $SOCKSRC shmif1 bus1
+
+       export RUMP_SERVER=$SOCKSRC
+       atf_check -s exit:0 rump.ifconfig shmif1 inet6 $IP6SRC2/64
+       atf_check -s exit:0 rump.ifconfig -w 10
+
+       $DEBUG && rump.netstat -nr -f inet6
+       atf_check -s exit:0 -o ignore rump.ping6 -n -X 1 -c 1 $IP6DST
+       $DEBUG && rump.ndp -na
+       atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
+       atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST
+
+       # Clean up
+       atf_check -s exit:0 -o ignore rump.ndp -c
+       atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
+
+       # ping from a different source address
+       atf_check -s exit:0 -o ignore \
+           rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
+       $DEBUG && rump.ndp -na
+       atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
+       # ARP reply goes back via shmif1, so a cache is created on shmif1
+       atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST
+
+       # Clean up by ndp -c
+       atf_check -s exit:0 -o ignore rump.ndp -c
+       atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
+
+       # ping from a different source address again
+       atf_check -s exit:0 -o ignore \
+           rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
+       atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
+       # ARP reply doen't come
+       atf_check -s exit:0 -o not-match:'shmif1' rump.ndp -n $IP6DST
+
+       # Cleanup caches on the destination
+       export RUMP_SERVER=$SOCKDST
+       $DEBUG && rump.ndp -na
+       atf_check -s exit:0 -o ignore rump.ndp -c
+       $DEBUG && rump.ndp -na
+       export RUMP_SERVER=$SOCKSRC
+
+       # ping from a different source address again
+       atf_check -s exit:0 -o ignore \
+           rump.ping6 -n -X 1 -c 1 -S $IP6SRC2 $IP6DST
+       atf_check -s exit:0 -o match:'shmif0' rump.ndp -n $IP6DST
+       # ARP reply goes back via shmif1
+       atf_check -s exit:0 -o match:'shmif1' rump.ndp -n $IP6DST
+
+       # Clean up by ndp -d <ip>
+       atf_check -s exit:0 -o ignore rump.ndp -d $IP6DST
+       # Both entries should be deleted
+       atf_check -s not-exit:0 -o ignore -e match:'no entry' rump.ndp -n $IP6DST
+
+       rump_server_destroy_ifaces
+}
+
+ndp_stray_entries_cleanup()
+{
+
+       $DEBUG && dump
+       cleanup
+}
+
 atf_init_test_cases()
 {
        atf_add_test_case ndp_cache_expiration
@@ -611,4 +686,5 @@
        atf_add_test_case ndp_purge_on_route_change
        atf_add_test_case ndp_purge_on_route_delete
        atf_add_test_case ndp_purge_on_ifdown
+       atf_add_test_case ndp_stray_entries
 }
diff -r a95e2550c761 -r a81d285459f8 usr.sbin/arp/arp.c
--- a/usr.sbin/arp/arp.c        Wed Jun 28 04:14:53 2017 +0000
+++ b/usr.sbin/arp/arp.c        Wed Jun 28 08:17:50 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: arp.c,v 1.57 2017/06/26 03:13:40 ozaki-r Exp $ */
+/*     $NetBSD: arp.c,v 1.58 2017/06/28 08:17:50 ozaki-r Exp $ */
 
 /*
  * Copyright (c) 1984, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)arp.c      8.3 (Berkeley) 4/28/95";
 #else
-__RCSID("$NetBSD: arp.c,v 1.57 2017/06/26 03:13:40 ozaki-r Exp $");
+__RCSID("$NetBSD: arp.c,v 1.58 2017/06/28 08:17:50 ozaki-r Exp $");
 #endif
 #endif /* not lint */
 
@@ -79,9 +79,9 @@
 #include "prog_ops.h"
 
 static int is_llinfo(const struct sockaddr_dl *, int);
-static int delete(const char *, const char *);
+static int delete_one(struct rt_msghdr *);
 static void dump(uint32_t);
-static void delete_all(void);
+static void delete(const char *, const char *);
 static void sdl_print(const struct sockaddr_dl *);
 static int getifname(u_int16_t, char *, size_t);
 static int atosdl(const char *s, struct sockaddr_dl *sdl);
@@ -90,8 +90,8 @@
 static int getinetaddr(const char *, struct in_addr *);
 static int getsocket(void);
 static struct rt_msghdr *
-       rtmsg(const int, const int, const struct sockaddr_inarp *,
-           const struct sockaddr_dl *);
+       rtmsg(const int, const int,  struct rt_msghdr *,
+           const struct sockaddr_inarp *, const struct sockaddr_dl *);
 static int set(int, char **);
 static void usage(void) __dead;
 
@@ -157,11 +157,11 @@
                break;
        case 'd':
                if (aflag && argc == 0)
-                       delete_all();
+                       delete(NULL, NULL);
                else {



Home | Main Index | Thread Index | Old Index