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.

bpftool: Add 'prepend' option for tcx attach to insert at chain start

Add support for the 'prepend' option when attaching tcx_ingress and
tcx_egress programs. This option allows inserting a BPF program at
the beginning of the TCX chain instead of appending it at the end.

The implementation uses BPF_F_BEFORE flag which automatically inserts
the program at the beginning of the chain when no relative reference
is specified.

This change includes:
- Modify do_attach_tcx() to support prepend insertion using BPF_F_BEFORE
- Update documentation to describe the new 'prepend' option
- Add bash completion support for the 'prepend' option on tcx attach types
- Add example usage in the documentation
- Add validation to reject 'overwrite' for non-XDP attach types

The 'prepend' option is only valid for tcx_ingress and tcx_egress attach
types. For XDP attach types, the existing 'overwrite' option remains
available.

Example usage:
# bpftool net attach tcx_ingress name tc_prog dev lo prepend

This feature is useful when the order of program execution in the TCX
chain matters and users need to ensure certain programs run first.

Co-developed-by: Siwan Kim <siwan.kim@navercorp.com>
Signed-off-by: Siwan Kim <siwan.kim@navercorp.com>
Signed-off-by: Gyutae Bae <gyutae.bae@navercorp.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Quentin Monnet <qmo@kernel.org>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20260112034516.22723-1-gyutae.opensource@navercorp.com

authored by

Gyutae Bae and committed by
Andrii Nakryiko
999b2395 4787eaf7

+58 -12
+23 -7
tools/bpf/bpftool/Documentation/bpftool-net.rst
··· 24 24 ============ 25 25 26 26 | **bpftool** **net** { **show** | **list** } [ **dev** *NAME* ] 27 - | **bpftool** **net attach** *ATTACH_TYPE* *PROG* **dev** *NAME* [ **overwrite** ] 27 + | **bpftool** **net attach** *ATTACH_TYPE* *PROG* **dev** *NAME* [ **overwrite** | **prepend** ] 28 28 | **bpftool** **net detach** *ATTACH_TYPE* **dev** *NAME* 29 29 | **bpftool** **net help** 30 30 | ··· 58 58 then all bpf programs attached to non clsact qdiscs, and finally all bpf 59 59 programs attached to root and clsact qdisc. 60 60 61 - bpftool net attach *ATTACH_TYPE* *PROG* dev *NAME* [ overwrite ] 61 + bpftool net attach *ATTACH_TYPE* *PROG* dev *NAME* [ overwrite | prepend ] 62 62 Attach bpf program *PROG* to network interface *NAME* with type specified 63 - by *ATTACH_TYPE*. Previously attached bpf program can be replaced by the 64 - command used with **overwrite** option. Currently, only XDP-related modes 65 - are supported for *ATTACH_TYPE*. 63 + by *ATTACH_TYPE*. 66 64 67 65 *ATTACH_TYPE* can be of: 68 66 **xdp** - try native XDP and fallback to generic XDP if NIC driver does not support it; ··· 70 72 **tcx_ingress** - Ingress TCX. runs on ingress net traffic; 71 73 **tcx_egress** - Egress TCX. runs on egress net traffic; 72 74 75 + For XDP-related attach types (**xdp**, **xdpgeneric**, **xdpdrv**, 76 + **xdpoffload**), the **overwrite** option can be used to replace a 77 + previously attached bpf program. 78 + 79 + For **tcx_ingress** and **tcx_egress** attach types, the **prepend** option 80 + can be used to attach the program at the beginning of the chain instead of 81 + at the end. 82 + 73 83 bpftool net detach *ATTACH_TYPE* dev *NAME* 74 84 Detach bpf program attached to network interface *NAME* with type specified 75 85 by *ATTACH_TYPE*. To detach bpf program, same *ATTACH_TYPE* previously used 76 - for attach must be specified. Currently, only XDP-related modes are 77 - supported for *ATTACH_TYPE*. 86 + for attach must be specified. 78 87 79 88 bpftool net help 80 89 Print short help message. ··· 194 189 :: 195 190 196 191 tc: 192 + lo(1) tcx/ingress tc_prog prog_id 29 193 + 194 + | 195 + | **# bpftool net attach tcx_ingress name tc_prog2 dev lo prepend** 196 + | **# bpftool net** 197 + | 198 + 199 + :: 200 + 201 + tc: 202 + lo(1) tcx/ingress tc_prog2 prog_id 30 197 203 lo(1) tcx/ingress tc_prog prog_id 29 198 204 199 205 |
+8 -1
tools/bpf/bpftool/bash-completion/bpftool
··· 1142 1142 return 0 1143 1143 ;; 1144 1144 8) 1145 - _bpftool_once_attr 'overwrite' 1145 + case ${words[3]} in 1146 + tcx_ingress|tcx_egress) 1147 + _bpftool_once_attr 'prepend' 1148 + ;; 1149 + *) 1150 + _bpftool_once_attr 'overwrite' 1151 + ;; 1152 + esac 1146 1153 return 0 1147 1154 ;; 1148 1155 esac
+27 -4
tools/bpf/bpftool/net.c
··· 666 666 } 667 667 } 668 668 669 - static int do_attach_tcx(int progfd, enum net_attach_type attach_type, int ifindex) 669 + static int do_attach_tcx(int progfd, enum net_attach_type attach_type, int ifindex, bool prepend) 670 670 { 671 671 int type = get_tcx_type(attach_type); 672 672 673 + if (prepend) { 674 + LIBBPF_OPTS(bpf_prog_attach_opts, opts, 675 + .flags = BPF_F_BEFORE 676 + ); 677 + return bpf_prog_attach_opts(progfd, ifindex, type, &opts); 678 + } 673 679 return bpf_prog_attach(progfd, ifindex, type, 0); 674 680 } 675 681 ··· 691 685 enum net_attach_type attach_type; 692 686 int progfd, ifindex, err = 0; 693 687 bool overwrite = false; 688 + bool prepend = false; 694 689 695 690 /* parse attach args */ 696 691 if (!REQ_ARGS(5)) ··· 716 709 717 710 if (argc) { 718 711 if (is_prefix(*argv, "overwrite")) { 712 + if (attach_type != NET_ATTACH_TYPE_XDP && 713 + attach_type != NET_ATTACH_TYPE_XDP_GENERIC && 714 + attach_type != NET_ATTACH_TYPE_XDP_DRIVER && 715 + attach_type != NET_ATTACH_TYPE_XDP_OFFLOAD) { 716 + p_err("'overwrite' is only supported for xdp types"); 717 + err = -EINVAL; 718 + goto cleanup; 719 + } 719 720 overwrite = true; 721 + } else if (is_prefix(*argv, "prepend")) { 722 + if (attach_type != NET_ATTACH_TYPE_TCX_INGRESS && 723 + attach_type != NET_ATTACH_TYPE_TCX_EGRESS) { 724 + p_err("'prepend' is only supported for tcx_ingress/tcx_egress"); 725 + err = -EINVAL; 726 + goto cleanup; 727 + } 728 + prepend = true; 720 729 } else { 721 - p_err("expected 'overwrite', got: '%s'?", *argv); 730 + p_err("expected 'overwrite' or 'prepend', got: '%s'?", *argv); 722 731 err = -EINVAL; 723 732 goto cleanup; 724 733 } ··· 751 728 /* attach tcx prog */ 752 729 case NET_ATTACH_TYPE_TCX_INGRESS: 753 730 case NET_ATTACH_TYPE_TCX_EGRESS: 754 - err = do_attach_tcx(progfd, attach_type, ifindex); 731 + err = do_attach_tcx(progfd, attach_type, ifindex, prepend); 755 732 break; 756 733 default: 757 734 break; ··· 1008 985 1009 986 fprintf(stderr, 1010 987 "Usage: %1$s %2$s { show | list } [dev <devname>]\n" 1011 - " %1$s %2$s attach ATTACH_TYPE PROG dev <devname> [ overwrite ]\n" 988 + " %1$s %2$s attach ATTACH_TYPE PROG dev <devname> [ overwrite | prepend ]\n" 1012 989 " %1$s %2$s detach ATTACH_TYPE dev <devname>\n" 1013 990 " %1$s %2$s help\n" 1014 991 "\n"