Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 
0003 /*
0004  * End-to-end eBPF tunnel test suite
0005  *   The file tests BPF network tunnel implementation.
0006  *
0007  * Topology:
0008  * ---------
0009  *     root namespace   |     at_ns0 namespace
0010  *                       |
0011  *       -----------     |     -----------
0012  *       | tnl dev |     |     | tnl dev |  (overlay network)
0013  *       -----------     |     -----------
0014  *       metadata-mode   |     metadata-mode
0015  *        with bpf       |       with bpf
0016  *                       |
0017  *       ----------      |     ----------
0018  *       |  veth1  | --------- |  veth0  |  (underlay network)
0019  *       ----------    peer    ----------
0020  *
0021  *
0022  *  Device Configuration
0023  *  --------------------
0024  *  root namespace with metadata-mode tunnel + BPF
0025  *  Device names and addresses:
0026  *  veth1 IP 1: 172.16.1.200, IPv6: 00::22 (underlay)
0027  *      IP 2: 172.16.1.20, IPv6: 00::bb (underlay)
0028  *  tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
0029  *
0030  *  Namespace at_ns0 with native tunnel
0031  *  Device names and addresses:
0032  *  veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
0033  *  tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
0034  *
0035  *
0036  * End-to-end ping packet flow
0037  *  ---------------------------
0038  *  Most of the tests start by namespace creation, device configuration,
0039  *  then ping the underlay and overlay network.  When doing 'ping 10.1.1.100'
0040  *  from root namespace, the following operations happen:
0041  *  1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
0042  *  2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
0043  *     with local_ip=172.16.1.200, remote_ip=172.16.1.100. BPF program choose
0044  *     the primary or secondary ip of veth1 as the local ip of tunnel. The
0045  *     choice is made based on the value of bpf map local_ip_map.
0046  *  3) Outer tunnel header is prepended and route the packet to veth1's egress.
0047  *  4) veth0's ingress queue receive the tunneled packet at namespace at_ns0.
0048  *  5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet.
0049  *  6) Forward the packet to the overlay tnl dev.
0050  */
0051 
0052 #include <arpa/inet.h>
0053 #include <linux/if_tun.h>
0054 #include <linux/limits.h>
0055 #include <linux/sysctl.h>
0056 #include <linux/time_types.h>
0057 #include <linux/net_tstamp.h>
0058 #include <net/if.h>
0059 #include <stdbool.h>
0060 #include <stdio.h>
0061 #include <sys/stat.h>
0062 #include <unistd.h>
0063 
0064 #include "test_progs.h"
0065 #include "network_helpers.h"
0066 #include "test_tunnel_kern.skel.h"
0067 
0068 #define IP4_ADDR_VETH0 "172.16.1.100"
0069 #define IP4_ADDR1_VETH1 "172.16.1.200"
0070 #define IP4_ADDR2_VETH1 "172.16.1.20"
0071 #define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
0072 #define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
0073 
0074 #define IP6_ADDR_VETH0 "::11"
0075 #define IP6_ADDR1_VETH1 "::22"
0076 #define IP6_ADDR2_VETH1 "::bb"
0077 
0078 #define IP4_ADDR1_HEX_VETH1 0xac1001c8
0079 #define IP4_ADDR2_HEX_VETH1 0xac100114
0080 #define IP6_ADDR1_HEX_VETH1 0x22
0081 #define IP6_ADDR2_HEX_VETH1 0xbb
0082 
0083 #define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
0084 #define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
0085 #define MAC_VETH1 "52:54:00:d9:03:00"
0086 
0087 #define VXLAN_TUNL_DEV0 "vxlan00"
0088 #define VXLAN_TUNL_DEV1 "vxlan11"
0089 #define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
0090 #define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
0091 
0092 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
0093 
0094 #define SYS(fmt, ...)                       \
0095     ({                          \
0096         char cmd[1024];                 \
0097         snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
0098         if (!ASSERT_OK(system(cmd), cmd))       \
0099             goto fail;              \
0100     })
0101 
0102 #define SYS_NOFAIL(fmt, ...)                    \
0103     ({                          \
0104         char cmd[1024];                 \
0105         snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
0106         system(cmd);                    \
0107     })
0108 
0109 static int config_device(void)
0110 {
0111     SYS("ip netns add at_ns0");
0112     SYS("ip link add veth0 address " MAC_VETH1 " type veth peer name veth1");
0113     SYS("ip link set veth0 netns at_ns0");
0114     SYS("ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
0115     SYS("ip link set dev veth1 up mtu 1500");
0116     SYS("ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
0117     SYS("ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
0118 
0119     return 0;
0120 fail:
0121     return -1;
0122 }
0123 
0124 static void cleanup(void)
0125 {
0126     SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
0127     SYS_NOFAIL("ip link del veth1 2> /dev/null");
0128     SYS_NOFAIL("ip link del %s 2> /dev/null", VXLAN_TUNL_DEV1);
0129     SYS_NOFAIL("ip link del %s 2> /dev/null", IP6VXLAN_TUNL_DEV1);
0130 }
0131 
0132 static int add_vxlan_tunnel(void)
0133 {
0134     /* at_ns0 namespace */
0135     SYS("ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
0136         VXLAN_TUNL_DEV0);
0137     SYS("ip netns exec at_ns0 ip link set dev %s address %s up",
0138         VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
0139     SYS("ip netns exec at_ns0 ip addr add dev %s %s/24",
0140         VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
0141     SYS("ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
0142         IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
0143     SYS("ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0",
0144         IP4_ADDR2_VETH1, MAC_VETH1);
0145 
0146     /* root namespace */
0147     SYS("ip link add dev %s type vxlan external gbp dstport 4789",
0148         VXLAN_TUNL_DEV1);
0149     SYS("ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
0150     SYS("ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
0151     SYS("ip neigh add %s lladdr %s dev %s",
0152         IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
0153 
0154     return 0;
0155 fail:
0156     return -1;
0157 }
0158 
0159 static void delete_vxlan_tunnel(void)
0160 {
0161     SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
0162            VXLAN_TUNL_DEV0);
0163     SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
0164 }
0165 
0166 static int add_ip6vxlan_tunnel(void)
0167 {
0168     SYS("ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
0169         IP6_ADDR_VETH0);
0170     SYS("ip netns exec at_ns0 ip link set dev veth0 up");
0171     SYS("ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
0172     SYS("ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
0173     SYS("ip link set dev veth1 up");
0174 
0175     /* at_ns0 namespace */
0176     SYS("ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
0177         IP6VXLAN_TUNL_DEV0);
0178     SYS("ip netns exec at_ns0 ip addr add dev %s %s/24",
0179         IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
0180     SYS("ip netns exec at_ns0 ip link set dev %s address %s up",
0181         IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
0182 
0183     /* root namespace */
0184     SYS("ip link add dev %s type vxlan external dstport 4789",
0185         IP6VXLAN_TUNL_DEV1);
0186     SYS("ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
0187     SYS("ip link set dev %s address %s up",
0188         IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
0189 
0190     return 0;
0191 fail:
0192     return -1;
0193 }
0194 
0195 static void delete_ip6vxlan_tunnel(void)
0196 {
0197     SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
0198            IP6_ADDR_VETH0);
0199     SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
0200     SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
0201     SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
0202            IP6VXLAN_TUNL_DEV0);
0203     SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
0204 }
0205 
0206 static int test_ping(int family, const char *addr)
0207 {
0208     SYS("%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
0209     return 0;
0210 fail:
0211     return -1;
0212 }
0213 
0214 static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
0215 {
0216     DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
0217                 .priority = 1, .prog_fd = igr_fd);
0218     DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
0219                 .priority = 1, .prog_fd = egr_fd);
0220     int ret;
0221 
0222     ret = bpf_tc_hook_create(hook);
0223     if (!ASSERT_OK(ret, "create tc hook"))
0224         return ret;
0225 
0226     if (igr_fd >= 0) {
0227         hook->attach_point = BPF_TC_INGRESS;
0228         ret = bpf_tc_attach(hook, &opts1);
0229         if (!ASSERT_OK(ret, "bpf_tc_attach")) {
0230             bpf_tc_hook_destroy(hook);
0231             return ret;
0232         }
0233     }
0234 
0235     if (egr_fd >= 0) {
0236         hook->attach_point = BPF_TC_EGRESS;
0237         ret = bpf_tc_attach(hook, &opts2);
0238         if (!ASSERT_OK(ret, "bpf_tc_attach")) {
0239             bpf_tc_hook_destroy(hook);
0240             return ret;
0241         }
0242     }
0243 
0244     return 0;
0245 }
0246 
0247 static void test_vxlan_tunnel(void)
0248 {
0249     struct test_tunnel_kern *skel = NULL;
0250     struct nstoken *nstoken;
0251     int local_ip_map_fd = -1;
0252     int set_src_prog_fd, get_src_prog_fd;
0253     int set_dst_prog_fd;
0254     int key = 0, ifindex = -1;
0255     uint local_ip;
0256     int err;
0257     DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
0258                 .attach_point = BPF_TC_INGRESS);
0259 
0260     /* add vxlan tunnel */
0261     err = add_vxlan_tunnel();
0262     if (!ASSERT_OK(err, "add vxlan tunnel"))
0263         goto done;
0264 
0265     /* load and attach bpf prog to tunnel dev tc hook point */
0266     skel = test_tunnel_kern__open_and_load();
0267     if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
0268         goto done;
0269     ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
0270     if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
0271         goto done;
0272     tc_hook.ifindex = ifindex;
0273     get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
0274     set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
0275     if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
0276         goto done;
0277     if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
0278         goto done;
0279     if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
0280         goto done;
0281 
0282     /* load and attach bpf prog to veth dev tc hook point */
0283     ifindex = if_nametoindex("veth1");
0284     if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex"))
0285         goto done;
0286     tc_hook.ifindex = ifindex;
0287     set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst);
0288     if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
0289         goto done;
0290     if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1))
0291         goto done;
0292 
0293     /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
0294     nstoken = open_netns("at_ns0");
0295     if (!ASSERT_OK_PTR(nstoken, "setns src"))
0296         goto done;
0297     ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
0298     if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
0299         goto done;
0300     tc_hook.ifindex = ifindex;
0301     set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
0302     if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
0303         goto done;
0304     if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
0305         goto done;
0306     close_netns(nstoken);
0307 
0308     /* use veth1 ip 2 as tunnel source ip */
0309     local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
0310     if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
0311         goto done;
0312     local_ip = IP4_ADDR2_HEX_VETH1;
0313     err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
0314     if (!ASSERT_OK(err, "update bpf local_ip_map"))
0315         goto done;
0316 
0317     /* ping test */
0318     err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
0319     if (!ASSERT_OK(err, "test_ping"))
0320         goto done;
0321 
0322 done:
0323     /* delete vxlan tunnel */
0324     delete_vxlan_tunnel();
0325     if (local_ip_map_fd >= 0)
0326         close(local_ip_map_fd);
0327     if (skel)
0328         test_tunnel_kern__destroy(skel);
0329 }
0330 
0331 static void test_ip6vxlan_tunnel(void)
0332 {
0333     struct test_tunnel_kern *skel = NULL;
0334     struct nstoken *nstoken;
0335     int local_ip_map_fd = -1;
0336     int set_src_prog_fd, get_src_prog_fd;
0337     int set_dst_prog_fd;
0338     int key = 0, ifindex = -1;
0339     uint local_ip;
0340     int err;
0341     DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
0342                 .attach_point = BPF_TC_INGRESS);
0343 
0344     /* add vxlan tunnel */
0345     err = add_ip6vxlan_tunnel();
0346     if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
0347         goto done;
0348 
0349     /* load and attach bpf prog to tunnel dev tc hook point */
0350     skel = test_tunnel_kern__open_and_load();
0351     if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
0352         goto done;
0353     ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
0354     if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
0355         goto done;
0356     tc_hook.ifindex = ifindex;
0357     get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
0358     set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
0359     if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
0360         goto done;
0361     if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
0362         goto done;
0363     if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
0364         goto done;
0365 
0366     /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
0367     nstoken = open_netns("at_ns0");
0368     if (!ASSERT_OK_PTR(nstoken, "setns src"))
0369         goto done;
0370     ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
0371     if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
0372         goto done;
0373     tc_hook.ifindex = ifindex;
0374     set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
0375     if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
0376         goto done;
0377     if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
0378         goto done;
0379     close_netns(nstoken);
0380 
0381     /* use veth1 ip 2 as tunnel source ip */
0382     local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
0383     if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
0384         goto done;
0385     local_ip = IP6_ADDR2_HEX_VETH1;
0386     err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
0387     if (!ASSERT_OK(err, "update bpf local_ip_map"))
0388         goto done;
0389 
0390     /* ping test */
0391     err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
0392     if (!ASSERT_OK(err, "test_ping"))
0393         goto done;
0394 
0395 done:
0396     /* delete ipv6 vxlan tunnel */
0397     delete_ip6vxlan_tunnel();
0398     if (local_ip_map_fd >= 0)
0399         close(local_ip_map_fd);
0400     if (skel)
0401         test_tunnel_kern__destroy(skel);
0402 }
0403 
0404 #define RUN_TEST(name)                          \
0405     ({                              \
0406         if (test__start_subtest(#name)) {           \
0407             test_ ## name();                \
0408         }                           \
0409     })
0410 
0411 static void *test_tunnel_run_tests(void *arg)
0412 {
0413     cleanup();
0414     config_device();
0415 
0416     RUN_TEST(vxlan_tunnel);
0417     RUN_TEST(ip6vxlan_tunnel);
0418 
0419     cleanup();
0420 
0421     return NULL;
0422 }
0423 
0424 void serial_test_tunnel(void)
0425 {
0426     pthread_t test_thread;
0427     int err;
0428 
0429     /* Run the tests in their own thread to isolate the namespace changes
0430      * so they do not affect the environment of other tests.
0431      * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
0432      */
0433     err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
0434     if (ASSERT_OK(err, "pthread_create"))
0435         ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
0436 }