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

selftests/bpf: Add tc helpers

The test_tunnel.c file defines small fonctions to easily attach eBPF
programs to tc hooks, either on egress, ingress or both.

Create a shared helper in network_helpers.c so that other tests can
benefit from it.

Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20251027-tc_tunnel-v3-1-505c12019f9d@bootlin.com

authored by

Alexis Lothoré (eBPF Foundation) and committed by
Martin KaFai Lau
1d5137c8 54c134f3

+74 -93
+44
tools/testing/selftests/bpf/network_helpers.c
··· 766 766 return err; 767 767 } 768 768 769 + int tc_prog_attach(const char *dev, int ingress_fd, int egress_fd) 770 + { 771 + int ifindex, ret; 772 + 773 + if (!ASSERT_TRUE(ingress_fd >= 0 || egress_fd >= 0, 774 + "at least one program fd is valid")) 775 + return -1; 776 + 777 + ifindex = if_nametoindex(dev); 778 + if (!ASSERT_NEQ(ifindex, 0, "get ifindex")) 779 + return -1; 780 + 781 + DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex, 782 + .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS); 783 + DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1, 784 + .priority = 1, .prog_fd = ingress_fd); 785 + DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1, 786 + .priority = 1, .prog_fd = egress_fd); 787 + 788 + ret = bpf_tc_hook_create(&hook); 789 + if (!ASSERT_OK(ret, "create tc hook")) 790 + return ret; 791 + 792 + if (ingress_fd >= 0) { 793 + hook.attach_point = BPF_TC_INGRESS; 794 + ret = bpf_tc_attach(&hook, &opts1); 795 + if (!ASSERT_OK(ret, "bpf_tc_attach")) { 796 + bpf_tc_hook_destroy(&hook); 797 + return ret; 798 + } 799 + } 800 + 801 + if (egress_fd >= 0) { 802 + hook.attach_point = BPF_TC_EGRESS; 803 + ret = bpf_tc_attach(&hook, &opts2); 804 + if (!ASSERT_OK(ret, "bpf_tc_attach")) { 805 + bpf_tc_hook_destroy(&hook); 806 + return ret; 807 + } 808 + } 809 + 810 + return 0; 811 + } 812 + 769 813 #ifdef TRAFFIC_MONITOR 770 814 struct tmonitor_ctx { 771 815 pcap_t *pcap;
+16
tools/testing/selftests/bpf/network_helpers.h
··· 255 255 256 256 typedef int (*tm_print_fn_t)(const char *format, va_list args); 257 257 258 + /** 259 + * tc_prog_attach - attach BPF program(s) to an interface 260 + * 261 + * Takes file descriptors pointing to at least one, at most two BPF 262 + * programs, and attach those programs to an interface ingress, egress or 263 + * both. 264 + * 265 + * @dev: string containing the interface name 266 + * @ingress_fd: file descriptor of the program to attach to interface ingress 267 + * @egress_fd: file descriptor of the program to attach to interface egress 268 + * 269 + * Returns 0 on success, -1 if no valid file descriptor has been found, if 270 + * the interface name is invalid or if an error ocurred during attach. 271 + */ 272 + int tc_prog_attach(const char *dev, int ingress_fd, int egress_fd); 273 + 258 274 #ifdef TRAFFIC_MONITOR 259 275 struct tmonitor_ctx *traffic_monitor_start(const char *netns, const char *test_name, 260 276 const char *subtest_name);
+14 -93
tools/testing/selftests/bpf/prog_tests/test_tunnel.c
··· 534 534 close_netns(nstoken); 535 535 } 536 536 537 - static int attach_tc_prog(int ifindex, int igr_fd, int egr_fd) 538 - { 539 - DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex, 540 - .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS); 541 - DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1, 542 - .priority = 1, .prog_fd = igr_fd); 543 - DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1, 544 - .priority = 1, .prog_fd = egr_fd); 545 - int ret; 546 - 547 - ret = bpf_tc_hook_create(&hook); 548 - if (!ASSERT_OK(ret, "create tc hook")) 549 - return ret; 550 - 551 - if (igr_fd >= 0) { 552 - hook.attach_point = BPF_TC_INGRESS; 553 - ret = bpf_tc_attach(&hook, &opts1); 554 - if (!ASSERT_OK(ret, "bpf_tc_attach")) { 555 - bpf_tc_hook_destroy(&hook); 556 - return ret; 557 - } 558 - } 559 - 560 - if (egr_fd >= 0) { 561 - hook.attach_point = BPF_TC_EGRESS; 562 - ret = bpf_tc_attach(&hook, &opts2); 563 - if (!ASSERT_OK(ret, "bpf_tc_attach")) { 564 - bpf_tc_hook_destroy(&hook); 565 - return ret; 566 - } 567 - } 568 - 569 - return 0; 570 - } 571 - 572 - static int generic_attach(const char *dev, int igr_fd, int egr_fd) 573 - { 574 - int ifindex; 575 - 576 - if (!ASSERT_OK_FD(igr_fd, "check ingress fd")) 577 - return -1; 578 - if (!ASSERT_OK_FD(egr_fd, "check egress fd")) 579 - return -1; 580 - 581 - ifindex = if_nametoindex(dev); 582 - if (!ASSERT_NEQ(ifindex, 0, "get ifindex")) 583 - return -1; 584 - 585 - return attach_tc_prog(ifindex, igr_fd, egr_fd); 586 - } 587 - 588 - static int generic_attach_igr(const char *dev, int igr_fd) 589 - { 590 - int ifindex; 591 - 592 - if (!ASSERT_OK_FD(igr_fd, "check ingress fd")) 593 - return -1; 594 - 595 - ifindex = if_nametoindex(dev); 596 - if (!ASSERT_NEQ(ifindex, 0, "get ifindex")) 597 - return -1; 598 - 599 - return attach_tc_prog(ifindex, igr_fd, -1); 600 - } 601 - 602 - static int generic_attach_egr(const char *dev, int egr_fd) 603 - { 604 - int ifindex; 605 - 606 - if (!ASSERT_OK_FD(egr_fd, "check egress fd")) 607 - return -1; 608 - 609 - ifindex = if_nametoindex(dev); 610 - if (!ASSERT_NEQ(ifindex, 0, "get ifindex")) 611 - return -1; 612 - 613 - return attach_tc_prog(ifindex, -1, egr_fd); 614 - } 615 - 616 537 static void test_vxlan_tunnel(void) 617 538 { 618 539 struct test_tunnel_kern *skel = NULL; ··· 556 635 goto done; 557 636 get_src_prog_fd = bpf_program__fd(skel->progs.vxlan_get_tunnel_src); 558 637 set_src_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_src); 559 - if (generic_attach(VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 638 + if (tc_prog_attach(VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 560 639 goto done; 561 640 562 641 /* load and attach bpf prog to veth dev tc hook point */ 563 642 set_dst_prog_fd = bpf_program__fd(skel->progs.veth_set_outer_dst); 564 - if (generic_attach_igr("veth1", set_dst_prog_fd)) 643 + if (tc_prog_attach("veth1", set_dst_prog_fd, -1)) 565 644 goto done; 566 645 567 646 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */ ··· 569 648 if (!ASSERT_OK_PTR(nstoken, "setns src")) 570 649 goto done; 571 650 set_dst_prog_fd = bpf_program__fd(skel->progs.vxlan_set_tunnel_dst); 572 - if (generic_attach_egr(VXLAN_TUNL_DEV0, set_dst_prog_fd)) 651 + if (tc_prog_attach(VXLAN_TUNL_DEV0, -1, set_dst_prog_fd)) 573 652 goto done; 574 653 close_netns(nstoken); 575 654 ··· 616 695 goto done; 617 696 get_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_get_tunnel_src); 618 697 set_src_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_src); 619 - if (generic_attach(IP6VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 698 + if (tc_prog_attach(IP6VXLAN_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 620 699 goto done; 621 700 622 701 /* load and attach prog set_md to tunnel dev tc hook point at_ns0 */ ··· 624 703 if (!ASSERT_OK_PTR(nstoken, "setns src")) 625 704 goto done; 626 705 set_dst_prog_fd = bpf_program__fd(skel->progs.ip6vxlan_set_tunnel_dst); 627 - if (generic_attach_egr(IP6VXLAN_TUNL_DEV0, set_dst_prog_fd)) 706 + if (tc_prog_attach(IP6VXLAN_TUNL_DEV0, -1, set_dst_prog_fd)) 628 707 goto done; 629 708 close_netns(nstoken); 630 709 ··· 685 764 skel->progs.ipip_set_tunnel); 686 765 } 687 766 688 - if (generic_attach(IPIP_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 767 + if (tc_prog_attach(IPIP_TUNL_DEV1, get_src_prog_fd, set_src_prog_fd)) 689 768 goto done; 690 769 691 770 ping_dev0(); ··· 718 797 719 798 /* attach tc prog to tunnel dev */ 720 799 tc_prog_fd = bpf_program__fd(skel->progs.xfrm_get_state); 721 - if (generic_attach_igr("veth1", tc_prog_fd)) 800 + if (tc_prog_attach("veth1", tc_prog_fd, -1)) 722 801 goto done; 723 802 724 803 /* attach xdp prog to tunnel dev */ ··· 791 870 if (!ASSERT_OK(err, "add tunnel")) 792 871 goto done; 793 872 794 - if (generic_attach(GRE_TUNL_DEV1, get_fd, set_fd)) 873 + if (tc_prog_attach(GRE_TUNL_DEV1, get_fd, set_fd)) 795 874 goto done; 796 875 797 876 ping_dev0(); ··· 832 911 833 912 set_fd = bpf_program__fd(skel->progs.ip6gretap_set_tunnel); 834 913 get_fd = bpf_program__fd(skel->progs.ip6gretap_get_tunnel); 835 - if (generic_attach(IP6GRE_TUNL_DEV1, get_fd, set_fd)) 914 + if (tc_prog_attach(IP6GRE_TUNL_DEV1, get_fd, set_fd)) 836 915 goto done; 837 916 838 917 ping6_veth0(); ··· 875 954 876 955 set_fd = bpf_program__fd(skel->progs.erspan_set_tunnel); 877 956 get_fd = bpf_program__fd(skel->progs.erspan_get_tunnel); 878 - if (generic_attach(ERSPAN_TUNL_DEV1, get_fd, set_fd)) 957 + if (tc_prog_attach(ERSPAN_TUNL_DEV1, get_fd, set_fd)) 879 958 goto done; 880 959 881 960 ping_dev0(); ··· 911 990 912 991 set_fd = bpf_program__fd(skel->progs.ip4ip6erspan_set_tunnel); 913 992 get_fd = bpf_program__fd(skel->progs.ip4ip6erspan_get_tunnel); 914 - if (generic_attach(IP6ERSPAN_TUNL_DEV1, get_fd, set_fd)) 993 + if (tc_prog_attach(IP6ERSPAN_TUNL_DEV1, get_fd, set_fd)) 915 994 goto done; 916 995 917 996 ping6_veth0(); ··· 938 1017 939 1018 set_fd = bpf_program__fd(skel->progs.geneve_set_tunnel); 940 1019 get_fd = bpf_program__fd(skel->progs.geneve_get_tunnel); 941 - if (generic_attach(GENEVE_TUNL_DEV1, get_fd, set_fd)) 1020 + if (tc_prog_attach(GENEVE_TUNL_DEV1, get_fd, set_fd)) 942 1021 goto done; 943 1022 944 1023 ping_dev0(); ··· 965 1044 966 1045 set_fd = bpf_program__fd(skel->progs.ip6geneve_set_tunnel); 967 1046 get_fd = bpf_program__fd(skel->progs.ip6geneve_get_tunnel); 968 - if (generic_attach(IP6GENEVE_TUNL_DEV1, get_fd, set_fd)) 1047 + if (tc_prog_attach(IP6GENEVE_TUNL_DEV1, get_fd, set_fd)) 969 1048 goto done; 970 1049 971 1050 ping_dev0(); ··· 1004 1083 get_fd = bpf_program__fd(skel->progs.ip6ip6_get_tunnel); 1005 1084 break; 1006 1085 } 1007 - if (generic_attach(IP6TNL_TUNL_DEV1, get_fd, set_fd)) 1086 + if (tc_prog_attach(IP6TNL_TUNL_DEV1, get_fd, set_fd)) 1008 1087 goto done; 1009 1088 1010 1089 ping6_veth0();