|
50 | 50 | */
|
51 | 51 |
|
52 | 52 | #include <arpa/inet.h>
|
| 53 | +#include <linux/if_link.h> |
53 | 54 | #include <linux/if_tun.h>
|
54 | 55 | #include <linux/limits.h>
|
55 | 56 | #include <linux/sysctl.h>
|
|
92 | 93 | #define IPIP_TUNL_DEV0 "ipip00"
|
93 | 94 | #define IPIP_TUNL_DEV1 "ipip11"
|
94 | 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 | + |
95 | 101 | #define PING_ARGS "-i 0.01 -c 3 -w 10 -q"
|
96 | 102 |
|
97 | 103 | static int config_device(void)
|
@@ -264,6 +270,92 @@ static void delete_ipip_tunnel(void)
|
264 | 270 | SYS_NOFAIL("ip fou del port 5555 2> /dev/null");
|
265 | 271 | }
|
266 | 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 2> /dev/null", |
| 350 | + IP4_ADDR_TUNL_DEV1, IP4_ADDR_TUNL_DEV0); |
| 351 | + SYS_NOFAIL("ip xfrm policy delete dir in src %s/32 dst %s/32 2> /dev/null", |
| 352 | + IP4_ADDR_TUNL_DEV0, IP4_ADDR_TUNL_DEV1); |
| 353 | + SYS_NOFAIL("ip xfrm state delete src %s dst %s proto esp spi %d 2> /dev/null", |
| 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 2> /dev/null", |
| 356 | + IP4_ADDR1_VETH1, IP4_ADDR_VETH0, XFRM_SPI_OUT_TO_IN); |
| 357 | +} |
| 358 | + |
267 | 359 | static int test_ping(int family, const char *addr)
|
268 | 360 | {
|
269 | 361 | SYS(fail, "%s %s %s > /dev/null", ping_command(family), PING_ARGS, addr);
|
@@ -532,25 +624,85 @@ static void test_ipip_tunnel(enum ipip_encap encap)
|
532 | 624 | test_tunnel_kern__destroy(skel);
|
533 | 625 | }
|
534 | 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 | + |
535 | 689 | #define RUN_TEST(name, ...) \
|
536 | 690 | ({ \
|
537 | 691 | if (test__start_subtest(#name)) { \
|
| 692 | + config_device(); \ |
538 | 693 | test_ ## name(__VA_ARGS__); \
|
| 694 | + cleanup(); \ |
539 | 695 | } \
|
540 | 696 | })
|
541 | 697 |
|
542 | 698 | static void *test_tunnel_run_tests(void *arg)
|
543 | 699 | {
|
544 |
| - cleanup(); |
545 |
| - config_device(); |
546 |
| - |
547 | 700 | RUN_TEST(vxlan_tunnel);
|
548 | 701 | RUN_TEST(ip6vxlan_tunnel);
|
549 | 702 | RUN_TEST(ipip_tunnel, NONE);
|
550 | 703 | RUN_TEST(ipip_tunnel, FOU);
|
551 | 704 | RUN_TEST(ipip_tunnel, GUE);
|
552 |
| - |
553 |
| - cleanup(); |
| 705 | + RUN_TEST(xfrm_tunnel); |
554 | 706 |
|
555 | 707 | return NULL;
|
556 | 708 | }
|
|
0 commit comments