brintos

brintos / linux-shallow public Read only

0
0
Text · 6.3 KiB · 8d75424 Raw
214 lines · c
1// SPDX-License-Identifier: GPL-2.02 3/* Create 3 namespaces with 3 veth peers, and forward packets in-between using4 * native XDP5 *6 *                      XDP_TX7 * NS1(veth11)        NS2(veth22)        NS3(veth33)8 *      |                  |                  |9 *      |                  |                  |10 *   (veth1,            (veth2,            (veth3,11 *   id:111)            id:122)            id:133)12 *     ^ |                ^ |                ^ |13 *     | |  XDP_REDIRECT  | |  XDP_REDIRECT  | |14 *     | ------------------ ------------------ |15 *     -----------------------------------------16 *                    XDP_REDIRECT17 */18 19#define _GNU_SOURCE20#include <net/if.h>21#include "test_progs.h"22#include "network_helpers.h"23#include "xdp_dummy.skel.h"24#include "xdp_redirect_map.skel.h"25#include "xdp_tx.skel.h"26 27#define VETH_PAIRS_COUNT	328#define NS_SUFFIX_LEN		629#define VETH_NAME_MAX_LEN	1630#define IP_SRC				"10.1.1.11"31#define IP_DST				"10.1.1.33"32#define IP_CMD_MAX_LEN		12833 34struct skeletons {35	struct xdp_dummy *xdp_dummy;36	struct xdp_tx *xdp_tx;37	struct xdp_redirect_map *xdp_redirect_maps;38};39 40struct veth_configuration {41	char local_veth[VETH_NAME_MAX_LEN]; /* Interface in main namespace */42	char remote_veth[VETH_NAME_MAX_LEN]; /* Peer interface in dedicated namespace*/43	const char *namespace; /* Namespace for the remote veth */44	char next_veth[VETH_NAME_MAX_LEN]; /* Local interface to redirect traffic to */45	char *remote_addr; /* IP address of the remote veth */46};47 48static struct veth_configuration config[VETH_PAIRS_COUNT] = {49	{50		.local_veth = "veth1",51		.remote_veth = "veth11",52		.next_veth = "veth2",53		.remote_addr = IP_SRC,54		.namespace = "ns-veth11"55	},56	{57		.local_veth = "veth2",58		.remote_veth = "veth22",59		.next_veth = "veth3",60		.remote_addr = NULL,61		.namespace = "ns-veth22"62	},63	{64		.local_veth = "veth3",65		.remote_veth = "veth33",66		.next_veth = "veth1",67		.remote_addr = IP_DST,68		.namespace = "ns-veth33"69	}70};71 72static int attach_programs_to_veth_pair(struct skeletons *skeletons, int index)73{74	struct bpf_program *local_prog, *remote_prog;75	struct bpf_link **local_link, **remote_link;76	struct nstoken *nstoken;77	struct bpf_link *link;78	int interface;79 80	switch (index) {81	case 0:82		local_prog = skeletons->xdp_redirect_maps->progs.xdp_redirect_map_0;83		local_link = &skeletons->xdp_redirect_maps->links.xdp_redirect_map_0;84		remote_prog = skeletons->xdp_dummy->progs.xdp_dummy_prog;85		remote_link = &skeletons->xdp_dummy->links.xdp_dummy_prog;86		break;87	case 1:88		local_prog = skeletons->xdp_redirect_maps->progs.xdp_redirect_map_1;89		local_link = &skeletons->xdp_redirect_maps->links.xdp_redirect_map_1;90		remote_prog = skeletons->xdp_tx->progs.xdp_tx;91		remote_link = &skeletons->xdp_tx->links.xdp_tx;92		break;93	case 2:94		local_prog = skeletons->xdp_redirect_maps->progs.xdp_redirect_map_2;95		local_link = &skeletons->xdp_redirect_maps->links.xdp_redirect_map_2;96		remote_prog = skeletons->xdp_dummy->progs.xdp_dummy_prog;97		remote_link = &skeletons->xdp_dummy->links.xdp_dummy_prog;98		break;99	}100	interface = if_nametoindex(config[index].local_veth);101	if (!ASSERT_NEQ(interface, 0, "non zero interface index"))102		return -1;103	link = bpf_program__attach_xdp(local_prog, interface);104	if (!ASSERT_OK_PTR(link, "attach xdp program to local veth"))105		return -1;106	*local_link = link;107	nstoken = open_netns(config[index].namespace);108	if (!ASSERT_OK_PTR(nstoken, "switch to remote veth namespace"))109		return -1;110	interface = if_nametoindex(config[index].remote_veth);111	if (!ASSERT_NEQ(interface, 0, "non zero interface index")) {112		close_netns(nstoken);113		return -1;114	}115	link = bpf_program__attach_xdp(remote_prog, interface);116	*remote_link = link;117	close_netns(nstoken);118	if (!ASSERT_OK_PTR(link, "attach xdp program to remote veth"))119		return -1;120 121	return 0;122}123 124static int configure_network(struct skeletons *skeletons)125{126	int interface_id;127	int map_fd;128	int err;129	int i = 0;130 131	/* First create and configure all interfaces */132	for (i = 0; i < VETH_PAIRS_COUNT; i++) {133		SYS(fail, "ip netns add %s", config[i].namespace);134		SYS(fail, "ip link add %s type veth peer name %s netns %s",135		    config[i].local_veth, config[i].remote_veth, config[i].namespace);136		SYS(fail, "ip link set dev %s up", config[i].local_veth);137		if (config[i].remote_addr)138			SYS(fail, "ip -n %s addr add %s/24 dev %s",	config[i].namespace,139			    config[i].remote_addr, config[i].remote_veth);140		SYS(fail, "ip -n %s link set dev %s up", config[i].namespace,141		    config[i].remote_veth);142	}143 144	/* Then configure the redirect map and attach programs to interfaces */145	map_fd = bpf_map__fd(skeletons->xdp_redirect_maps->maps.tx_port);146	if (!ASSERT_GE(map_fd, 0, "open redirect map"))147		goto fail;148	for (i = 0; i < VETH_PAIRS_COUNT; i++) {149		interface_id = if_nametoindex(config[i].next_veth);150		if (!ASSERT_NEQ(interface_id, 0, "non zero interface index"))151			goto fail;152		err = bpf_map_update_elem(map_fd, &i, &interface_id, BPF_ANY);153		if (!ASSERT_OK(err, "configure interface redirection through map"))154			goto fail;155		if (attach_programs_to_veth_pair(skeletons, i))156			goto fail;157	}158 159	return 0;160 161fail:162	return -1;163}164 165static void cleanup_network(void)166{167	int i;168 169	/* Deleting namespaces is enough to automatically remove veth pairs as well170	 */171	for (i = 0; i < VETH_PAIRS_COUNT; i++)172		SYS_NOFAIL("ip netns del %s", config[i].namespace);173}174 175static int check_ping(struct skeletons *skeletons)176{177	/* Test: if all interfaces are properly configured, we must be able to ping178	 * veth33 from veth11179	 */180	return SYS_NOFAIL("ip netns exec %s ping -c 1 -W 1 %s > /dev/null",181					  config[0].namespace, IP_DST);182}183 184void test_xdp_veth_redirect(void)185{186	struct skeletons skeletons = {};187 188	skeletons.xdp_dummy = xdp_dummy__open_and_load();189	if (!ASSERT_OK_PTR(skeletons.xdp_dummy, "xdp_dummy__open_and_load"))190		return;191 192	skeletons.xdp_tx = xdp_tx__open_and_load();193	if (!ASSERT_OK_PTR(skeletons.xdp_tx, "xdp_tx__open_and_load"))194		goto destroy_xdp_dummy;195 196	skeletons.xdp_redirect_maps = xdp_redirect_map__open_and_load();197	if (!ASSERT_OK_PTR(skeletons.xdp_redirect_maps, "xdp_redirect_map__open_and_load"))198		goto destroy_xdp_tx;199 200	if (configure_network(&skeletons))201		goto destroy_xdp_redirect_map;202 203	ASSERT_OK(check_ping(&skeletons), "ping");204 205destroy_xdp_redirect_map:206	xdp_redirect_map__destroy(skeletons.xdp_redirect_maps);207destroy_xdp_tx:208	xdp_tx__destroy(skeletons.xdp_tx);209destroy_xdp_dummy:210	xdp_dummy__destroy(skeletons.xdp_dummy);211 212	cleanup_network();213}214