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

selftests/bpf: Move vxlan tunnel testcases to test_progs

Move vxlan tunnel testcases from test_tunnel.sh to test_progs.
And add vxlan tunnel source testcases also. Other tunnel testcases
will be moved to test_progs step by step in the future.
Rename bpf program section name as SEC("tc") because test_progs
bpf loader could not load sections with name SEC("gre_set_tunnel").
Because of this, add bpftool to load bpf programs in test_tunnel.sh.

Signed-off-by: Kaixi Fan <fankaixi.li@bytedance.com>
Link: https://lore.kernel.org/r/20220430074844.69214-3-fankaixi.li@bytedance.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Kaixi Fan and committed by
Alexei Starovoitov
1ee7efd4 26101f5a

+610 -163
+423
tools/testing/selftests/bpf/prog_tests/test_tunnel.c
··· 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 + 108 + static 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; 120 + fail: 121 + return -1; 122 + } 123 + 124 + static 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 + 132 + static 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; 153 + fail: 154 + return -1; 155 + } 156 + 157 + static 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 + 164 + static 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; 189 + fail: 190 + return -1; 191 + } 192 + 193 + static 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 + 204 + static 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; 208 + fail: 209 + return -1; 210 + } 211 + 212 + static 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 + 245 + static void test_vxlan_tunnel(void) 246 + { 247 + struct test_tunnel_kern *skel = NULL; 248 + struct nstoken *nstoken; 249 + int local_ip_map_fd; 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 + 309 + done: 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 + 318 + static void test_ip6vxlan_tunnel(void) 319 + { 320 + struct test_tunnel_kern *skel = NULL; 321 + struct nstoken *nstoken; 322 + int local_ip_map_fd; 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 + 382 + done: 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 + 398 + static 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 + 411 + void 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 + }
+176 -50
tools/testing/selftests/bpf/progs/test_tunnel_kern.c
··· 40 40 __u32 gbp; 41 41 }; 42 42 43 - SEC("gre_set_tunnel") 44 - int _gre_set_tunnel(struct __sk_buff *skb) 43 + struct { 44 + __uint(type, BPF_MAP_TYPE_ARRAY); 45 + __uint(max_entries, 1); 46 + __type(key, __u32); 47 + __type(value, __u32); 48 + } local_ip_map SEC(".maps"); 49 + 50 + 51 + SEC("tc") 52 + int gre_set_tunnel(struct __sk_buff *skb) 45 53 { 46 54 int ret; 47 55 struct bpf_tunnel_key key; ··· 70 62 return TC_ACT_OK; 71 63 } 72 64 73 - SEC("gre_get_tunnel") 74 - int _gre_get_tunnel(struct __sk_buff *skb) 65 + SEC("tc") 66 + int gre_get_tunnel(struct __sk_buff *skb) 75 67 { 76 68 int ret; 77 69 struct bpf_tunnel_key key; ··· 87 79 return TC_ACT_OK; 88 80 } 89 81 90 - SEC("ip6gretap_set_tunnel") 91 - int _ip6gretap_set_tunnel(struct __sk_buff *skb) 82 + SEC("tc") 83 + int ip6gretap_set_tunnel(struct __sk_buff *skb) 92 84 { 93 85 struct bpf_tunnel_key key; 94 86 int ret; ··· 111 103 return TC_ACT_OK; 112 104 } 113 105 114 - SEC("ip6gretap_get_tunnel") 115 - int _ip6gretap_get_tunnel(struct __sk_buff *skb) 106 + SEC("tc") 107 + int ip6gretap_get_tunnel(struct __sk_buff *skb) 116 108 { 117 109 char fmt[] = "key %d remote ip6 ::%x label %x\n"; 118 110 struct bpf_tunnel_key key; ··· 131 123 return TC_ACT_OK; 132 124 } 133 125 134 - SEC("erspan_set_tunnel") 135 - int _erspan_set_tunnel(struct __sk_buff *skb) 126 + SEC("tc") 127 + int erspan_set_tunnel(struct __sk_buff *skb) 136 128 { 137 129 struct bpf_tunnel_key key; 138 130 struct erspan_metadata md; ··· 174 166 return TC_ACT_OK; 175 167 } 176 168 177 - SEC("erspan_get_tunnel") 178 - int _erspan_get_tunnel(struct __sk_buff *skb) 169 + SEC("tc") 170 + int erspan_get_tunnel(struct __sk_buff *skb) 179 171 { 180 172 char fmt[] = "key %d remote ip 0x%x erspan version %d\n"; 181 173 struct bpf_tunnel_key key; ··· 215 207 return TC_ACT_OK; 216 208 } 217 209 218 - SEC("ip4ip6erspan_set_tunnel") 219 - int _ip4ip6erspan_set_tunnel(struct __sk_buff *skb) 210 + SEC("tc") 211 + int ip4ip6erspan_set_tunnel(struct __sk_buff *skb) 220 212 { 221 213 struct bpf_tunnel_key key; 222 214 struct erspan_metadata md; ··· 259 251 return TC_ACT_OK; 260 252 } 261 253 262 - SEC("ip4ip6erspan_get_tunnel") 263 - int _ip4ip6erspan_get_tunnel(struct __sk_buff *skb) 254 + SEC("tc") 255 + int ip4ip6erspan_get_tunnel(struct __sk_buff *skb) 264 256 { 265 257 char fmt[] = "ip6erspan get key %d remote ip6 ::%x erspan version %d\n"; 266 258 struct bpf_tunnel_key key; ··· 301 293 return TC_ACT_OK; 302 294 } 303 295 304 - SEC("vxlan_set_tunnel") 305 - int _vxlan_set_tunnel(struct __sk_buff *skb) 296 + SEC("tc") 297 + int vxlan_set_tunnel_dst(struct __sk_buff *skb) 306 298 { 307 299 int ret; 308 300 struct bpf_tunnel_key key; 309 301 struct vxlan_metadata md; 302 + __u32 index = 0; 303 + __u32 *local_ip = NULL; 304 + 305 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 306 + if (!local_ip) { 307 + log_err(ret); 308 + return TC_ACT_SHOT; 309 + } 310 310 311 311 __builtin_memset(&key, 0x0, sizeof(key)); 312 + key.local_ipv4 = 0xac100164; /* 172.16.1.100 */ 313 + key.remote_ipv4 = *local_ip; 314 + key.tunnel_id = 2; 315 + key.tunnel_tos = 0; 316 + key.tunnel_ttl = 64; 317 + 318 + ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 319 + BPF_F_ZERO_CSUM_TX); 320 + if (ret < 0) { 321 + log_err(ret); 322 + return TC_ACT_SHOT; 323 + } 324 + 325 + md.gbp = 0x800FF; /* Set VXLAN Group Policy extension */ 326 + ret = bpf_skb_set_tunnel_opt(skb, &md, sizeof(md)); 327 + if (ret < 0) { 328 + log_err(ret); 329 + return TC_ACT_SHOT; 330 + } 331 + 332 + return TC_ACT_OK; 333 + } 334 + 335 + SEC("tc") 336 + int vxlan_set_tunnel_src(struct __sk_buff *skb) 337 + { 338 + int ret; 339 + struct bpf_tunnel_key key; 340 + struct vxlan_metadata md; 341 + __u32 index = 0; 342 + __u32 *local_ip = NULL; 343 + 344 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 345 + if (!local_ip) { 346 + ERROR(ret); 347 + return TC_ACT_SHOT; 348 + } 349 + 350 + __builtin_memset(&key, 0x0, sizeof(key)); 351 + key.local_ipv4 = *local_ip; 312 352 key.remote_ipv4 = 0xac100164; /* 172.16.1.100 */ 313 353 key.tunnel_id = 2; 314 354 key.tunnel_tos = 0; ··· 379 323 return TC_ACT_OK; 380 324 } 381 325 382 - SEC("vxlan_get_tunnel") 383 - int _vxlan_get_tunnel(struct __sk_buff *skb) 326 + SEC("tc") 327 + int vxlan_get_tunnel_src(struct __sk_buff *skb) 384 328 { 385 329 int ret; 386 330 struct bpf_tunnel_key key; 387 331 struct vxlan_metadata md; 388 332 char fmt[] = "key %d remote ip 0x%x vxlan gbp 0x%x\n"; 333 + char fmt2[] = "local ip 0x%x\n"; 334 + __u32 index = 0; 335 + __u32 *local_ip = NULL; 336 + 337 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 338 + if (!local_ip) { 339 + ERROR(ret); 340 + return TC_ACT_SHOT; 341 + } 389 342 390 343 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 0); 391 344 if (ret < 0) { ··· 408 343 return TC_ACT_SHOT; 409 344 } 410 345 411 - bpf_trace_printk(fmt, sizeof(fmt), 412 - key.tunnel_id, key.remote_ipv4, md.gbp); 346 + if (key.local_ipv4 != *local_ip || md.gbp != 0x800FF) { 347 + bpf_printk("vxlan key %d local ip 0x%x remote ip 0x%x gbp 0x%x\n", 348 + key.tunnel_id, key.local_ipv4, 349 + key.remote_ipv4, md.gbp); 350 + bpf_printk("local_ip 0x%x\n", *local_ip); 351 + log_err(ret); 352 + return TC_ACT_SHOT; 353 + } 413 354 414 355 return TC_ACT_OK; 415 356 } 416 357 417 - SEC("ip6vxlan_set_tunnel") 418 - int _ip6vxlan_set_tunnel(struct __sk_buff *skb) 358 + SEC("tc") 359 + int ip6vxlan_set_tunnel_dst(struct __sk_buff *skb) 419 360 { 420 361 struct bpf_tunnel_key key; 421 362 int ret; 363 + __u32 index = 0; 364 + __u32 *local_ip; 365 + 366 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 367 + if (!local_ip) { 368 + log_err(ret); 369 + return TC_ACT_SHOT; 370 + } 422 371 423 372 __builtin_memset(&key, 0x0, sizeof(key)); 373 + key.local_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 374 + key.remote_ipv6[3] = bpf_htonl(*local_ip); 375 + key.tunnel_id = 22; 376 + key.tunnel_tos = 0; 377 + key.tunnel_ttl = 64; 378 + 379 + ret = bpf_skb_set_tunnel_key(skb, &key, sizeof(key), 380 + BPF_F_TUNINFO_IPV6); 381 + if (ret < 0) { 382 + log_err(ret); 383 + return TC_ACT_SHOT; 384 + } 385 + 386 + return TC_ACT_OK; 387 + } 388 + 389 + SEC("tc") 390 + int ip6vxlan_set_tunnel_src(struct __sk_buff *skb) 391 + { 392 + struct bpf_tunnel_key key; 393 + int ret; 394 + __u32 index = 0; 395 + __u32 *local_ip; 396 + 397 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 398 + if (!local_ip) { 399 + ERROR(ret); 400 + return TC_ACT_SHOT; 401 + } 402 + 403 + __builtin_memset(&key, 0x0, sizeof(key)); 404 + key.local_ipv6[3] = bpf_htonl(*local_ip); 424 405 key.remote_ipv6[3] = bpf_htonl(0x11); /* ::11 */ 425 406 key.tunnel_id = 22; 426 407 key.tunnel_tos = 0; ··· 482 371 return TC_ACT_OK; 483 372 } 484 373 485 - SEC("ip6vxlan_get_tunnel") 486 - int _ip6vxlan_get_tunnel(struct __sk_buff *skb) 374 + SEC("tc") 375 + int ip6vxlan_get_tunnel_src(struct __sk_buff *skb) 487 376 { 488 377 char fmt[] = "key %d remote ip6 ::%x label %x\n"; 378 + char fmt2[] = "local ip6 ::%x\n"; 489 379 struct bpf_tunnel_key key; 490 380 int ret; 381 + __u32 index = 0; 382 + __u32 *local_ip; 383 + 384 + local_ip = bpf_map_lookup_elem(&local_ip_map, &index); 385 + if (!local_ip) { 386 + ERROR(ret); 387 + return TC_ACT_SHOT; 388 + } 491 389 492 390 ret = bpf_skb_get_tunnel_key(skb, &key, sizeof(key), 493 391 BPF_F_TUNINFO_IPV6); ··· 505 385 return TC_ACT_SHOT; 506 386 } 507 387 508 - bpf_trace_printk(fmt, sizeof(fmt), 509 - key.tunnel_id, key.remote_ipv6[3], key.tunnel_label); 388 + if (bpf_ntohl(key.local_ipv6[3]) != *local_ip) { 389 + bpf_trace_printk(fmt, sizeof(fmt), 390 + key.tunnel_id, 391 + key.remote_ipv6[3], key.tunnel_label); 392 + bpf_trace_printk(fmt2, sizeof(fmt2), key.local_ipv6[3]); 393 + ERROR(ret); 394 + return TC_ACT_SHOT; 395 + } 510 396 511 397 return TC_ACT_OK; 512 398 } 513 399 514 - SEC("geneve_set_tunnel") 515 - int _geneve_set_tunnel(struct __sk_buff *skb) 400 + SEC("tc") 401 + int geneve_set_tunnel(struct __sk_buff *skb) 516 402 { 517 403 int ret; 518 404 struct bpf_tunnel_key key; ··· 555 429 return TC_ACT_OK; 556 430 } 557 431 558 - SEC("geneve_get_tunnel") 559 - int _geneve_get_tunnel(struct __sk_buff *skb) 432 + SEC("tc") 433 + int geneve_get_tunnel(struct __sk_buff *skb) 560 434 { 561 435 int ret; 562 436 struct bpf_tunnel_key key; ··· 578 452 return TC_ACT_OK; 579 453 } 580 454 581 - SEC("ip6geneve_set_tunnel") 582 - int _ip6geneve_set_tunnel(struct __sk_buff *skb) 455 + SEC("tc") 456 + int ip6geneve_set_tunnel(struct __sk_buff *skb) 583 457 { 584 458 struct bpf_tunnel_key key; 585 459 struct geneve_opt gopt; ··· 616 490 return TC_ACT_OK; 617 491 } 618 492 619 - SEC("ip6geneve_get_tunnel") 620 - int _ip6geneve_get_tunnel(struct __sk_buff *skb) 493 + SEC("tc") 494 + int ip6geneve_get_tunnel(struct __sk_buff *skb) 621 495 { 622 496 char fmt[] = "key %d remote ip 0x%x geneve class 0x%x\n"; 623 497 struct bpf_tunnel_key key; ··· 641 515 return TC_ACT_OK; 642 516 } 643 517 644 - SEC("ipip_set_tunnel") 645 - int _ipip_set_tunnel(struct __sk_buff *skb) 518 + SEC("tc") 519 + int ipip_set_tunnel(struct __sk_buff *skb) 646 520 { 647 521 struct bpf_tunnel_key key = {}; 648 522 void *data = (void *)(long)skb->data; ··· 670 544 return TC_ACT_OK; 671 545 } 672 546 673 - SEC("ipip_get_tunnel") 674 - int _ipip_get_tunnel(struct __sk_buff *skb) 547 + SEC("tc") 548 + int ipip_get_tunnel(struct __sk_buff *skb) 675 549 { 676 550 int ret; 677 551 struct bpf_tunnel_key key; ··· 687 561 return TC_ACT_OK; 688 562 } 689 563 690 - SEC("ipip6_set_tunnel") 691 - int _ipip6_set_tunnel(struct __sk_buff *skb) 564 + SEC("tc") 565 + int ipip6_set_tunnel(struct __sk_buff *skb) 692 566 { 693 567 struct bpf_tunnel_key key = {}; 694 568 void *data = (void *)(long)skb->data; ··· 718 592 return TC_ACT_OK; 719 593 } 720 594 721 - SEC("ipip6_get_tunnel") 722 - int _ipip6_get_tunnel(struct __sk_buff *skb) 595 + SEC("tc") 596 + int ipip6_get_tunnel(struct __sk_buff *skb) 723 597 { 724 598 int ret; 725 599 struct bpf_tunnel_key key; ··· 737 611 return TC_ACT_OK; 738 612 } 739 613 740 - SEC("ip6ip6_set_tunnel") 741 - int _ip6ip6_set_tunnel(struct __sk_buff *skb) 614 + SEC("tc") 615 + int ip6ip6_set_tunnel(struct __sk_buff *skb) 742 616 { 743 617 struct bpf_tunnel_key key = {}; 744 618 void *data = (void *)(long)skb->data; ··· 767 641 return TC_ACT_OK; 768 642 } 769 643 770 - SEC("ip6ip6_get_tunnel") 771 - int _ip6ip6_get_tunnel(struct __sk_buff *skb) 644 + SEC("tc") 645 + int ip6ip6_get_tunnel(struct __sk_buff *skb) 772 646 { 773 647 int ret; 774 648 struct bpf_tunnel_key key; ··· 786 660 return TC_ACT_OK; 787 661 } 788 662 789 - SEC("xfrm_get_state") 790 - int _xfrm_get_state(struct __sk_buff *skb) 663 + SEC("tc") 664 + int xfrm_get_state(struct __sk_buff *skb) 791 665 { 792 666 struct bpf_xfrm_state x; 793 667 char fmt[] = "reqid %d spi 0x%x remote ip 0x%x\n";
+11 -113
tools/testing/selftests/bpf/test_tunnel.sh
··· 45 45 # 5) Tunnel protocol handler, ex: vxlan_rcv, decap the packet 46 46 # 6) Forward the packet to the overlay tnl dev 47 47 48 + BPF_PIN_TUNNEL_DIR="/sys/fs/bpf/tc/tunnel" 48 49 PING_ARG="-c 3 -w 10 -q" 49 50 ret=0 50 51 GREEN='\033[0;92m' ··· 152 151 153 152 # root namespace 154 153 ip link add dev $DEV type $TYPE external 155 - ip addr add dev $DEV 10.1.1.200/24 156 - ip link set dev $DEV up 157 - } 158 - 159 - add_vxlan_tunnel() 160 - { 161 - # Set static ARP entry here because iptables set-mark works 162 - # on L3 packet, as a result not applying to ARP packets, 163 - # causing errors at get_tunnel_{key/opt}. 164 - 165 - # at_ns0 namespace 166 - ip netns exec at_ns0 \ 167 - ip link add dev $DEV_NS type $TYPE \ 168 - id 2 dstport 4789 gbp remote 172.16.1.200 169 - ip netns exec at_ns0 \ 170 - ip link set dev $DEV_NS address 52:54:00:d9:01:00 up 171 - ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 172 - ip netns exec at_ns0 \ 173 - ip neigh add 10.1.1.200 lladdr 52:54:00:d9:02:00 dev $DEV_NS 174 - ip netns exec at_ns0 iptables -A OUTPUT -j MARK --set-mark 0x800FF 175 - 176 - # root namespace 177 - ip link add dev $DEV type $TYPE external gbp dstport 4789 178 - ip link set dev $DEV address 52:54:00:d9:02:00 up 179 - ip addr add dev $DEV 10.1.1.200/24 180 - ip neigh add 10.1.1.100 lladdr 52:54:00:d9:01:00 dev $DEV 181 - } 182 - 183 - add_ip6vxlan_tunnel() 184 - { 185 - #ip netns exec at_ns0 ip -4 addr del 172.16.1.100 dev veth0 186 - ip netns exec at_ns0 ip -6 addr add ::11/96 dev veth0 187 - ip netns exec at_ns0 ip link set dev veth0 up 188 - #ip -4 addr del 172.16.1.200 dev veth1 189 - ip -6 addr add dev veth1 ::22/96 190 - ip link set dev veth1 up 191 - 192 - # at_ns0 namespace 193 - ip netns exec at_ns0 \ 194 - ip link add dev $DEV_NS type $TYPE id 22 dstport 4789 \ 195 - local ::11 remote ::22 196 - ip netns exec at_ns0 ip addr add dev $DEV_NS 10.1.1.100/24 197 - ip netns exec at_ns0 ip link set dev $DEV_NS up 198 - 199 - # root namespace 200 - ip link add dev $DEV type $TYPE external dstport 4789 201 154 ip addr add dev $DEV 10.1.1.200/24 202 155 ip link set dev $DEV up 203 156 } ··· 358 403 echo -e ${GREEN}"PASS: $TYPE"${NC} 359 404 } 360 405 361 - test_vxlan() 362 - { 363 - TYPE=vxlan 364 - DEV_NS=vxlan00 365 - DEV=vxlan11 366 - ret=0 367 - 368 - check $TYPE 369 - config_device 370 - add_vxlan_tunnel 371 - attach_bpf $DEV vxlan_set_tunnel vxlan_get_tunnel 372 - ping $PING_ARG 10.1.1.100 373 - check_err $? 374 - ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 375 - check_err $? 376 - cleanup 377 - 378 - if [ $ret -ne 0 ]; then 379 - echo -e ${RED}"FAIL: $TYPE"${NC} 380 - return 1 381 - fi 382 - echo -e ${GREEN}"PASS: $TYPE"${NC} 383 - } 384 - 385 - test_ip6vxlan() 386 - { 387 - TYPE=vxlan 388 - DEV_NS=ip6vxlan00 389 - DEV=ip6vxlan11 390 - ret=0 391 - 392 - check $TYPE 393 - config_device 394 - add_ip6vxlan_tunnel 395 - ip link set dev veth1 mtu 1500 396 - attach_bpf $DEV ip6vxlan_set_tunnel ip6vxlan_get_tunnel 397 - # underlay 398 - ping6 $PING_ARG ::11 399 - # ip4 over ip6 400 - ping $PING_ARG 10.1.1.100 401 - check_err $? 402 - ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 403 - check_err $? 404 - cleanup 405 - 406 - if [ $ret -ne 0 ]; then 407 - echo -e ${RED}"FAIL: ip6$TYPE"${NC} 408 - return 1 409 - fi 410 - echo -e ${GREEN}"PASS: ip6$TYPE"${NC} 411 - } 412 - 413 406 test_geneve() 414 407 { 415 408 TYPE=geneve ··· 544 641 config_device 545 642 > /sys/kernel/debug/tracing/trace 546 643 setup_xfrm_tunnel 644 + mkdir -p ${BPF_PIN_TUNNEL_DIR} 645 + bpftool prog loadall ./test_tunnel_kern.o ${BPF_PIN_TUNNEL_DIR} 547 646 tc qdisc add dev veth1 clsact 548 - tc filter add dev veth1 proto ip ingress bpf da obj test_tunnel_kern.o \ 549 - sec xfrm_get_state 647 + tc filter add dev veth1 proto ip ingress bpf da object-pinned \ 648 + ${BPF_PIN_TUNNEL_DIR}/xfrm_get_state 550 649 ip netns exec at_ns0 ping $PING_ARG 10.1.1.200 551 650 sleep 1 552 651 grep "reqid 1" /sys/kernel/debug/tracing/trace ··· 571 666 DEV=$1 572 667 SET=$2 573 668 GET=$3 669 + mkdir -p ${BPF_PIN_TUNNEL_DIR} 670 + bpftool prog loadall ./test_tunnel_kern.o ${BPF_PIN_TUNNEL_DIR}/ 574 671 tc qdisc add dev $DEV clsact 575 - tc filter add dev $DEV egress bpf da obj test_tunnel_kern.o sec $SET 576 - tc filter add dev $DEV ingress bpf da obj test_tunnel_kern.o sec $GET 672 + tc filter add dev $DEV egress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$SET 673 + tc filter add dev $DEV ingress bpf da object-pinned ${BPF_PIN_TUNNEL_DIR}/$GET 577 674 } 578 675 579 676 cleanup() 580 677 { 678 + rm -rf ${BPF_PIN_TUNNEL_DIR} 679 + 581 680 ip netns delete at_ns0 2> /dev/null 582 681 ip link del veth1 2> /dev/null 583 682 ip link del ipip11 2> /dev/null ··· 590 681 ip link del gretap11 2> /dev/null 591 682 ip link del ip6gre11 2> /dev/null 592 683 ip link del ip6gretap11 2> /dev/null 593 - ip link del vxlan11 2> /dev/null 594 - ip link del ip6vxlan11 2> /dev/null 595 684 ip link del geneve11 2> /dev/null 596 685 ip link del ip6geneve11 2> /dev/null 597 686 ip link del erspan11 2> /dev/null ··· 621 714 { 622 715 echo 'file ip_gre.c +p' > /sys/kernel/debug/dynamic_debug/control 623 716 echo 'file ip6_gre.c +p' > /sys/kernel/debug/dynamic_debug/control 624 - echo 'file vxlan.c +p' > /sys/kernel/debug/dynamic_debug/control 625 717 echo 'file geneve.c +p' > /sys/kernel/debug/dynamic_debug/control 626 718 echo 'file ipip.c +p' > /sys/kernel/debug/dynamic_debug/control 627 719 } ··· 654 748 655 749 echo "Testing IP6ERSPAN tunnel..." 656 750 test_ip6erspan v2 657 - errors=$(( $errors + $? )) 658 - 659 - echo "Testing VXLAN tunnel..." 660 - test_vxlan 661 - errors=$(( $errors + $? )) 662 - 663 - echo "Testing IP6VXLAN tunnel..." 664 - test_ip6vxlan 665 751 errors=$(( $errors + $? )) 666 752 667 753 echo "Testing GENEVE tunnel..."