cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

test_tunnel.c (12838B)


      1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
      2
      3/*
      4 * End-to-end eBPF tunnel test suite
      5 *   The file tests BPF network tunnel implementation.
      6 *
      7 * Topology:
      8 * ---------
      9 *     root namespace   |     at_ns0 namespace
     10 *                       |
     11 *       -----------     |     -----------
     12 *       | tnl dev |     |     | tnl dev |  (overlay network)
     13 *       -----------     |     -----------
     14 *       metadata-mode   |     metadata-mode
     15 *        with bpf       |       with bpf
     16 *                       |
     17 *       ----------      |     ----------
     18 *       |  veth1  | --------- |  veth0  |  (underlay network)
     19 *       ----------    peer    ----------
     20 *
     21 *
     22 *  Device Configuration
     23 *  --------------------
     24 *  root namespace with metadata-mode tunnel + BPF
     25 *  Device names and addresses:
     26 *	veth1 IP 1: 172.16.1.200, IPv6: 00::22 (underlay)
     27 *		IP 2: 172.16.1.20, IPv6: 00::bb (underlay)
     28 *	tunnel dev <type>11, ex: gre11, IPv4: 10.1.1.200, IPv6: 1::22 (overlay)
     29 *
     30 *  Namespace at_ns0 with native tunnel
     31 *  Device names and addresses:
     32 *	veth0 IPv4: 172.16.1.100, IPv6: 00::11 (underlay)
     33 *	tunnel dev <type>00, ex: gre00, IPv4: 10.1.1.100, IPv6: 1::11 (overlay)
     34 *
     35 *
     36 * End-to-end ping packet flow
     37 *  ---------------------------
     38 *  Most of the tests start by namespace creation, device configuration,
     39 *  then ping the underlay and overlay network.  When doing 'ping 10.1.1.100'
     40 *  from root namespace, the following operations happen:
     41 *  1) Route lookup shows 10.1.1.100/24 belongs to tnl dev, fwd to tnl dev.
     42 *  2) Tnl device's egress BPF program is triggered and set the tunnel metadata,
     43 *     with local_ip=172.16.1.200, remote_ip=172.16.1.100. BPF program choose
     44 *     the primary or secondary ip of veth1 as the local ip of tunnel. The
     45 *     choice is made based on the value of bpf map local_ip_map.
     46 *  3) Outer tunnel header is prepended and route the packet to veth1's egress.
     47 *  4) veth0's ingress queue receive the tunneled packet at namespace at_ns0.
     48 *  5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet.
     49 *  6) Forward the packet to the overlay tnl dev.
     50 */
     51
     52#include <arpa/inet.h>
     53#include <linux/if_tun.h>
     54#include <linux/limits.h>
     55#include <linux/sysctl.h>
     56#include <linux/time_types.h>
     57#include <linux/net_tstamp.h>
     58#include <net/if.h>
     59#include <stdbool.h>
     60#include <stdio.h>
     61#include <sys/stat.h>
     62#include <unistd.h>
     63
     64#include "test_progs.h"
     65#include "network_helpers.h"
     66#include "test_tunnel_kern.skel.h"
     67
     68#define IP4_ADDR_VETH0 "172.16.1.100"
     69#define IP4_ADDR1_VETH1 "172.16.1.200"
     70#define IP4_ADDR2_VETH1 "172.16.1.20"
     71#define IP4_ADDR_TUNL_DEV0 "10.1.1.100"
     72#define IP4_ADDR_TUNL_DEV1 "10.1.1.200"
     73
     74#define IP6_ADDR_VETH0 "::11"
     75#define IP6_ADDR1_VETH1 "::22"
     76#define IP6_ADDR2_VETH1 "::bb"
     77
     78#define IP4_ADDR1_HEX_VETH1 0xac1001c8
     79#define IP4_ADDR2_HEX_VETH1 0xac100114
     80#define IP6_ADDR1_HEX_VETH1 0x22
     81#define IP6_ADDR2_HEX_VETH1 0xbb
     82
     83#define MAC_TUNL_DEV0 "52:54:00:d9:01:00"
     84#define MAC_TUNL_DEV1 "52:54:00:d9:02:00"
     85
     86#define VXLAN_TUNL_DEV0 "vxlan00"
     87#define VXLAN_TUNL_DEV1 "vxlan11"
     88#define IP6VXLAN_TUNL_DEV0 "ip6vxlan00"
     89#define IP6VXLAN_TUNL_DEV1 "ip6vxlan11"
     90
     91#define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
     92
     93#define SYS(fmt, ...)						\
     94	({							\
     95		char cmd[1024];					\
     96		snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__);	\
     97		if (!ASSERT_OK(system(cmd), cmd))		\
     98			goto fail;				\
     99	})
    100
    101#define SYS_NOFAIL(fmt, ...)					\
    102	({							\
    103		char cmd[1024];					\
    104		snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__);	\
    105		system(cmd);					\
    106	})
    107
    108static int config_device(void)
    109{
    110	SYS("ip netns add at_ns0");
    111	SYS("ip link add veth0 type veth peer name veth1");
    112	SYS("ip link set veth0 netns at_ns0");
    113	SYS("ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1");
    114	SYS("ip addr add " IP4_ADDR2_VETH1 "/24 dev veth1");
    115	SYS("ip link set dev veth1 up mtu 1500");
    116	SYS("ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0");
    117	SYS("ip netns exec at_ns0 ip link set dev veth0 up mtu 1500");
    118
    119	return 0;
    120fail:
    121	return -1;
    122}
    123
    124static void cleanup(void)
    125{
    126	SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0");
    127	SYS_NOFAIL("ip link del veth1 2> /dev/null");
    128	SYS_NOFAIL("ip link del %s 2> /dev/null", VXLAN_TUNL_DEV1);
    129	SYS_NOFAIL("ip link del %s 2> /dev/null", IP6VXLAN_TUNL_DEV1);
    130}
    131
    132static int add_vxlan_tunnel(void)
    133{
    134	/* at_ns0 namespace */
    135	SYS("ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789",
    136	    VXLAN_TUNL_DEV0);
    137	SYS("ip netns exec at_ns0 ip link set dev %s address %s up",
    138	    VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
    139	SYS("ip netns exec at_ns0 ip addr add dev %s %s/24",
    140	    VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
    141	SYS("ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s",
    142	    IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0);
    143
    144	/* root namespace */
    145	SYS("ip link add dev %s type vxlan external gbp dstport 4789",
    146	    VXLAN_TUNL_DEV1);
    147	SYS("ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
    148	SYS("ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
    149	SYS("ip neigh add %s lladdr %s dev %s",
    150	    IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1);
    151
    152	return 0;
    153fail:
    154	return -1;
    155}
    156
    157static void delete_vxlan_tunnel(void)
    158{
    159	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
    160		   VXLAN_TUNL_DEV0);
    161	SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1);
    162}
    163
    164static int add_ip6vxlan_tunnel(void)
    165{
    166	SYS("ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0",
    167	    IP6_ADDR_VETH0);
    168	SYS("ip netns exec at_ns0 ip link set dev veth0 up");
    169	SYS("ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1);
    170	SYS("ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1);
    171	SYS("ip link set dev veth1 up");
    172
    173	/* at_ns0 namespace */
    174	SYS("ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789",
    175	    IP6VXLAN_TUNL_DEV0);
    176	SYS("ip netns exec at_ns0 ip addr add dev %s %s/24",
    177	    IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0);
    178	SYS("ip netns exec at_ns0 ip link set dev %s address %s up",
    179	    IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0);
    180
    181	/* root namespace */
    182	SYS("ip link add dev %s type vxlan external dstport 4789",
    183	    IP6VXLAN_TUNL_DEV1);
    184	SYS("ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1);
    185	SYS("ip link set dev %s address %s up",
    186	    IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1);
    187
    188	return 0;
    189fail:
    190	return -1;
    191}
    192
    193static void delete_ip6vxlan_tunnel(void)
    194{
    195	SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0",
    196		   IP6_ADDR_VETH0);
    197	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1);
    198	SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1);
    199	SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s",
    200		   IP6VXLAN_TUNL_DEV0);
    201	SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1);
    202}
    203
    204static int test_ping(int family, const char *addr)
    205{
    206	SYS("%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
    207	return 0;
    208fail:
    209	return -1;
    210}
    211
    212static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd)
    213{
    214	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
    215			    .priority = 1, .prog_fd = igr_fd);
    216	DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
    217			    .priority = 1, .prog_fd = egr_fd);
    218	int ret;
    219
    220	ret = bpf_tc_hook_create(hook);
    221	if (!ASSERT_OK(ret, "create tc hook"))
    222		return ret;
    223
    224	if (igr_fd >= 0) {
    225		hook->attach_point = BPF_TC_INGRESS;
    226		ret = bpf_tc_attach(hook, &opts1);
    227		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
    228			bpf_tc_hook_destroy(hook);
    229			return ret;
    230		}
    231	}
    232
    233	if (egr_fd >= 0) {
    234		hook->attach_point = BPF_TC_EGRESS;
    235		ret = bpf_tc_attach(hook, &opts2);
    236		if (!ASSERT_OK(ret, "bpf_tc_attach")) {
    237			bpf_tc_hook_destroy(hook);
    238			return ret;
    239		}
    240	}
    241
    242	return 0;
    243}
    244
    245static void test_vxlan_tunnel(void)
    246{
    247	struct test_tunnel_kern *skel = NULL;
    248	struct nstoken *nstoken;
    249	int local_ip_map_fd = -1;
    250	int set_src_prog_fd, get_src_prog_fd;
    251	int set_dst_prog_fd;
    252	int key = 0, ifindex = -1;
    253	uint local_ip;
    254	int err;
    255	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
    256			    .attach_point = BPF_TC_INGRESS);
    257
    258	/* add vxlan tunnel */
    259	err = add_vxlan_tunnel();
    260	if (!ASSERT_OK(err, "add vxlan tunnel"))
    261		goto done;
    262
    263	/* load and attach bpf prog to tunnel dev tc hook point */
    264	skel = test_tunnel_kern__open_and_load();
    265	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
    266		goto done;
    267	ifindex = if_nametoindex(VXLAN_TUNL_DEV1);
    268	if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex"))
    269		goto done;
    270	tc_hook.ifindex = ifindex;
    271	get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src);
    272	set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src);
    273	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
    274		goto done;
    275	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
    276		goto done;
    277	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
    278		goto done;
    279
    280	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
    281	nstoken = open_netns("at_ns0");
    282	if (!ASSERT_OK_PTR(nstoken, "setns src"))
    283		goto done;
    284	ifindex = if_nametoindex(VXLAN_TUNL_DEV0);
    285	if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex"))
    286		goto done;
    287	tc_hook.ifindex = ifindex;
    288	set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst);
    289	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
    290		goto done;
    291	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
    292		goto done;
    293	close_netns(nstoken);
    294
    295	/* use veth1 ip 2 as tunnel source ip */
    296	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
    297	if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd"))
    298		goto done;
    299	local_ip = IP4_ADDR2_HEX_VETH1;
    300	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
    301	if (!ASSERT_OK(err, "update bpf local_ip_map"))
    302		goto done;
    303
    304	/* ping test */
    305	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
    306	if (!ASSERT_OK(err, "test_ping"))
    307		goto done;
    308
    309done:
    310	/* delete vxlan tunnel */
    311	delete_vxlan_tunnel();
    312	if (local_ip_map_fd >= 0)
    313		close(local_ip_map_fd);
    314	if (skel)
    315		test_tunnel_kern__destroy(skel);
    316}
    317
    318static void test_ip6vxlan_tunnel(void)
    319{
    320	struct test_tunnel_kern *skel = NULL;
    321	struct nstoken *nstoken;
    322	int local_ip_map_fd = -1;
    323	int set_src_prog_fd, get_src_prog_fd;
    324	int set_dst_prog_fd;
    325	int key = 0, ifindex = -1;
    326	uint local_ip;
    327	int err;
    328	DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook,
    329			    .attach_point = BPF_TC_INGRESS);
    330
    331	/* add vxlan tunnel */
    332	err = add_ip6vxlan_tunnel();
    333	if (!ASSERT_OK(err, "add_ip6vxlan_tunnel"))
    334		goto done;
    335
    336	/* load and attach bpf prog to tunnel dev tc hook point */
    337	skel = test_tunnel_kern__open_and_load();
    338	if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load"))
    339		goto done;
    340	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1);
    341	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex"))
    342		goto done;
    343	tc_hook.ifindex = ifindex;
    344	get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src);
    345	set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src);
    346	if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd"))
    347		goto done;
    348	if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd"))
    349		goto done;
    350	if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd))
    351		goto done;
    352
    353	/* load and attach prog set_md to tunnel dev tc hook point at_ns0 */
    354	nstoken = open_netns("at_ns0");
    355	if (!ASSERT_OK_PTR(nstoken, "setns src"))
    356		goto done;
    357	ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0);
    358	if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex"))
    359		goto done;
    360	tc_hook.ifindex = ifindex;
    361	set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst);
    362	if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd"))
    363		goto done;
    364	if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd))
    365		goto done;
    366	close_netns(nstoken);
    367
    368	/* use veth1 ip 2 as tunnel source ip */
    369	local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map);
    370	if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd"))
    371		goto done;
    372	local_ip = IP6_ADDR2_HEX_VETH1;
    373	err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY);
    374	if (!ASSERT_OK(err, "update bpf local_ip_map"))
    375		goto done;
    376
    377	/* ping test */
    378	err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0);
    379	if (!ASSERT_OK(err, "test_ping"))
    380		goto done;
    381
    382done:
    383	/* delete ipv6 vxlan tunnel */
    384	delete_ip6vxlan_tunnel();
    385	if (local_ip_map_fd >= 0)
    386		close(local_ip_map_fd);
    387	if (skel)
    388		test_tunnel_kern__destroy(skel);
    389}
    390
    391#define RUN_TEST(name)							\
    392	({								\
    393		if (test__start_subtest(#name)) {			\
    394			test_ ## name();				\
    395		}							\
    396	})
    397
    398static void *test_tunnel_run_tests(void *arg)
    399{
    400	cleanup();
    401	config_device();
    402
    403	RUN_TEST(vxlan_tunnel);
    404	RUN_TEST(ip6vxlan_tunnel);
    405
    406	cleanup();
    407
    408	return NULL;
    409}
    410
    411void serial_test_tunnel(void)
    412{
    413	pthread_t test_thread;
    414	int err;
    415
    416	/* Run the tests in their own thread to isolate the namespace changes
    417	 * so they do not affect the environment of other tests.
    418	 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
    419	 */
    420	err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL);
    421	if (ASSERT_OK(err, "pthread_create"))
    422		ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
    423}