netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network
@ 2022-07-11 17:51 Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 1/3] net: ipv4: new arp_accept option to accept garp " Jaehee Park
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jaehee Park @ 2022-07-11 17:51 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, shuah,
	linux-kernel, aajith, roopa, aroulin, sbrivio, jhpark1013

The first patch adds an option to learn a neighbor from garp only if
the src ip is in the same subnet of addresses configured on the
interface. The option has been added to arp_accept in ipv4.

The same feature has been added to ndisc (patch 2). For ipv6, the
subnet filtering knob is an extension of the accept_untracked_na
option introduced in these patches:
https://lore.kernel.org/all/642672cb-8b11-c78f-8975-f287ece9e89e@gmail.com/t/
https://lore.kernel.org/netdev/20220530101414.65439-1-aajith@arista.com/T/

The third patch contains selftests for testing the different options
for accepting arp and neighbor advertisements. 

Jaehee Park (3):
  net: ipv4: new arp_accept option to accept garp only if in-network
  net: ipv6: new accept_untracked_na option to accept na only if
    in-network
  selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and
    accept_untracked_na

 Documentation/networking/ip-sysctl.rst        |  48 +--
 include/linux/inetdevice.h                    |   2 +-
 net/ipv4/arp.c                                |  24 +-
 net/ipv6/addrconf.c                           |   2 +-
 net/ipv6/ndisc.c                              |  29 +-
 tools/testing/selftests/net/Makefile          |   1 +
 .../net/arp_ndisc_untracked_subnets.sh        | 281 ++++++++++++++++++
 7 files changed, 360 insertions(+), 27 deletions(-)
 create mode 100755 tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh

-- 
2.30.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH net-next 1/3] net: ipv4: new arp_accept option to accept garp only if in-network
  2022-07-11 17:51 [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee Park
@ 2022-07-11 17:51 ` Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 2/3] net: ipv6: new accept_untracked_na option to accept na " Jaehee Park
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jaehee Park @ 2022-07-11 17:51 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, shuah,
	linux-kernel, aajith, roopa, aroulin, sbrivio, jhpark1013

In many deployments, we want the option to not learn a neighbor from
garp if the src ip is not in the subnet of addresses configured on the
interface. net.ipv4.arp_accept sysctl is currently used to control
creation of a neigh from a received garp packet. This patch adds a
new option '2' to net.ipv4.arp_accept which extends option '1' by
including the subnet check.

Signed-off-by: Jaehee Park <jhpark1013@gmail.com>
Suggested-by: Roopa Prabhu <roopa@nvidia.com>
---
 Documentation/networking/ip-sysctl.rst |  4 +++-
 include/linux/inetdevice.h             |  2 +-
 net/ipv4/arp.c                         | 24 ++++++++++++++++++++++--
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 4c8bbf5acfd1..599373601a2b 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -1633,12 +1633,14 @@ arp_notify - BOOLEAN
 	     or hardware address changes.
 	 ==  ==========================================================
 
-arp_accept - BOOLEAN
+arp_accept - INTEGER
 	Define behavior for gratuitous ARP frames who's IP is not
 	already present in the ARP table:
 
 	- 0 - don't create new entries in the ARP table
 	- 1 - create new entries in the ARP table
+	- 2 - create new entries only if src ip is in the same subnet as
+	  the configured address on the received interface
 
 	Both replies and requests type gratuitous arp will trigger the
 	ARP table to be updated, if this setting is on.
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index ead323243e7b..ddb27fc0ee8c 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -131,7 +131,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 	IN_DEV_ORCONF((in_dev), IGNORE_ROUTES_WITH_LINKDOWN)
 
 #define IN_DEV_ARPFILTER(in_dev)	IN_DEV_ORCONF((in_dev), ARPFILTER)
-#define IN_DEV_ARP_ACCEPT(in_dev)	IN_DEV_ORCONF((in_dev), ARP_ACCEPT)
+#define IN_DEV_ARP_ACCEPT(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ACCEPT)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
 #define IN_DEV_ARP_IGNORE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_IGNORE)
 #define IN_DEV_ARP_NOTIFY(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index af2f12ffc9ca..5eedb042c50b 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -429,6 +429,26 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
 	return !inet_confirm_addr(net, in_dev, sip, tip, scope);
 }
 
+static int arp_accept(struct in_device *in_dev, __be32 sip)
+{
+	struct net *net = dev_net(in_dev->dev);
+	int scope = RT_SCOPE_LINK;
+
+	switch (IN_DEV_ARP_ACCEPT(in_dev)) {
+	case 0: /* don't create new entries from garp */
+		return 0;
+	case 1: /* create new entries from garp */
+		return 1;
+	case 2: /*
+		 * create garp only if sip is in the same subnet
+		 * as an address configured on the incoming interface
+		 */
+		return inet_confirm_addr(net, in_dev, sip, 0, scope) ? 1 : 0;
+	default:
+		return 0;
+	}
+}
+
 static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
 {
 	struct rtable *rt;
@@ -868,12 +888,12 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
 	n = __neigh_lookup(&arp_tbl, &sip, dev, 0);
 
 	addr_type = -1;
-	if (n || IN_DEV_ARP_ACCEPT(in_dev)) {
+	if (n || arp_accept(in_dev, sip)) {
 		is_garp = arp_is_garp(net, dev, &addr_type, arp->ar_op,
 				      sip, tip, sha, tha);
 	}
 
-	if (IN_DEV_ARP_ACCEPT(in_dev)) {
+	if (arp_accept(in_dev, sip)) {
 		/* Unsolicited ARP is not accepted by default.
 		   It is possible, that this option should be enabled for some
 		   devices (strip is candidate)
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 2/3] net: ipv6: new accept_untracked_na option to accept na only if in-network
  2022-07-11 17:51 [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 1/3] net: ipv4: new arp_accept option to accept garp " Jaehee Park
@ 2022-07-11 17:51 ` Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 3/3] selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na Jaehee Park
  2022-07-11 23:42 ` [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee
  3 siblings, 0 replies; 5+ messages in thread
From: Jaehee Park @ 2022-07-11 17:51 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, shuah,
	linux-kernel, aajith, roopa, aroulin, sbrivio, jhpark1013

This patch adds a third knob, '2', which extends the
accept_untracked_na option to learn a neighbor only if the src ip is
in the same subnet of addresses configured on the interfaces. This is
similar to the arp_accept configuration for ipv4.

Signed-off-by: Jaehee Park <jhpark1013@gmail.com>
Suggested-by: Roopa Prabhu <roopa@nvidia.com>
---
 Documentation/networking/ip-sysctl.rst | 50 +++++++++++++++-----------
 net/ipv6/addrconf.c                    |  2 +-
 net/ipv6/ndisc.c                       | 29 ++++++++++++---
 3 files changed, 55 insertions(+), 26 deletions(-)

diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index 599373601a2b..2ee32224cae8 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -2482,27 +2482,36 @@ drop_unsolicited_na - BOOLEAN
 
 	By default this is turned off.
 
-accept_untracked_na - BOOLEAN
-	Add a new neighbour cache entry in STALE state for routers on receiving a
-	neighbour advertisement (either solicited or unsolicited) with target
-	link-layer address option specified if no neighbour entry is already
-	present for the advertised IPv6 address. Without this knob, NAs received
-	for untracked addresses (absent in neighbour cache) are silently ignored.
-
-	This is as per router-side behaviour documented in RFC9131.
-
-	This has lower precedence than drop_unsolicited_na.
-
-	This will optimize the return path for the initial off-link communication
-	that is initiated by a directly connected host, by ensuring that
-	the first-hop router which turns on this setting doesn't have to
-	buffer the initial return packets to do neighbour-solicitation.
-	The prerequisite is that the host is configured to send
-	unsolicited neighbour advertisements on interface bringup.
-	This setting should be used in conjunction with the ndisc_notify setting
-	on the host to satisfy this prerequisite.
+accept_untracked_na - INTEGER
+	Define behavior for accepting neighbor advertisements from devices that
+	are absent in the neighbor cache:
 
-	By default this is turned off.
+	- 0 - (default) Do not accept unsolicited and untracked neighbor
+	  advertisements.
+
+	- 1 - Add a new neighbor cache entry in STALE state for routers on
+	  receiving a neighbor advertisement (either solicited or unsolicited)
+	  with target link-layer address option specified if no neighbor entry
+	  is already present for the advertised IPv6 address. Without this knob,
+	  NAs received for untracked addresses (absent in neighbor cache) are
+	  silently ignored.
+
+	  This is as per router-side behavior documented in RFC9131.
+
+	  This has lower precedence than drop_unsolicited_na.
+
+	  This will optimize the return path for the initial off-link
+	  communication that is initiated by a directly connected host, by
+	  ensuring that the first-hop router which turns on this setting doesn't
+	  have to buffer the initial return packets to do neighbor-solicitation.
+	  The prerequisite is that the host is configured to send unsolicited
+	  neighbor advertisements on interface bringup. This setting should be
+	  used in conjunction with the ndisc_notify setting on the host to
+	  satisfy this prerequisite.
+
+	- 2 - Extend option (1) to add a new neighbor cache entry only if the
+	  source IP is in the same subnet as the configured address on the
+	  received interface.
 
 enhanced_dad - BOOLEAN
 	Include a nonce option in the IPv6 neighbor solicitation messages used for
@@ -2984,4 +2993,3 @@ max_dgram_qlen - INTEGER
 	The maximum length of dgram socket receive queue
 
 	Default: 10
-
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 88becb037eb6..6ed807b6c647 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7042,7 +7042,7 @@ static const struct ctl_table addrconf_sysctl[] = {
 		.data		= &ipv6_devconf.accept_untracked_na,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
+		.proc_handler	= proc_dointvec,
 		.extra1		= (void *)SYSCTL_ZERO,
 		.extra2		= (void *)SYSCTL_ONE,
 	},
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index cd84cbdac0a2..57b0b1c9123a 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -967,6 +967,26 @@ static void ndisc_recv_ns(struct sk_buff *skb)
 		in6_dev_put(idev);
 }
 
+static int accept_untracked_na(struct net_device *dev, struct in6_addr *saddr)
+{
+	struct inet6_dev *idev = __in6_dev_get(dev);
+
+	switch (idev->cnf.accept_untracked_na) {
+	case 0: /* don't accept untracked (absent in neighbor cache) */
+		return 0;
+	case 1: /* create new entries if entry currently untracked */
+		return 1;
+	case 2: /*
+		 * create new entries from untracked only if saddr is in the
+		 * same subnet as an address configured on the incoming
+		 * interface
+		 */
+		return ipv6_chk_prefix(saddr, dev) ? 1 : 0;
+	default:
+		return 0;
+	}
+}
+
 static void ndisc_recv_na(struct sk_buff *skb)
 {
 	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
@@ -1062,10 +1082,11 @@ static void ndisc_recv_na(struct sk_buff *skb)
 	 */
 	new_state = msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE;
 	if (!neigh && lladdr &&
-	    idev && idev->cnf.forwarding &&
-	    idev->cnf.accept_untracked_na) {
-		neigh = neigh_create(&nd_tbl, &msg->target, dev);
-		new_state = NUD_STALE;
+	    idev && idev->cnf.forwarding) {
+		if (accept_untracked_na(dev, saddr)) {
+			neigh = neigh_create(&nd_tbl, &msg->target, dev);
+			new_state = NUD_STALE;
+		}
 	}
 
 	if (neigh && !IS_ERR(neigh)) {
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH net-next 3/3] selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na
  2022-07-11 17:51 [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 1/3] net: ipv4: new arp_accept option to accept garp " Jaehee Park
  2022-07-11 17:51 ` [PATCH net-next 2/3] net: ipv6: new accept_untracked_na option to accept na " Jaehee Park
@ 2022-07-11 17:51 ` Jaehee Park
  2022-07-11 23:42 ` [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee
  3 siblings, 0 replies; 5+ messages in thread
From: Jaehee Park @ 2022-07-11 17:51 UTC (permalink / raw)
  To: netdev
  Cc: davem, yoshfuji, dsahern, edumazet, kuba, pabeni, shuah,
	linux-kernel, aajith, roopa, aroulin, sbrivio, jhpark1013

ipv4 arp_accept has a new option '2' to create new neighbor entries
only if the src ip is in the subnet of configured address on the
interface. This selftest tests all options in arp_accept.

ipv6 has a sysctl endpoint, accept_untracked_na, that defines the
behavior for accepting untracked neighbor advertisements. A new option
similar to that of arp_accept for learning only from the same subnet is
added to accept_untracked_na. This selftest tests this new feature.

Signed-off-by: Jaehee Park <jhpark1013@gmail.com>
Suggested-by: Roopa Prabhu <roopa@nvidia.com>
---
 tools/testing/selftests/net/Makefile          |   1 +
 .../net/arp_ndisc_untracked_subnets.sh        | 281 ++++++++++++++++++
 2 files changed, 282 insertions(+)
 create mode 100755 tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index ddad703ace34..9c2e9e303c37 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -38,6 +38,7 @@ TEST_PROGS += srv6_end_dt6_l3vpn_test.sh
 TEST_PROGS += vrf_strict_mode_test.sh
 TEST_PROGS += arp_ndisc_evict_nocarrier.sh
 TEST_PROGS += ndisc_unsolicited_na_test.sh
+TEST_PROGS += arp_ndisc_untracked_subnets.sh
 TEST_PROGS += stress_reuseport_listen.sh
 TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh
 TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh
diff --git a/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh b/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh
new file mode 100755
index 000000000000..57a14b4e26f2
--- /dev/null
+++ b/tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh
@@ -0,0 +1,281 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# 2 namespaces: one host and one router. Use arping from the host to send a
+# garp to the router. Router accepts or ignores based on its arp_accept
+# configuration.
+
+TESTS="arp ndisc"
+
+ROUTER_NS="ns-router"
+ROUTER_NS_V6="ns-router-v6"
+ROUTER_INTF="veth-router"
+ROUTER_ADDR="10.0.10.1"
+ROUTER_ADDR_V6="2001:db8:abcd:0012::1"
+
+HOST_NS="ns-host"
+HOST_NS_V6="ns-host-v6"
+HOST_INTF="veth-host"
+HOST_ADDR="10.0.10.2"
+HOST_ADDR_V6="2001:db8:abcd:0012::2"
+
+SUBNET_WIDTH=24
+SUBNET_WIDTH_V6=64
+
+cleanup() {
+        ip netns del ${HOST_NS}
+        ip netns del ${ROUTER_NS}
+}
+
+cleanup_v6() {
+        ip netns del ${HOST_NS_V6}
+        ip netns del ${ROUTER_NS_V6}
+}
+
+setup() {
+        local arp_accept=$1
+
+        # setup two namespaces
+        ip netns add ${ROUTER_NS}
+        ip netns add ${HOST_NS}
+
+        # setup interfaces veth0 and veth1, which are pairs in separate
+        # namespaces. veth0 is veth-router, veth1 is veth-host.
+        # first, setup the inteface's link to the namespace
+        # then, set the interface "up"
+        ip netns exec ${ROUTER_NS} ip link add name ${ROUTER_INTF} \
+                type veth peer name ${HOST_INTF}
+
+        ip netns exec ${ROUTER_NS} ip link set dev ${ROUTER_INTF} up
+        ip netns exec ${ROUTER_NS} ip link set dev ${HOST_INTF} netns ${HOST_NS}
+
+        ip netns exec ${HOST_NS} ip link set dev ${HOST_INTF} up
+        ip netns exec ${ROUTER_NS} ip addr add ${ROUTER_ADDR}/${SUBNET_WIDTH} \
+                dev ${ROUTER_INTF}
+
+        ip netns exec ${HOST_NS} ip addr add ${HOST_ADDR}/${SUBNET_WIDTH} \
+                dev ${HOST_INTF}
+        ip netns exec ${HOST_NS} ip route add default via ${HOST_ADDR} \
+                dev ${HOST_INTF}
+        ip netns exec ${ROUTER_NS} ip route add default via ${ROUTER_ADDR} \
+                dev ${ROUTER_INTF}
+
+        ROUTER_CONF=net.ipv4.conf.${ROUTER_INTF}
+        ip netns exec ${ROUTER_NS} sysctl -w \
+                ${ROUTER_CONF}.arp_accept=${arp_accept} >/dev/null 2>&1
+}
+
+setup_v6() {
+        local accept_untracked_na=$1
+
+        # setup two namespaces
+        ip netns add ${ROUTER_NS_V6}
+        ip netns add ${HOST_NS_V6}
+
+        # setup interfaces veth0 and veth1, which are pairs in separate
+        # namespaces. veth0 is veth-router, veth1 is veth-host.
+        # first, setup the inteface's link to the namespace
+        # then, set the interface "up"
+        ip -6 -netns ${ROUTER_NS_V6} link add name ${ROUTER_INTF} \
+                type veth peer name ${HOST_INTF}
+
+        ip -6 -netns ${ROUTER_NS_V6} link set dev ${ROUTER_INTF} up
+        ip -6 -netns ${ROUTER_NS_V6} link set dev ${HOST_INTF} netns \
+                ${HOST_NS_V6}
+
+        ip -6 -netns ${HOST_NS_V6} link set dev ${HOST_INTF} up
+        ip -6 -netns ${ROUTER_NS_V6} addr add \
+                ${ROUTER_ADDR_V6}/${SUBNET_WIDTH_V6} dev ${ROUTER_INTF} nodad
+
+        HOST_CONF=net.ipv6.conf.${HOST_INTF}
+        ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.ndisc_notify=1
+        ip netns exec ${HOST_NS_V6} sysctl -qw ${HOST_CONF}.disable_ipv6=0
+        ip -6 -netns ${HOST_NS_V6} addr add ${HOST_ADDR_V6}/${SUBNET_WIDTH_V6} \
+                dev ${HOST_INTF}
+
+        ROUTER_CONF=net.ipv6.conf.${ROUTER_INTF}
+
+        ip netns exec ${ROUTER_NS_V6} sysctl -w \
+                ${ROUTER_CONF}.forwarding=1 >/dev/null 2>&1
+        ip netns exec ${ROUTER_NS_V6} sysctl -w \
+                ${ROUTER_CONF}.drop_unsolicited_na=0 >/dev/null 2>&1
+        ip netns exec ${ROUTER_NS_V6} sysctl -w \
+                ${ROUTER_CONF}.accept_untracked_na=${accept_untracked_na} \
+                >/dev/null 2>&1
+}
+
+verify_arp() {
+        local arp_accept=$1
+        local same_subnet=$2
+
+        # If no entries, there's an error, so stderr would not be 0.
+        neigh_show_output=$(ip netns exec ${ROUTER_NS} ip neigh get \
+                ${HOST_ADDR} dev ${ROUTER_INTF} 2>/dev/null)
+
+        if [ ${arp_accept} -eq 1 ]; then
+                # Neighbor entries expected.
+                [[ ${neigh_show_output} ]]
+        elif [ ${arp_accept} -eq 2 ]; then
+                if [ ${same_subnet} -eq 1 ]; then
+                        # Neighbor entries expected.
+                        [[ ${neigh_show_output} ]]
+                else
+                        [[ -z ${neigh_show_output} ]]
+                fi
+        else
+                [[ -z ${neigh_show_output} ]]
+        fi
+ }
+
+arp_test_gratuitous() {
+        local arp_accept=$1
+        local same_subnet=$2
+
+        if [ ${arp_accept} -eq 2 ]; then
+                test_msg=("test_arp: "
+                          "accept_arp=$1 "
+                          "same_subnet=$2")
+                if [ ${same_subnet} -eq 0 ]; then
+                        HOST_ADDR=10.0.11.3
+                else
+                        HOST_ADDR=10.0.10.3
+                fi
+        else
+                test_msg=("test_arp: "
+                          "accept_arp=$1")
+        fi
+        # supply arp_accept option to setup which sets it in sysctl
+        setup ${arp_accept}
+        ip netns exec ${HOST_NS} arping -A -U ${HOST_ADDR} -c1 2>&1 >/dev/null
+        verify_arp $1 $2
+
+        if [ $? -eq 0 ]; then
+                printf "    TEST: %-60s  [ OK ]\n" "${test_msg[*]}"
+        else
+                printf "    TEST: %-60s  [FAIL]\n" "${test_msg[*]}"
+        fi
+        cleanup
+}
+
+arp_test_gratuitous_combinations() {
+        arp_test_gratuitous 0
+        arp_test_gratuitous 1
+        arp_test_gratuitous 2 0 # second entry indicates subnet or not
+        arp_test_gratuitous 2 1
+}
+
+cleanup_tcpdump() {
+        set -e
+        [[ ! -z  ${tcpdump_stdout} ]] && rm -f ${tcpdump_stdout}
+        [[ ! -z  ${tcpdump_stderr} ]] && rm -f ${tcpdump_stderr}
+        tcpdump_stdout=
+        tcpdump_stderr=
+        set +e
+}
+
+start_tcpdump() {
+        set -e
+        tcpdump_stdout=`mktemp`
+        tcpdump_stderr=`mktemp`
+        ip netns exec ${ROUTER_NS_V6} timeout 15s \
+                tcpdump --immediate-mode -tpni ${ROUTER_INTF} -c 1 \
+                "icmp6 && icmp6[0] == 136 && src ${HOST_ADDR_V6}" \
+                > ${tcpdump_stdout} 2> /dev/null
+        set +e
+}
+
+verify_ndisc() {
+        local accept_untracked_na=$1
+        local same_subnet=$2
+
+        neigh_show_output=$(ip -6 -netns ${ROUTER_NS_V6} neigh show \
+                to ${HOST_ADDR_V6} dev ${ROUTER_INTF} nud stale)
+
+        if [ ${accept_untracked_na} -eq 1 ]; then
+                # Neighbour entry expected to be present for 011 case
+                [[ ${neigh_show_output} ]]
+        elif [ ${accept_untracked_na} -eq 2 ]; then
+                if [ ${same_subnet} -eq 1 ]; then
+                        [[ ${neigh_show_output} ]]
+                else
+                        [[ -z ${neigh_show_output} ]]
+                fi
+        else
+                # Neighbour entry expected to be absent for all other cases
+                [[ -z ${neigh_show_output} ]]
+        fi
+}
+
+ndisc_test_untracked_advertisements() {
+        # HOST_ADDR_V6="2001:db8:91::3"
+        # ROUTER_ADDR_V6="2001:db8:91::1"
+        test_msg=("test_ndisc: "
+                  "accept_untracked_na=$1")
+
+        local accept_untracked_na=$1
+        local same_subnet=$2
+        if [ ${accept_untracked_na} -eq 2 ]; then
+                test_msg=("test_ndisc: "
+                          "accept_untracked_na=$1 "
+                          "same_subnet=$2")
+                if [ ${same_subnet} -eq 0 ]; then
+                        # not same subnet
+                        HOST_ADDR_V6=2000:db8:abcd:0013::4
+                else
+                        HOST_ADDR_V6=2001:db8:abcd:0012::3
+                fi
+        fi
+        setup_v6 $1 $2
+        start_tcpdump
+        verify_ndisc $1 $2
+
+        if [ $? -eq 0 ]; then
+                printf "    TEST: %-60s  [ OK ]\n" "${test_msg[*]}"
+        else
+                printf "    TEST: %-60s  [FAIL]\n" "${test_msg[*]}"
+        fi
+
+        cleanup_tcpdump
+        cleanup_v6
+}
+
+ndisc_test_untracked_combinations() {
+        ndisc_test_untracked_advertisements 0
+        ndisc_test_untracked_advertisements 1
+        ndisc_test_untracked_advertisements 2 0
+        ndisc_test_untracked_advertisements 2 1
+}
+
+################################################################################
+# usage
+
+usage()
+{
+        cat <<EOF
+usage: ${0##*/} OPTS
+
+        -t <test>       Test(s) to run (default: all)
+                        (options: $TESTS)
+EOF
+}
+
+################################################################################
+# main
+
+while getopts ":t:h" opt; do
+        case $opt in
+                t) TESTS=$OPTARG;;
+                h) usage; exit 0;;
+                *) usage; exit 1;;
+        esac
+done
+
+for t in $TESTS
+do
+        case $t in
+        arp_test_gratuitous_combinations|arp) arp_test_gratuitous_combinations;;
+        ndisc_test_untracked_combinations|ndisc) \
+                ndisc_test_untracked_combinations;;
+        help) echo "Test names: $TESTS"; exit 0;;
+esac
+done
-- 
2.30.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network
  2022-07-11 17:51 [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee Park
                   ` (2 preceding siblings ...)
  2022-07-11 17:51 ` [PATCH net-next 3/3] selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na Jaehee Park
@ 2022-07-11 23:42 ` Jaehee
  3 siblings, 0 replies; 5+ messages in thread
From: Jaehee @ 2022-07-11 23:42 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, yoshfuji, dsahern, edumazet, Jakub Kicinski,
	Paolo Abeni, shuah, linux-kernel, aajith, Roopa Prabhu,
	Andy Roulin, Stefano Brivio

On Mon, Jul 11, 2022 at 10:51 AM Jaehee Park <jhpark1013@gmail.com> wrote:
>
> The first patch adds an option to learn a neighbor from garp only if
> the src ip is in the same subnet of addresses configured on the
> interface. The option has been added to arp_accept in ipv4.
>
> The same feature has been added to ndisc (patch 2). For ipv6, the
> subnet filtering knob is an extension of the accept_untracked_na
> option introduced in these patches:
> https://lore.kernel.org/all/642672cb-8b11-c78f-8975-f287ece9e89e@gmail.com/t/
> https://lore.kernel.org/netdev/20220530101414.65439-1-aajith@arista.com/T/
>
> The third patch contains selftests for testing the different options
> for accepting arp and neighbor advertisements.
>
> Jaehee Park (3):
>   net: ipv4: new arp_accept option to accept garp only if in-network
>   net: ipv6: new accept_untracked_na option to accept na only if
>     in-network
>   selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and
>     accept_untracked_na
>
>  Documentation/networking/ip-sysctl.rst        |  48 +--
>  include/linux/inetdevice.h                    |   2 +-
>  net/ipv4/arp.c                                |  24 +-
>  net/ipv6/addrconf.c                           |   2 +-
>  net/ipv6/ndisc.c                              |  29 +-
>  tools/testing/selftests/net/Makefile          |   1 +
>  .../net/arp_ndisc_untracked_subnets.sh        | 281 ++++++++++++++++++
>  7 files changed, 360 insertions(+), 27 deletions(-)
>  create mode 100755 tools/testing/selftests/net/arp_ndisc_untracked_subnets.sh
>
> --
> 2.30.2
>


I forgot a few cleanups. I will post a v2 soon.
Sorry about that!

Thanks,
Jaehee

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-07-11 23:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-07-11 17:51 [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee Park
2022-07-11 17:51 ` [PATCH net-next 1/3] net: ipv4: new arp_accept option to accept garp " Jaehee Park
2022-07-11 17:51 ` [PATCH net-next 2/3] net: ipv6: new accept_untracked_na option to accept na " Jaehee Park
2022-07-11 17:51 ` [PATCH net-next 3/3] selftests: net: arp_ndisc_untracked_subnets: test for arp_accept and accept_untracked_na Jaehee Park
2022-07-11 23:42 ` [PATCH net-next 0/3] net: ipv4/ipv6: new option to accept garp/untracked na only if in-network Jaehee

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).