From: Yan Zhai <yan@cloudflare.com>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>, Yonghong Song <yhs@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@kernel.org>,
Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>,
Jiri Olsa <jolsa@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Mykola Lysenko <mykolal@fb.com>, Shuah Khan <shuah@kernel.org>,
Yan Zhai <yan@cloudflare.com>,
linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
linux-kselftest@vger.kernel.org, kernel-team@cloudflare.com,
Jordan Griege <jgriege@cloudflare.com>,
Markus Elfring <Markus.Elfring@web.de>,
Jakub Sitnicki <jakub@cloudflare.com>
Subject: [PATCH v4 bpf 2/2] bpf: selftests: add lwt redirect regression test cases
Date: Tue, 25 Jul 2023 18:09:12 -0700 [thread overview]
Message-ID: <9c4896b109a39c3fa088844addaa1737a84bbbb5.1690332693.git.yan@cloudflare.com> (raw)
In-Reply-To: <cover.1690332693.git.yan@cloudflare.com>
Tests BPF redirect at the lwt xmit hook to ensure error handling are
safe, i.e. won't panic the kernel.
Tested-by: Jakub Sitnicki <jakub@cloudflare.com>
Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Signed-off-by: Yan Zhai <yan@cloudflare.com>
---
tools/testing/selftests/bpf/Makefile | 1 +
.../selftests/bpf/progs/test_lwt_redirect.c | 66 +++++++
.../selftests/bpf/test_lwt_redirect.sh | 174 ++++++++++++++++++
3 files changed, 241 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/test_lwt_redirect.c
create mode 100755 tools/testing/selftests/bpf/test_lwt_redirect.sh
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 538df8fb8c42..e3a24d053793 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -66,6 +66,7 @@ TEST_PROGS := test_kmod.sh \
test_xdp_vlan_mode_generic.sh \
test_xdp_vlan_mode_native.sh \
test_lwt_ip_encap.sh \
+ test_lwt_redirect.sh \
test_tcp_check_syncookie.sh \
test_tc_tunnel.sh \
test_tc_edt.sh \
diff --git a/tools/testing/selftests/bpf/progs/test_lwt_redirect.c b/tools/testing/selftests/bpf/progs/test_lwt_redirect.c
new file mode 100644
index 000000000000..3674e101f68f
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_lwt_redirect.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_tracing_net.h"
+
+/* We don't care about whether the packet can be received by network stack.
+ * Just care if the packet is sent to the correct device at correct direction
+ * and not panic the kernel.
+ */
+static __always_inline int prepend_dummy_mac(struct __sk_buff *skb)
+{
+ char mac[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0xf,
+ 0xe, 0xd, 0xc, 0xb, 0xa, 0x08, 0x00};
+
+ if (bpf_skb_change_head(skb, ETH_HLEN, 0)) {
+ bpf_printk("%s: fail to change head", __func__);
+ return -1;
+ }
+
+ if (bpf_skb_store_bytes(skb, 0, mac, sizeof(mac), 0)) {
+ bpf_printk("%s: fail to update mac", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+SEC("redir_ingress")
+int test_lwt_redirect_in(struct __sk_buff *skb)
+{
+ if (prepend_dummy_mac(skb))
+ return BPF_DROP;
+
+ bpf_printk("Redirect skb to link %d ingress", skb->mark);
+ return bpf_redirect(skb->mark, BPF_F_INGRESS);
+}
+
+SEC("redir_egress")
+int test_lwt_redirect_out(struct __sk_buff *skb)
+{
+ if (prepend_dummy_mac(skb))
+ return BPF_DROP;
+
+ bpf_printk("Redirect skb to link %d egress", skb->mark);
+ return bpf_redirect(skb->mark, 0);
+}
+
+SEC("redir_egress_nomac")
+int test_lwt_redirect_out_nomac(struct __sk_buff *skb)
+{
+ int ret = bpf_redirect(skb->mark, 0);
+
+ bpf_printk("Redirect skb to link %d egress nomac: %d", skb->mark, ret);
+ return ret;
+}
+
+SEC("redir_ingress_nomac")
+int test_lwt_redirect_in_nomac(struct __sk_buff *skb)
+{
+ int ret = bpf_redirect(skb->mark, BPF_F_INGRESS);
+
+ bpf_printk("Redirect skb to link %d ingress nomac: %d", skb->mark, ret);
+ return ret;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_lwt_redirect.sh b/tools/testing/selftests/bpf/test_lwt_redirect.sh
new file mode 100755
index 000000000000..1b7b78b48174
--- /dev/null
+++ b/tools/testing/selftests/bpf/test_lwt_redirect.sh
@@ -0,0 +1,174 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# This regression test checks basic lwt redirect functionality,
+# making sure the kernel would not crash when redirecting packets
+# to a device, regardless its administration state:
+#
+# 1. redirect to a device egress/ingress should work normally
+# 2. redirect to a device egress/ingress should not panic when target is down
+# 3. redirect to a device egress/ingress should not panic when target carrier is down
+#
+# All test setup are simple: redirect ping packet via lwt xmit to cover above
+# situations. We do not worry about specific device type, except for the two
+# categories of devices that require MAC header and not require MAC header. For
+# carrier down situation, we use a vlan device as upper link, and bring down its
+# lower device.
+#
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+BPF_FILE="test_lwt_redirect.bpf.o"
+INGRESS_REDIR_IP=2.2.2.2
+EGRESS_REDIR_IP=3.3.3.3
+INGRESS_REDIR_IP_NOMAC=4.4.4.4
+EGRESS_REDIR_IP_NOMAC=5.5.5.5
+PASS=0
+FAIL=0
+
+readonly NS1="ns1-$(mktemp -u XXXXXX)"
+
+msg="skip all tests:"
+if [ $UID != 0 ]; then
+ echo $msg please run this as root >&2
+ exit $ksft_skip
+fi
+
+get_ip_direction()
+{
+ case $1 in
+ $INGRESS_REDIR_IP|$INGRESS_REDIR_IP_NOMAC)
+ echo ingress
+ ;;
+ $EGRESS_REDIR_IP|$EGRESS_REDIR_IP_NOMAC)
+ echo egress
+ ;;
+ *)
+ echo bug
+ ;;
+ esac
+}
+
+test_pass()
+{
+ local testname=$1
+ local direction=`get_ip_direction $2`
+ shift 2
+ echo "Pass: $testname $direction $@"
+ PASS=$((PASS + 1))
+}
+
+test_fail()
+{
+ local testname=$1
+ local direction=`get_ip_direction $2`
+ shift 2
+ echo "Fail: $testname $direction $@"
+ FAIL=$((FAIL + 1))
+}
+
+setup()
+{
+ ip netns add $NS1
+
+ ip -n $NS1 link set lo up
+ ip -n $NS1 link add link_err type dummy
+ ip -n $NS1 link add link_w_mac type dummy
+ ip -n $NS1 link add link link_w_mac link_upper type vlan id 1
+ ip -n $NS1 link add link_wo_mac type gre remote 4.3.2.1 local 1.2.3.4
+ ip -n $NS1 link set link_err up
+ ip -n $NS1 link set link_w_mac up
+ ip -n $NS1 link set link_upper up
+ ip -n $NS1 link set link_wo_mac up
+
+ ip -n $NS1 addr add dev lo 1.1.1.1/32
+
+ # link_err is only used to make sure packets are redirected instead of
+ # being routed
+ ip -n $NS1 route add $INGRESS_REDIR_IP encap bpf xmit \
+ obj $BPF_FILE sec redir_ingress dev link_err
+ ip -n $NS1 route add $EGRESS_REDIR_IP encap bpf xmit \
+ obj $BPF_FILE sec redir_egress dev link_err
+ ip -n $NS1 route add $INGRESS_REDIR_IP_NOMAC encap bpf xmit \
+ obj $BPF_FILE sec redir_ingress_nomac dev link_err
+ ip -n $NS1 route add $EGRESS_REDIR_IP_NOMAC encap bpf xmit \
+ obj $BPF_FILE sec redir_egress_nomac dev link_err
+}
+
+cleanup_and_summary()
+{
+ ip netns del $NS1
+ echo PASSED:$PASS FAILED:$FAIL
+ if [ $FAIL -ne 0 ]; then
+ exit 1
+ else
+ exit 0
+ fi
+}
+
+test_redirect_normal()
+{
+ local test_name=${FUNCNAME[0]}
+ local link_name=$1
+ local link_id=`ip netns exec $NS1 cat /sys/class/net/${link_name}/ifindex`
+ local dest=$2
+
+ ip netns exec $NS1 timeout 2 tcpdump -i ${link_name} -c 1 -n -p icmp >/dev/null 2>&1 &
+ local jobid=$!
+ sleep 1
+
+ # hack: mark indicates the link to redirect to
+ ip netns exec $NS1 ping -m $link_id $dest -c 1 -w 1 > /dev/null 2>&1
+ wait $jobid
+
+ if [ $? -ne 0 ]; then
+ test_fail $test_name $dest $link_name
+ else
+ test_pass $test_name $dest $link_name
+ fi
+}
+
+test_redirect_no_panic_on_link_down()
+{
+ local test_name=${FUNCNAME[0]}
+ local link_name=$1
+ local link_id=`ip netns exec $NS1 cat /sys/class/net/${link_name}/ifindex`
+ local dest=$2
+
+ ip -n $NS1 link set $link_name down
+ # hack: mark indicates the link to redirect to
+ ip netns exec $NS1 ping -m $link_id $dest -c 1 -w 1 >/dev/null 2>&1
+
+ test_pass $test_name $dest to $link_name
+ ip -n $NS1 link set $link_name up
+}
+
+test_redirect_no_panic_on_link_carrier_down()
+{
+ local test_name=${FUNCNAME[0]}
+ local link_id=`ip netns exec $NS1 cat /sys/class/net/link_upper/ifindex`
+ local dest=$1
+
+ ip -n $NS1 link set link_w_mac down
+ # hack: mark indicates the link to redirect to
+ ip netns exec $NS1 ping -m $link_id $dest -c 1 -w 1 >/dev/null 2>&1
+
+ test_pass $test_name $dest to link_upper
+ ip -n $NS1 link set link_w_mac up
+}
+
+setup
+
+echo "Testing lwt redirect to devices requiring MAC header"
+for dest in $INGRESS_REDIR_IP $EGRESS_REDIR_IP; do
+ test_redirect_normal link_w_mac $dest
+ test_redirect_no_panic_on_link_down link_w_mac $dest
+ test_redirect_no_panic_on_link_carrier_down $dest
+done
+
+echo "Testing lwt redirect to devices not requiring MAC header"
+for dest in $INGRESS_REDIR_IP_NOMAC $EGRESS_REDIR_IP_NOMAC; do
+ test_redirect_normal link_wo_mac $dest
+ test_redirect_no_panic_on_link_down link_wo_mac $dest
+done
+
+cleanup_and_summary
--
2.30.2
next prev parent reply other threads:[~2023-07-26 1:09 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-26 1:07 [PATCH v4 bpf 0/2] bpf: return proper error codes for lwt redirect Yan Zhai
2023-07-26 1:08 ` [PATCH v4 bpf 1/2] bpf: fix skb_do_redirect return values Yan Zhai
2023-07-26 12:25 ` Jakub Sitnicki
2023-07-26 13:39 ` Dan Carpenter
2023-07-26 14:14 ` Yan Zhai
2023-07-26 15:01 ` Dan Carpenter
2023-07-26 16:10 ` Yan Zhai
2023-07-26 16:53 ` Dan Carpenter
2023-07-31 14:26 ` Dan Carpenter
2023-08-01 22:18 ` Yan Zhai
2023-07-28 22:02 ` Martin KaFai Lau
2023-07-31 21:35 ` Yan Zhai
2023-07-31 22:11 ` Martin KaFai Lau
2023-07-31 23:01 ` Yan Zhai
2023-07-31 23:52 ` Martin KaFai Lau
2023-07-26 1:09 ` Yan Zhai [this message]
[not found] ` <3ec61192-c65c-62cc-d073-d6111b08e690@web.de>
[not found] ` <CAO3-PbraNcfQnqHUG_992vssuA795RxtexYsMdEo=k9zp-XHog@mail.gmail.com>
2023-07-26 10:30 ` [PATCH v4 bpf 2/2] bpf: selftests: add lwt redirect regression test cases Yan Zhai
2023-07-26 13:22 ` Dan Carpenter
2023-07-26 12:26 ` Jakub Sitnicki
2023-07-28 22:47 ` Martin KaFai Lau
2023-07-31 9:48 ` Jakub Sitnicki
2023-07-31 18:46 ` Alexei Starovoitov
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=9c4896b109a39c3fa088844addaa1737a84bbbb5.1690332693.git.yan@cloudflare.com \
--to=yan@cloudflare.com \
--cc=Markus.Elfring@web.de \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=haoluo@google.com \
--cc=jakub@cloudflare.com \
--cc=jgriege@cloudflare.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kernel-team@cloudflare.com \
--cc=kpsingh@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=mykolal@fb.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@google.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yhs@fb.com \
/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
all inboxes | Powered by JetHome®