bpf: selftests: Move xfrm tunnel test to test_progs
authorDaniel Xu <dxu@dxuuu.xyz>
Thu, 14 Dec 2023 22:49:05 +0000 (15:49 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 15 Dec 2023 01:12:49 +0000 (17:12 -0800)
test_progs is better than a shell script b/c C is a bit easier to
maintain than shell. Also it's easier to use new infra like memory
mapped global variables from C via bpf skeleton.

Co-developed-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
Link: https://lore.kernel.org/r/a350db9e08520c64544562d88ec005a039124d9b.1702593901.git.dxu@dxuuu.xyz
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/test_tunnel.c
tools/testing/selftests/bpf/progs/test_tunnel_kern.c
tools/testing/selftests/bpf/test_tunnel.sh

index b57d48219d0b4e2f93c09679cf071fa3b698427e..2d7f8fa82ebd32832330001e01ced6d217364e31 100644 (file)
@@ -50,6 +50,7 @@
  */
 
 #include <arpa/inet.h>
+#include <linux/if_link.h>
 #include <linux/if_tun.h>
 #include <linux/limits.h>
 #include <linux/sysctl.h>
 #define IPIP_TUNL_DEV0 "ipip00"
 #define IPIP_TUNL_DEV1 "ipip11"
 
+#define XFRM_AUTH "0x1111111111111111111111111111111111111111"
+#define XFRM_ENC "0x22222222222222222222222222222222"
+#define XFRM_SPI_IN_TO_OUT 0x1
+#define XFRM_SPI_OUT_TO_IN 0x2
+
 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
 
 static int config_device(void)
@@ -264,6 +270,92 @@ static void delete_ipip_tunnel(void)
        SYS_NOFAIL("ip fou del port 5555 2> /dev/null");
 }
 
+static int add_xfrm_tunnel(void)
+{
+       /* at_ns0 namespace
+        * at_ns0 -> root
+        */
+       SYS(fail,
+           "ip netns exec at_ns0 "
+               "ip xfrm state add src %s dst %s proto esp "
+                       "spi %d reqid 1 mode tunnel "
+                       "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
+           IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
+       SYS(fail,
+           "ip netns exec at_ns0 "
+               "ip xfrm policy add src %s/32 dst %s/32 dir out "
+                       "tmpl src %s dst %s proto esp reqid 1 "
+                       "mode tunnel",
+           IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
+
+       /* root -> at_ns0 */
+       SYS(fail,
+           "ip netns exec at_ns0 "
+               "ip xfrm state add src %s dst %s proto esp "
+                       "spi %d reqid 2 mode tunnel "
+                       "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s",
+           IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
+       SYS(fail,
+           "ip netns exec at_ns0 "
+               "ip xfrm policy add src %s/32 dst %s/32 dir in "
+                       "tmpl src %s dst %s proto esp reqid 2 "
+                       "mode tunnel",
+           IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
+
+       /* address & route */
+       SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32",
+           IP4_ADDR_TUNL_DEV0);
+       SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s",
+           IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0);
+
+       /* root namespace
+        * at_ns0 -> root
+        */
+       SYS(fail,
+           "ip xfrm state add src %s dst %s proto esp "
+                   "spi %d reqid 1 mode tunnel "
+                   "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
+           IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC);
+       SYS(fail,
+           "ip xfrm policy add src %s/32 dst %s/32 dir in "
+                   "tmpl src %s dst %s proto esp reqid 1 "
+                   "mode tunnel",
+           IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1);
+
+       /* root -> at_ns0 */
+       SYS(fail,
+           "ip xfrm state add src %s dst %s proto esp "
+                   "spi %d reqid 2 mode tunnel "
+                   "auth-trunc 'hmac(sha1)' %s 96  enc 'cbc(aes)' %s",
+           IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC);
+       SYS(fail,
+           "ip xfrm policy add src %s/32 dst %s/32 dir out "
+                   "tmpl src %s dst %s proto esp reqid 2 "
+                   "mode tunnel",
+           IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0);
+
+       /* address & route */
+       SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1);
+       SYS(fail, "ip route add %s dev veth1 via %s src %s",
+           IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1);
+
+       return 0;
+fail:
+       return -1;
+}
+
+static void delete_xfrm_tunnel(void)
+{
+       SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32 2> /dev/null",
+                  IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0);
+       SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32 2> /dev/null",
+                  IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1);
+       SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d 2> /dev/null",
+                  IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT);
+       SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d 2> /dev/null",
+                  IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN);
+}
+
 static int test_ping(int family, const char *addr)
 {
        SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
@@ -532,6 +624,56 @@ done:
                test_tunnel_kern__destroy(skel);
 }
 
+static void test_xfrm_tunnel(void)
+{
+       DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
+                           .attach_point = BPF_TC_INGRESS);
+       struct test_tunnel_kern *skel = NULL;
+       struct nstoken *nstoken;
+       int tc_prog_fd;
+       int ifindex;
+       int err;
+
+       err = add_xfrm_tunnel();
+       if (!ASSERT_OK(err, "add_xfrm_tunnel"))
+               return;
+
+       skel = test_tunnel_kern__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
+               goto done;
+
+       ifindex = if_nametoindex("veth1");
+       if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
+               goto done;
+
+       /* attach tc prog to tunnel dev */
+       tc_hook.ifindex = ifindex;
+       tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state);
+       if (!ASSERT_GE(tc_prog_fd, 0, "bpf_program__fd"))
+               goto done;
+       if (attach_tc_prog(&tc_hook, tc_prog_fd, -1))
+               goto done;
+
+       /* ping from at_ns0 namespace test */
+       nstoken = open_netns("at_ns0");
+       err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1);
+       close_netns(nstoken);
+       if (!ASSERT_OK(err, "test_ping"))
+               goto done;
+
+       if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id"))
+               goto done;
+       if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi"))
+               goto done;
+       if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip"))
+               goto done;
+
+done:
+       delete_xfrm_tunnel();
+       if (skel)
+               test_tunnel_kern__destroy(skel);
+}
+
 #define RUN_TEST(name, ...)                                            \
        ({                                                              \
                if (test__start_subtest(#name)) {                       \
@@ -548,6 +690,7 @@ static void *test_tunnel_run_tests(void *arg)
        RUN_TEST(ipip_tunnel, NONE);
        RUN_TEST(ipip_tunnel, FOU);
        RUN_TEST(ipip_tunnel, GUE);
+       RUN_TEST(xfrm_tunnel);
 
        return NULL;
 }
index b320fb7bb080faf2da98dec3e1388d4de3fa230b..3a59eb9c34de23a1e40dab96000987ce6610073b 100644 (file)
@@ -929,6 +929,10 @@ int ip6ip6_get_tunnel(struct __sk_buff *skb)
        return TC_ACT_OK;
 }
 
+volatile int xfrm_reqid = 0;
+volatile int xfrm_spi = 0;
+volatile int xfrm_remote_ip = 0;
+
 SEC("tc")
 int xfrm_get_state(struct __sk_buff *skb)
 {
@@ -939,9 +943,10 @@ int xfrm_get_state(struct __sk_buff *skb)
        if (ret < 0)
                return TC_ACT_OK;
 
-       bpf_printk("reqid %d spi 0x%x remote ip 0x%x\n",
-                  x.reqid, bpf_ntohl(x.spi),
-                  bpf_ntohl(x.remote_ipv4));
+       xfrm_reqid = x.reqid;
+       xfrm_spi = bpf_ntohl(x.spi);
+       xfrm_remote_ip = bpf_ntohl(x.remote_ipv4);
+
        return TC_ACT_OK;
 }
 
index 2dec7dbf29a27b252e3200896b7235cd77a63864..d9661b9988ba907e023ef9bc58d96a0155f58326 100755 (executable)
@@ -517,90 +517,6 @@ test_ip6ip6()
         echo -e ${GREEN}"PASS: ip6$TYPE"${NC}
 }
 
-setup_xfrm_tunnel()
-{
-       auth=0x$(printf '1%.0s' {1..40})
-       enc=0x$(printf '2%.0s' {1..32})
-       spi_in_to_out=0x1
-       spi_out_to_in=0x2
-       # at_ns0 namespace
-       # at_ns0 -> root
-       ip netns exec at_ns0 \
-               ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \
-                       spi $spi_in_to_out reqid 1 mode tunnel \
-                       auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
-       ip netns exec at_ns0 \
-               ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir out \
-               tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
-               mode tunnel
-       # root -> at_ns0
-       ip netns exec at_ns0 \
-               ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
-                       spi $spi_out_to_in reqid 2 mode tunnel \
-                       auth-trunc 'hmac(sha1)' $auth 96 enc 'cbc(aes)' $enc
-       ip netns exec at_ns0 \
-               ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir in \
-               tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \
-               mode tunnel
-       # address & route
-       ip netns exec at_ns0 \
-               ip addr add dev veth0 10.1.1.100/32
-       ip netns exec at_ns0 \
-               ip route add 10.1.1.200 dev veth0 via 172.16.1.200 \
-                       src 10.1.1.100
-
-       # root namespace
-       # at_ns0 -> root
-       ip xfrm state add src 172.16.1.100 dst 172.16.1.200 proto esp \
-               spi $spi_in_to_out reqid 1 mode tunnel \
-               auth-trunc 'hmac(sha1)' $auth 96  enc 'cbc(aes)' $enc
-       ip xfrm policy add src 10.1.1.100/32 dst 10.1.1.200/32 dir in \
-               tmpl src 172.16.1.100 dst 172.16.1.200 proto esp reqid 1 \
-               mode tunnel
-       # root -> at_ns0
-       ip xfrm state add src 172.16.1.200 dst 172.16.1.100 proto esp \
-               spi $spi_out_to_in reqid 2 mode tunnel \
-               auth-trunc 'hmac(sha1)' $auth 96  enc 'cbc(aes)' $enc
-       ip xfrm policy add src 10.1.1.200/32 dst 10.1.1.100/32 dir out \
-               tmpl src 172.16.1.200 dst 172.16.1.100 proto esp reqid 2 \
-               mode tunnel
-       # address & route
-       ip addr add dev veth1 10.1.1.200/32
-       ip route add 10.1.1.100 dev veth1 via 172.16.1.100 src 10.1.1.200
-}
-
-test_xfrm_tunnel()
-{
-       if [[ -e /sys/kernel/tracing/trace ]]; then
-               TRACE=/sys/kernel/tracing/trace
-       else
-               TRACE=/sys/kernel/debug/tracing/trace
-       fi
-       config_device
-       > ${TRACE}
-       setup_xfrm_tunnel
-       mkdir -p ${BPF_PIN_TUNNEL_DIR}
-       bpftool prog loadall ${BPF_FILE} ${BPF_PIN_TUNNEL_DIR}
-       tc qdisc add dev veth1 clsact
-       tc filter add dev veth1 proto ip ingress bpf da object-pinned \
-               ${BPF_PIN_TUNNEL_DIR}/xfrm_get_state
-       ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
-       sleep 1
-       grep "reqid 1" ${TRACE}
-       check_err $?
-       grep "spi 0x1" ${TRACE}
-       check_err $?
-       grep "remote ip 0xac100164" ${TRACE}
-       check_err $?
-       cleanup
-
-       if [ $ret -ne 0 ]; then
-               echo -e ${RED}"FAIL: xfrm tunnel"${NC}
-               return 1
-       fi
-       echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
-}
-
 attach_bpf()
 {
        DEV=$1
@@ -630,10 +546,6 @@ cleanup()
        ip link del ip6geneve11 2> /dev/null
        ip link del erspan11 2> /dev/null
        ip link del ip6erspan11 2> /dev/null
-       ip xfrm policy delete dir out src 10.1.1.200/32 dst 10.1.1.100/32 2> /dev/null
-       ip xfrm policy delete dir in src 10.1.1.100/32 dst 10.1.1.200/32 2> /dev/null
-       ip xfrm state delete src 172.16.1.100 dst 172.16.1.200 proto esp spi 0x1 2> /dev/null
-       ip xfrm state delete src 172.16.1.200 dst 172.16.1.100 proto esp spi 0x2 2> /dev/null
 }
 
 cleanup_exit()
@@ -716,10 +628,6 @@ bpf_tunnel_test()
        test_ip6ip6
        errors=$(( $errors + $? ))
 
-       echo "Testing IPSec tunnel..."
-       test_xfrm_tunnel
-       errors=$(( $errors + $? ))
-
        return $errors
 }