netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Toke Høiland-Jørgensen" <toke@redhat.com>
To: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@kernel.org>,
	netdev@vger.kernel.org, bpf@vger.kernel.org
Subject: [PATCH RFC bpf-next 2/2] selftests: Update test_tc_neigh to use the modified bpf_redirect_neigh()
Date: Thu, 15 Oct 2020 17:46:49 +0200	[thread overview]
Message-ID: <160277680973.157904.15451524562795164056.stgit@toke.dk> (raw)
In-Reply-To: <160277680746.157904.8726318184090980429.stgit@toke.dk>

From: Toke Høiland-Jørgensen <toke@redhat.com>

This updates the test_tc_neigh selftest to use the new syntax of
bpf_redirect_neigh(). To exercise the helper both with and without the
optional parameter, one forwarding direction is changed to do a
bpf_fib_lookup() followed by a call to bpf_redirect_neigh(), while the
other direction is using the map-based ifindex lookup letting the redirect
helper resolve the nexthop from the FIB.

This also fixes the test_tc_redirect.sh script to work on systems that have
a consolidated dual-stack 'ping' binary instead of separate ping/ping6
versions.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
 tools/testing/selftests/bpf/progs/test_tc_neigh.c |   83 ++++++++++++++++++---
 tools/testing/selftests/bpf/test_tc_redirect.sh   |    8 +-
 2 files changed, 78 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/test_tc_neigh.c b/tools/testing/selftests/bpf/progs/test_tc_neigh.c
index fe182616b112..ba03e603ba9b 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_neigh.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_neigh.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <stdint.h>
 #include <stdbool.h>
+#include <stddef.h>
 
 #include <linux/bpf.h>
 #include <linux/stddef.h>
@@ -32,6 +33,9 @@
 				 a.s6_addr32[3] == b.s6_addr32[3])
 #endif
 
+#define AF_INET 2
+#define AF_INET6 10
+
 enum {
 	dev_src,
 	dev_dst,
@@ -45,7 +49,8 @@ struct bpf_map_def SEC("maps") ifindex_map = {
 };
 
 static __always_inline bool is_remote_ep_v4(struct __sk_buff *skb,
-					    __be32 addr)
+					    __be32 addr,
+					    struct bpf_fib_lookup *fib_params)
 {
 	void *data_end = ctx_ptr(skb->data_end);
 	void *data = ctx_ptr(skb->data);
@@ -58,11 +63,26 @@ static __always_inline bool is_remote_ep_v4(struct __sk_buff *skb,
 	if ((void *)(ip4h + 1) > data_end)
 		return false;
 
-	return ip4h->daddr == addr;
+	if (ip4h->daddr != addr)
+		return false;
+
+	if (fib_params) {
+		fib_params->family = AF_INET;
+		fib_params->tos = ip4h->tos;
+		fib_params->l4_protocol = ip4h->protocol;
+		fib_params->sport = 0;
+		fib_params->dport = 0;
+		fib_params->tot_len = bpf_ntohs(ip4h->tot_len);
+		fib_params->ipv4_src = ip4h->saddr;
+		fib_params->ipv4_dst = ip4h->daddr;
+	}
+
+	return true;
 }
 
 static __always_inline bool is_remote_ep_v6(struct __sk_buff *skb,
-					    struct in6_addr addr)
+					    struct in6_addr addr,
+					    struct bpf_fib_lookup *fib_params)
 {
 	void *data_end = ctx_ptr(skb->data_end);
 	void *data = ctx_ptr(skb->data);
@@ -75,7 +95,24 @@ static __always_inline bool is_remote_ep_v6(struct __sk_buff *skb,
 	if ((void *)(ip6h + 1) > data_end)
 		return false;
 
-	return v6_equal(ip6h->daddr, addr);
+	if (!v6_equal(ip6h->daddr, addr))
+		return false;
+
+	if (fib_params) {
+		struct in6_addr *src = (struct in6_addr *)fib_params->ipv6_src;
+		struct in6_addr *dst = (struct in6_addr *)fib_params->ipv6_dst;
+
+		fib_params->family = AF_INET6;
+		fib_params->flowinfo = 0;
+		fib_params->l4_protocol = ip6h->nexthdr;
+		fib_params->sport = 0;
+		fib_params->dport = 0;
+		fib_params->tot_len = bpf_ntohs(ip6h->payload_len);
+		*src = ip6h->saddr;
+		*dst = ip6h->daddr;
+	}
+
+	return true;
 }
 
 static __always_inline int get_dev_ifindex(int which)
@@ -99,15 +136,17 @@ SEC("chk_egress") int tc_chk(struct __sk_buff *skb)
 
 SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
 {
+	struct bpf_fib_lookup fib_params = { .ifindex = skb->ingress_ifindex };
 	__u8 zero[ETH_ALEN * 2];
 	bool redirect = false;
+	int ret;
 
 	switch (skb->protocol) {
 	case __bpf_constant_htons(ETH_P_IP):
-		redirect = is_remote_ep_v4(skb, __bpf_constant_htonl(ip4_src));
+		redirect = is_remote_ep_v4(skb, __bpf_constant_htonl(ip4_src), &fib_params);
 		break;
 	case __bpf_constant_htons(ETH_P_IPV6):
-		redirect = is_remote_ep_v6(skb, (struct in6_addr)ip6_src);
+		redirect = is_remote_ep_v6(skb, (struct in6_addr)ip6_src, &fib_params);
 		break;
 	}
 
@@ -118,7 +157,31 @@ SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
 	if (bpf_skb_store_bytes(skb, 0, &zero, sizeof(zero), 0) < 0)
 		return TC_ACT_SHOT;
 
-	return bpf_redirect_neigh(get_dev_ifindex(dev_src), 0);
+	ret = bpf_fib_lookup(skb, &fib_params, sizeof(fib_params), 0);
+	bpf_printk("bpf_fib_lookup() ret: %d\n", ret);
+	if (ret == BPF_FIB_LKUP_RET_SUCCESS) {
+		void *data_end = ctx_ptr(skb->data_end);
+		struct ethhdr *eth = ctx_ptr(skb->data);
+
+		if (eth + 1 > data_end)
+			return TC_ACT_SHOT;
+
+		__builtin_memcpy(eth->h_dest, fib_params.dmac, ETH_ALEN);
+		__builtin_memcpy(eth->h_source, fib_params.smac, ETH_ALEN);
+
+		return bpf_redirect(fib_params.ifindex, 0);
+
+	} else if (ret == BPF_FIB_LKUP_RET_NO_NEIGH) {
+		struct bpf_redir_neigh nh_params = {};
+
+		nh_params.nh_family = fib_params.family;
+		__builtin_memcpy(&nh_params.ipv6_nh, &fib_params.ipv6_dst,
+				 sizeof(nh_params.ipv6_nh));
+
+		return bpf_redirect_neigh(fib_params.ifindex, &nh_params,
+					  sizeof(nh_params), 0);
+	}
+	return TC_ACT_SHOT;
 }
 
 SEC("src_ingress") int tc_src(struct __sk_buff *skb)
@@ -128,10 +191,10 @@ SEC("src_ingress") int tc_src(struct __sk_buff *skb)
 
 	switch (skb->protocol) {
 	case __bpf_constant_htons(ETH_P_IP):
-		redirect = is_remote_ep_v4(skb, __bpf_constant_htonl(ip4_dst));
+		redirect = is_remote_ep_v4(skb, __bpf_constant_htonl(ip4_dst), NULL);
 		break;
 	case __bpf_constant_htons(ETH_P_IPV6):
-		redirect = is_remote_ep_v6(skb, (struct in6_addr)ip6_dst);
+		redirect = is_remote_ep_v6(skb, (struct in6_addr)ip6_dst, NULL);
 		break;
 	}
 
@@ -142,7 +205,7 @@ SEC("src_ingress") int tc_src(struct __sk_buff *skb)
 	if (bpf_skb_store_bytes(skb, 0, &zero, sizeof(zero), 0) < 0)
 		return TC_ACT_SHOT;
 
-	return bpf_redirect_neigh(get_dev_ifindex(dev_dst), 0);
+	return bpf_redirect_neigh(get_dev_ifindex(dev_dst), NULL, 0, 0);
 }
 
 char __license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_tc_redirect.sh b/tools/testing/selftests/bpf/test_tc_redirect.sh
index 6d7482562140..09b20f24d018 100755
--- a/tools/testing/selftests/bpf/test_tc_redirect.sh
+++ b/tools/testing/selftests/bpf/test_tc_redirect.sh
@@ -24,8 +24,7 @@ command -v timeout >/dev/null 2>&1 || \
 	{ echo >&2 "timeout is not available"; exit 1; }
 command -v ping >/dev/null 2>&1 || \
 	{ echo >&2 "ping is not available"; exit 1; }
-command -v ping6 >/dev/null 2>&1 || \
-	{ echo >&2 "ping6 is not available"; exit 1; }
+if command -v ping6 >/dev/null 2>&1; then PING6=ping6; else PING6=ping; fi
 command -v perl >/dev/null 2>&1 || \
 	{ echo >&2 "perl is not available"; exit 1; }
 command -v jq >/dev/null 2>&1 || \
@@ -152,7 +151,7 @@ netns_test_connectivity()
 	echo -e "${TEST}: ${GREEN}PASS${NC}"
 
 	TEST="ICMPv6 connectivity test"
-	ip netns exec ${NS_SRC} ping6 $PING_ARG ${IP6_DST}
+	ip netns exec ${NS_SRC} $PING6 $PING_ARG ${IP6_DST}
 	if [ $? -ne 0 ]; then
 		echo -e "${TEST}: ${RED}FAIL${NC}"
 		exit 1
@@ -179,6 +178,9 @@ netns_setup_bpf()
 	ip netns exec ${NS_FWD} tc filter add dev veth_dst_fwd ingress bpf da obj $obj sec dst_ingress
 	ip netns exec ${NS_FWD} tc filter add dev veth_dst_fwd egress  bpf da obj $obj sec chk_egress
 
+	# bpf_fib_lookup() checks if forwarding is enabled
+	ip netns exec ${NS_FWD} sysctl -w net.ipv4.ip_forward=1 net.ipv6.conf.veth_dst_fwd.forwarding=1
+
 	veth_src=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_src_fwd/ifindex)
 	veth_dst=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_dst_fwd/ifindex)
 


  parent reply	other threads:[~2020-10-15 15:47 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-15 15:46 [PATCH RFC bpf-next 0/2] bpf: Rework bpf_redirect_neigh() to allow supplying nexthop from caller Toke Høiland-Jørgensen
2020-10-15 15:46 ` [PATCH RFC bpf-next 1/2] bpf_redirect_neigh: Support supplying the nexthop as a helper parameter Toke Høiland-Jørgensen
2020-10-15 16:27   ` David Ahern
2020-10-15 19:34     ` Toke Høiland-Jørgensen
2020-10-19 13:09       ` Daniel Borkmann
2020-10-19 13:28         ` Toke Høiland-Jørgensen
2020-10-19 14:48   ` Daniel Borkmann
2020-10-19 14:56     ` Toke Høiland-Jørgensen
2020-10-19 15:01   ` Daniel Borkmann
2020-10-15 15:46 ` Toke Høiland-Jørgensen [this message]
2020-10-19 14:40   ` [PATCH RFC bpf-next 2/2] selftests: Update test_tc_neigh to use the modified bpf_redirect_neigh() Daniel Borkmann
2020-10-19 14:48     ` Toke Høiland-Jørgensen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=160277680973.157904.15451524562795164056.stgit@toke.dk \
    --to=toke@redhat.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=dsahern@kernel.org \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).