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_link.h> 54 #include <linux/if_tun.h> 55 #include <linux/limits.h> 56 #include <linux/sysctl.h> 57 #include <linux/time_types.h> 58 #include <linux/net_tstamp.h> 59 #include <net/if.h> 60 #include <stdbool.h> 61 #include <stdio.h> 62 #include <sys/stat.h> 63 #include <unistd.h> 64 65 #include "test_progs.h" 66 #include "network_helpers.h" 67 #include "test_tunnel_kern.skel.h" 68 69 #define IP4_ADDR_VETH0 "172.16.1.100" 70 #define IP4_ADDR1_VETH1 "172.16.1.200" 71 #define IP4_ADDR2_VETH1 "172.16.1.20" 72 #define IP4_ADDR_TUNL_DEV0 "10.1.1.100" 73 #define IP4_ADDR_TUNL_DEV1 "10.1.1.200" 74 75 #define IP6_ADDR_VETH0 "::11" 76 #define IP6_ADDR1_VETH1 "::22" 77 #define IP6_ADDR2_VETH1 "::bb" 78 79 #define IP4_ADDR1_HEX_VETH1 0xac1001c8 80 #define IP4_ADDR2_HEX_VETH1 0xac100114 81 #define IP6_ADDR1_HEX_VETH1 0x22 82 #define IP6_ADDR2_HEX_VETH1 0xbb 83 84 #define MAC_TUNL_DEV0 "52:54:00:d9:01:00" 85 #define MAC_TUNL_DEV1 "52:54:00:d9:02:00" 86 #define MAC_VETH1 "52:54:00:d9:03:00" 87 88 #define VXLAN_TUNL_DEV0 "vxlan00" 89 #define VXLAN_TUNL_DEV1 "vxlan11" 90 #define IP6VXLAN_TUNL_DEV0 "ip6vxlan00" 91 #define IP6VXLAN_TUNL_DEV1 "ip6vxlan11" 92 93 #define IPIP_TUNL_DEV0 "ipip00" 94 #define IPIP_TUNL_DEV1 "ipip11" 95 96 #define XFRM_AUTH "0x1111111111111111111111111111111111111111" 97 #define XFRM_ENC "0x22222222222222222222222222222222" 98 #define XFRM_SPI_IN_TO_OUT 0x1 99 #define XFRM_SPI_OUT_TO_IN 0x2 100 101 #define PING_ARGS "-i 0.01 -c 3 -w 10 -q" 102 103 static int config_device(void) 104 { 105 SYS(fail, "ip netns add at_ns0"); 106 SYS(fail, "ip link add veth0 address " MAC_VETH1 " type veth peer name veth1"); 107 SYS(fail, "ip link set veth0 netns at_ns0"); 108 SYS(fail, "ip addr add " IP4_ADDR1_VETH1 "/24 dev veth1"); 109 SYS(fail, "ip link set dev veth1 up mtu 1500"); 110 SYS(fail, "ip netns exec at_ns0 ip addr add " IP4_ADDR_VETH0 "/24 dev veth0"); 111 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up mtu 1500"); 112 113 return 0; 114 fail: 115 return -1; 116 } 117 118 static void cleanup(void) 119 { 120 SYS_NOFAIL("test -f /var/run/netns/at_ns0 && ip netns delete at_ns0"); 121 SYS_NOFAIL("ip link del veth1"); 122 SYS_NOFAIL("ip link del %s", VXLAN_TUNL_DEV1); 123 SYS_NOFAIL("ip link del %s", IP6VXLAN_TUNL_DEV1); 124 } 125 126 static int add_vxlan_tunnel(void) 127 { 128 /* at_ns0 namespace */ 129 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external gbp dstport 4789", 130 VXLAN_TUNL_DEV0); 131 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up", 132 VXLAN_TUNL_DEV0, MAC_TUNL_DEV0); 133 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24", 134 VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0); 135 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev %s", 136 IP4_ADDR_TUNL_DEV1, MAC_TUNL_DEV1, VXLAN_TUNL_DEV0); 137 SYS(fail, "ip netns exec at_ns0 ip neigh add %s lladdr %s dev veth0", 138 IP4_ADDR2_VETH1, MAC_VETH1); 139 140 /* root namespace */ 141 SYS(fail, "ip link add dev %s type vxlan external gbp dstport 4789", 142 VXLAN_TUNL_DEV1); 143 SYS(fail, "ip link set dev %s address %s up", VXLAN_TUNL_DEV1, MAC_TUNL_DEV1); 144 SYS(fail, "ip addr add dev %s %s/24", VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1); 145 SYS(fail, "ip neigh add %s lladdr %s dev %s", 146 IP4_ADDR_TUNL_DEV0, MAC_TUNL_DEV0, VXLAN_TUNL_DEV1); 147 148 return 0; 149 fail: 150 return -1; 151 } 152 153 static void delete_vxlan_tunnel(void) 154 { 155 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s", 156 VXLAN_TUNL_DEV0); 157 SYS_NOFAIL("ip link delete dev %s", VXLAN_TUNL_DEV1); 158 } 159 160 static int add_ip6vxlan_tunnel(void) 161 { 162 SYS(fail, "ip netns exec at_ns0 ip -6 addr add %s/96 dev veth0", 163 IP6_ADDR_VETH0); 164 SYS(fail, "ip netns exec at_ns0 ip link set dev veth0 up"); 165 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR1_VETH1); 166 SYS(fail, "ip -6 addr add %s/96 dev veth1", IP6_ADDR2_VETH1); 167 SYS(fail, "ip link set dev veth1 up"); 168 169 /* at_ns0 namespace */ 170 SYS(fail, "ip netns exec at_ns0 ip link add dev %s type vxlan external dstport 4789", 171 IP6VXLAN_TUNL_DEV0); 172 SYS(fail, "ip netns exec at_ns0 ip addr add dev %s %s/24", 173 IP6VXLAN_TUNL_DEV0, IP4_ADDR_TUNL_DEV0); 174 SYS(fail, "ip netns exec at_ns0 ip link set dev %s address %s up", 175 IP6VXLAN_TUNL_DEV0, MAC_TUNL_DEV0); 176 177 /* root namespace */ 178 SYS(fail, "ip link add dev %s type vxlan external dstport 4789", 179 IP6VXLAN_TUNL_DEV1); 180 SYS(fail, "ip addr add dev %s %s/24", IP6VXLAN_TUNL_DEV1, IP4_ADDR_TUNL_DEV1); 181 SYS(fail, "ip link set dev %s address %s up", 182 IP6VXLAN_TUNL_DEV1, MAC_TUNL_DEV1); 183 184 return 0; 185 fail: 186 return -1; 187 } 188 189 static void delete_ip6vxlan_tunnel(void) 190 { 191 SYS_NOFAIL("ip netns exec at_ns0 ip -6 addr delete %s/96 dev veth0", 192 IP6_ADDR_VETH0); 193 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR1_VETH1); 194 SYS_NOFAIL("ip -6 addr delete %s/96 dev veth1", IP6_ADDR2_VETH1); 195 SYS_NOFAIL("ip netns exec at_ns0 ip link delete dev %s", 196 IP6VXLAN_TUNL_DEV0); 197 SYS_NOFAIL("ip link delete dev %s", IP6VXLAN_TUNL_DEV1); 198 } 199 200 enum ipip_encap { 201 NONE = 0, 202 FOU = 1, 203 GUE = 2, 204 }; 205 206 static int set_ipip_encap(const char *ipproto, const char *type) 207 { 208 SYS(fail, "ip -n at_ns0 fou add port 5555 %s", ipproto); 209 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap %s", 210 IPIP_TUNL_DEV0, type); 211 SYS(fail, "ip -n at_ns0 link set dev %s type ipip encap-dport 5555", 212 IPIP_TUNL_DEV0); 213 214 return 0; 215 fail: 216 return -1; 217 } 218 219 static int add_ipip_tunnel(enum ipip_encap encap) 220 { 221 int err; 222 const char *ipproto, *type; 223 224 switch (encap) { 225 case FOU: 226 ipproto = "ipproto 4"; 227 type = "fou"; 228 break; 229 case GUE: 230 ipproto = "gue"; 231 type = ipproto; 232 break; 233 default: 234 ipproto = NULL; 235 type = ipproto; 236 } 237 238 /* at_ns0 namespace */ 239 SYS(fail, "ip -n at_ns0 link add dev %s type ipip local %s remote %s", 240 IPIP_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR1_VETH1); 241 242 if (type && ipproto) { 243 err = set_ipip_encap(ipproto, type); 244 if (!ASSERT_OK(err, "set_ipip_encap")) 245 goto fail; 246 } 247 248 SYS(fail, "ip -n at_ns0 link set dev %s up", IPIP_TUNL_DEV0); 249 SYS(fail, "ip -n at_ns0 addr add dev %s %s/24", 250 IPIP_TUNL_DEV0, IP4_ADDR_TUNL_DEV0); 251 252 /* root namespace */ 253 if (type && ipproto) 254 SYS(fail, "ip fou add port 5555 %s", ipproto); 255 SYS(fail, "ip link add dev %s type ipip external", IPIP_TUNL_DEV1); 256 SYS(fail, "ip link set dev %s up", IPIP_TUNL_DEV1); 257 SYS(fail, "ip addr add dev %s %s/24", IPIP_TUNL_DEV1, 258 IP4_ADDR_TUNL_DEV1); 259 260 return 0; 261 fail: 262 return -1; 263 } 264 265 static void delete_ipip_tunnel(void) 266 { 267 SYS_NOFAIL("ip -n at_ns0 link delete dev %s", IPIP_TUNL_DEV0); 268 SYS_NOFAIL("ip -n at_ns0 fou del port 5555"); 269 SYS_NOFAIL("ip link delete dev %s", IPIP_TUNL_DEV1); 270 SYS_NOFAIL("ip fou del port 5555"); 271 } 272 273 static int add_xfrm_tunnel(void) 274 { 275 /* at_ns0 namespace 276 * at_ns0 -> root 277 */ 278 SYS(fail, 279 "ip netns exec at_ns0 " 280 "ip xfrm state add src %s dst %s proto esp " 281 "spi %d reqid 1 mode tunnel replay-window 42 " 282 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s", 283 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC); 284 SYS(fail, 285 "ip netns exec at_ns0 " 286 "ip xfrm policy add src %s/32 dst %s/32 dir out " 287 "tmpl src %s dst %s proto esp reqid 1 " 288 "mode tunnel", 289 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1); 290 291 /* root -> at_ns0 */ 292 SYS(fail, 293 "ip netns exec at_ns0 " 294 "ip xfrm state add src %s dst %s proto esp " 295 "spi %d reqid 2 mode tunnel " 296 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s", 297 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC); 298 SYS(fail, 299 "ip netns exec at_ns0 " 300 "ip xfrm policy add src %s/32 dst %s/32 dir in " 301 "tmpl src %s dst %s proto esp reqid 2 " 302 "mode tunnel", 303 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0); 304 305 /* address & route */ 306 SYS(fail, "ip netns exec at_ns0 ip addr add dev veth0 %s/32", 307 IP4_ADDR_TUNL_DEV0); 308 SYS(fail, "ip netns exec at_ns0 ip route add %s dev veth0 via %s src %s", 309 IP4_ADDR_TUNL_DEV1, IP4_ADDR1_VETH1, IP4_ADDR_TUNL_DEV0); 310 311 /* root namespace 312 * at_ns0 -> root 313 */ 314 SYS(fail, 315 "ip xfrm state add src %s dst %s proto esp " 316 "spi %d reqid 1 mode tunnel replay-window 42 " 317 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s", 318 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT, XFRM_AUTH, XFRM_ENC); 319 SYS(fail, 320 "ip xfrm policy add src %s/32 dst %s/32 dir in " 321 "tmpl src %s dst %s proto esp reqid 1 " 322 "mode tunnel", 323 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1, IP4_ADDR_VETH0, IP4_ADDR1_VETH1); 324 325 /* root -> at_ns0 */ 326 SYS(fail, 327 "ip xfrm state add src %s dst %s proto esp " 328 "spi %d reqid 2 mode tunnel " 329 "auth-trunc 'hmac(sha1)' %s 96 enc 'cbc(aes)' %s", 330 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN, XFRM_AUTH, XFRM_ENC); 331 SYS(fail, 332 "ip xfrm policy add src %s/32 dst %s/32 dir out " 333 "tmpl src %s dst %s proto esp reqid 2 " 334 "mode tunnel", 335 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0, IP4_ADDR1_VETH1, IP4_ADDR_VETH0); 336 337 /* address & route */ 338 SYS(fail, "ip addr add dev veth1 %s/32", IP4_ADDR_TUNL_DEV1); 339 SYS(fail, "ip route add %s dev veth1 via %s src %s", 340 IP4_ADDR_TUNL_DEV0, IP4_ADDR_VETH0, IP4_ADDR_TUNL_DEV1); 341 342 return 0; 343 fail: 344 return -1; 345 } 346 347 static void delete_xfrm_tunnel(void) 348 { 349 SYS_NOFAIL("ip xfrm policy delete dir out src %s/32 dst %s/32", 350 IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0); 351 SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32", 352 IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1); 353 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d", 354 IP4_ADDR_VETH0, IP4_ADDR1_VETH1, XFRM_SPI_IN_TO_OUT); 355 SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d", 356 IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN); 357 } 358 359 static int test_ping(int family, const char *addr) 360 { 361 SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr); 362 return 0; 363 fail: 364 return -1; 365 } 366 367 static int attach_tc_prog(struct bpf_tc_hook *hook, int igr_fd, int egr_fd) 368 { 369 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1, 370 .priority = 1, .prog_fd = igr_fd); 371 DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1, 372 .priority = 1, .prog_fd = egr_fd); 373 int ret; 374 375 ret = bpf_tc_hook_create(hook); 376 if (!ASSERT_OK(ret, "create tc hook")) 377 return ret; 378 379 if (igr_fd >= 0) { 380 hook->attach_point = BPF_TC_INGRESS; 381 ret = bpf_tc_attach(hook, &opts1); 382 if (!ASSERT_OK(ret, "bpf_tc_attach")) { 383 bpf_tc_hook_destroy(hook); 384 return ret; 385 } 386 } 387 388 if (egr_fd >= 0) { 389 hook->attach_point = BPF_TC_EGRESS; 390 ret = bpf_tc_attach(hook, &opts2); 391 if (!ASSERT_OK(ret, "bpf_tc_attach")) { 392 bpf_tc_hook_destroy(hook); 393 return ret; 394 } 395 } 396 397 return 0; 398 } 399 400 static void test_vxlan_tunnel(void) 401 { 402 struct test_tunnel_kern *skel = NULL; 403 struct nstoken *nstoken; 404 int local_ip_map_fd = -1; 405 int set_src_prog_fd, get_src_prog_fd; 406 int set_dst_prog_fd; 407 int key = 0, ifindex = -1; 408 uint local_ip; 409 int err; 410 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook, 411 .attach_point = BPF_TC_INGRESS); 412 413 /* add vxlan tunnel */ 414 err = add_vxlan_tunnel(); 415 if (!ASSERT_OK(err, "add vxlan tunnel")) 416 goto done; 417 418 /* load and attach bpf prog to tunnel dev tc hook point */ 419 skel = test_tunnel_kern__open_and_load(); 420 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load")) 421 goto done; 422 ifindex = if_nametoindex(VXLAN_TUNL_DEV1); 423 if (!ASSERT_NEQ(ifindex, 0, "vxlan11 ifindex")) 424 goto done; 425 tc_hook.ifindex = ifindex; 426 get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src); 427 set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src); 428 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd")) 429 goto done; 430 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd")) 431 goto done; 432 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd)) 433 goto done; 434 435 /* load and attach bpf prog to veth dev tc hook point */ 436 ifindex = if_nametoindex("veth1"); 437 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex")) 438 goto done; 439 tc_hook.ifindex = ifindex; 440 set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst); 441 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd")) 442 goto done; 443 if (attach_tc_prog(&tc_hook, set_dst_prog_fd, -1)) 444 goto done; 445 446 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */ 447 nstoken = open_netns("at_ns0"); 448 if (!ASSERT_OK_PTR(nstoken, "setns src")) 449 goto done; 450 ifindex = if_nametoindex(VXLAN_TUNL_DEV0); 451 if (!ASSERT_NEQ(ifindex, 0, "vxlan00 ifindex")) 452 goto done; 453 tc_hook.ifindex = ifindex; 454 set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst); 455 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd")) 456 goto done; 457 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd)) 458 goto done; 459 close_netns(nstoken); 460 461 /* use veth1 ip 2 as tunnel source ip */ 462 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map); 463 if (!ASSERT_GE(local_ip_map_fd, 0, "bpf_map__fd")) 464 goto done; 465 local_ip = IP4_ADDR2_HEX_VETH1; 466 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY); 467 if (!ASSERT_OK(err, "update bpf local_ip_map")) 468 goto done; 469 470 /* ping test */ 471 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0); 472 if (!ASSERT_OK(err, "test_ping")) 473 goto done; 474 475 done: 476 /* delete vxlan tunnel */ 477 delete_vxlan_tunnel(); 478 if (local_ip_map_fd >= 0) 479 close(local_ip_map_fd); 480 if (skel) 481 test_tunnel_kern__destroy(skel); 482 } 483 484 static void test_ip6vxlan_tunnel(void) 485 { 486 struct test_tunnel_kern *skel = NULL; 487 struct nstoken *nstoken; 488 int local_ip_map_fd = -1; 489 int set_src_prog_fd, get_src_prog_fd; 490 int set_dst_prog_fd; 491 int key = 0, ifindex = -1; 492 uint local_ip; 493 int err; 494 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook, 495 .attach_point = BPF_TC_INGRESS); 496 497 /* add vxlan tunnel */ 498 err = add_ip6vxlan_tunnel(); 499 if (!ASSERT_OK(err, "add_ip6vxlan_tunnel")) 500 goto done; 501 502 /* load and attach bpf prog to tunnel dev tc hook point */ 503 skel = test_tunnel_kern__open_and_load(); 504 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load")) 505 goto done; 506 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV1); 507 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan11 ifindex")) 508 goto done; 509 tc_hook.ifindex = ifindex; 510 get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src); 511 set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src); 512 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd")) 513 goto done; 514 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd")) 515 goto done; 516 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd)) 517 goto done; 518 519 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */ 520 nstoken = open_netns("at_ns0"); 521 if (!ASSERT_OK_PTR(nstoken, "setns src")) 522 goto done; 523 ifindex = if_nametoindex(IP6VXLAN_TUNL_DEV0); 524 if (!ASSERT_NEQ(ifindex, 0, "ip6vxlan00 ifindex")) 525 goto done; 526 tc_hook.ifindex = ifindex; 527 set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst); 528 if (!ASSERT_GE(set_dst_prog_fd, 0, "bpf_program__fd")) 529 goto done; 530 if (attach_tc_prog(&tc_hook, -1, set_dst_prog_fd)) 531 goto done; 532 close_netns(nstoken); 533 534 /* use veth1 ip 2 as tunnel source ip */ 535 local_ip_map_fd = bpf_map__fd(skel->maps.local_ip_map); 536 if (!ASSERT_GE(local_ip_map_fd, 0, "get local_ip_map fd")) 537 goto done; 538 local_ip = IP6_ADDR2_HEX_VETH1; 539 err = bpf_map_update_elem(local_ip_map_fd, &key, &local_ip, BPF_ANY); 540 if (!ASSERT_OK(err, "update bpf local_ip_map")) 541 goto done; 542 543 /* ping test */ 544 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0); 545 if (!ASSERT_OK(err, "test_ping")) 546 goto done; 547 548 done: 549 /* delete ipv6 vxlan tunnel */ 550 delete_ip6vxlan_tunnel(); 551 if (local_ip_map_fd >= 0) 552 close(local_ip_map_fd); 553 if (skel) 554 test_tunnel_kern__destroy(skel); 555 } 556 557 static void test_ipip_tunnel(enum ipip_encap encap) 558 { 559 struct test_tunnel_kern *skel = NULL; 560 struct nstoken *nstoken; 561 int set_src_prog_fd, get_src_prog_fd; 562 int ifindex = -1; 563 int err; 564 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook, 565 .attach_point = BPF_TC_INGRESS); 566 567 /* add ipip tunnel */ 568 err = add_ipip_tunnel(encap); 569 if (!ASSERT_OK(err, "add_ipip_tunnel")) 570 goto done; 571 572 /* load and attach bpf prog to tunnel dev tc hook point */ 573 skel = test_tunnel_kern__open_and_load(); 574 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load")) 575 goto done; 576 ifindex = if_nametoindex(IPIP_TUNL_DEV1); 577 if (!ASSERT_NEQ(ifindex, 0, "ipip11 ifindex")) 578 goto done; 579 tc_hook.ifindex = ifindex; 580 581 switch (encap) { 582 case FOU: 583 get_src_prog_fd = bpf_program__fd( 584 skel->progs.ipip_encap_get_tunnel); 585 set_src_prog_fd = bpf_program__fd( 586 skel->progs.ipip_fou_set_tunnel); 587 break; 588 case GUE: 589 get_src_prog_fd = bpf_program__fd( 590 skel->progs.ipip_encap_get_tunnel); 591 set_src_prog_fd = bpf_program__fd( 592 skel->progs.ipip_gue_set_tunnel); 593 break; 594 default: 595 get_src_prog_fd = bpf_program__fd( 596 skel->progs.ipip_get_tunnel); 597 set_src_prog_fd = bpf_program__fd( 598 skel->progs.ipip_set_tunnel); 599 } 600 601 if (!ASSERT_GE(set_src_prog_fd, 0, "bpf_program__fd")) 602 goto done; 603 if (!ASSERT_GE(get_src_prog_fd, 0, "bpf_program__fd")) 604 goto done; 605 if (attach_tc_prog(&tc_hook, get_src_prog_fd, set_src_prog_fd)) 606 goto done; 607 608 /* ping from root namespace test */ 609 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV0); 610 if (!ASSERT_OK(err, "test_ping")) 611 goto done; 612 613 /* ping from at_ns0 namespace test */ 614 nstoken = open_netns("at_ns0"); 615 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1); 616 if (!ASSERT_OK(err, "test_ping")) 617 goto done; 618 close_netns(nstoken); 619 620 done: 621 /* delete ipip tunnel */ 622 delete_ipip_tunnel(); 623 if (skel) 624 test_tunnel_kern__destroy(skel); 625 } 626 627 static void test_xfrm_tunnel(void) 628 { 629 DECLARE_LIBBPF_OPTS(bpf_tc_hook, tc_hook, 630 .attach_point = BPF_TC_INGRESS); 631 LIBBPF_OPTS(bpf_xdp_attach_opts, opts); 632 struct test_tunnel_kern *skel = NULL; 633 struct nstoken *nstoken; 634 int xdp_prog_fd; 635 int tc_prog_fd; 636 int ifindex; 637 int err; 638 639 err = add_xfrm_tunnel(); 640 if (!ASSERT_OK(err, "add_xfrm_tunnel")) 641 return; 642 643 skel = test_tunnel_kern__open_and_load(); 644 if (!ASSERT_OK_PTR(skel, "test_tunnel_kern__open_and_load")) 645 goto done; 646 647 ifindex = if_nametoindex("veth1"); 648 if (!ASSERT_NEQ(ifindex, 0, "veth1 ifindex")) 649 goto done; 650 651 /* attach tc prog to tunnel dev */ 652 tc_hook.ifindex = ifindex; 653 tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state); 654 if (!ASSERT_GE(tc_prog_fd, 0, "bpf_program__fd")) 655 goto done; 656 if (attach_tc_prog(&tc_hook, tc_prog_fd, -1)) 657 goto done; 658 659 /* attach xdp prog to tunnel dev */ 660 xdp_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state_xdp); 661 if (!ASSERT_GE(xdp_prog_fd, 0, "bpf_program__fd")) 662 goto done; 663 err = bpf_xdp_attach(ifindex, xdp_prog_fd, XDP_FLAGS_REPLACE, &opts); 664 if (!ASSERT_OK(err, "bpf_xdp_attach")) 665 goto done; 666 667 /* ping from at_ns0 namespace test */ 668 nstoken = open_netns("at_ns0"); 669 err = test_ping(AF_INET, IP4_ADDR_TUNL_DEV1); 670 close_netns(nstoken); 671 if (!ASSERT_OK(err, "test_ping")) 672 goto done; 673 674 if (!ASSERT_EQ(skel->bss->xfrm_reqid, 1, "req_id")) 675 goto done; 676 if (!ASSERT_EQ(skel->bss->xfrm_spi, XFRM_SPI_IN_TO_OUT, "spi")) 677 goto done; 678 if (!ASSERT_EQ(skel->bss->xfrm_remote_ip, 0xac100164, "remote_ip")) 679 goto done; 680 if (!ASSERT_EQ(skel->bss->xfrm_replay_window, 42, "replay_window")) 681 goto done; 682 683 done: 684 delete_xfrm_tunnel(); 685 if (skel) 686 test_tunnel_kern__destroy(skel); 687 } 688 689 #define RUN_TEST(name, ...) \ 690 ({ \ 691 if (test__start_subtest(#name)) { \ 692 config_device(); \ 693 test_ ## name(__VA_ARGS__); \ 694 cleanup(); \ 695 } \ 696 }) 697 698 static void *test_tunnel_run_tests(void *arg) 699 { 700 RUN_TEST(vxlan_tunnel); 701 RUN_TEST(ip6vxlan_tunnel); 702 RUN_TEST(ipip_tunnel, NONE); 703 RUN_TEST(ipip_tunnel, FOU); 704 RUN_TEST(ipip_tunnel, GUE); 705 RUN_TEST(xfrm_tunnel); 706 707 return NULL; 708 } 709 710 void test_tunnel(void) 711 { 712 pthread_t test_thread; 713 int err; 714 715 /* Run the tests in their own thread to isolate the namespace changes 716 * so they do not affect the environment of other tests. 717 * (specifically needed because of unshare(CLONE_NEWNS) in open_netns()) 718 */ 719 err = pthread_create(&test_thread, NULL, &test_tunnel_run_tests, NULL); 720 if (ASSERT_OK(err, "pthread_create")) 721 ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join"); 722 } 723