Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.14 213 lines 6.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2 3/* Create 3 namespaces with 3 veth peers, and forward packets in-between using 4 * native XDP 5 * 6 * XDP_TX 7 * 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_REDIRECT 17 */ 18 19#define _GNU_SOURCE 20#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 3 28#define NS_SUFFIX_LEN 6 29#define VETH_NAME_MAX_LEN 16 30#define IP_SRC "10.1.1.11" 31#define IP_DST "10.1.1.33" 32#define IP_CMD_MAX_LEN 128 33 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 well 170 */ 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 ping 178 * veth33 from veth11 179 */ 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}