@@ -134,6 +134,7 @@ static const char * const link_type_name[] = {
134134 [BPF_LINK_TYPE_KPROBE_MULTI ] = "kprobe_multi" ,
135135 [BPF_LINK_TYPE_STRUCT_OPS ] = "struct_ops" ,
136136 [BPF_LINK_TYPE_NETFILTER ] = "netfilter" ,
137+ [BPF_LINK_TYPE_TCX ] = "tcx" ,
137138};
138139
139140static const char * const map_type_name [] = {
@@ -11854,11 +11855,10 @@ static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_li
1185411855}
1185511856
1185611857static struct bpf_link *
11857- bpf_program__attach_fd (const struct bpf_program * prog , int target_fd , int btf_id ,
11858- const char * target_name )
11858+ bpf_program_attach_fd (const struct bpf_program * prog ,
11859+ int target_fd , const char * target_name ,
11860+ const struct bpf_link_create_opts * opts )
1185911861{
11860- DECLARE_LIBBPF_OPTS (bpf_link_create_opts , opts ,
11861- .target_btf_id = btf_id );
1186211862 enum bpf_attach_type attach_type ;
1186311863 char errmsg [STRERR_BUFSIZE ];
1186411864 struct bpf_link * link ;
@@ -11876,7 +11876,7 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1187611876 link -> detach = & bpf_link__detach_fd ;
1187711877
1187811878 attach_type = bpf_program__expected_attach_type (prog );
11879- link_fd = bpf_link_create (prog_fd , target_fd , attach_type , & opts );
11879+ link_fd = bpf_link_create (prog_fd , target_fd , attach_type , opts );
1188011880 if (link_fd < 0 ) {
1188111881 link_fd = - errno ;
1188211882 free (link );
@@ -11892,19 +11892,54 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
1189211892struct bpf_link *
1189311893bpf_program__attach_cgroup (const struct bpf_program * prog , int cgroup_fd )
1189411894{
11895- return bpf_program__attach_fd (prog , cgroup_fd , 0 , "cgroup" );
11895+ return bpf_program_attach_fd (prog , cgroup_fd , "cgroup" , NULL );
1189611896}
1189711897
1189811898struct bpf_link *
1189911899bpf_program__attach_netns (const struct bpf_program * prog , int netns_fd )
1190011900{
11901- return bpf_program__attach_fd (prog , netns_fd , 0 , "netns" );
11901+ return bpf_program_attach_fd (prog , netns_fd , "netns" , NULL );
1190211902}
1190311903
1190411904struct bpf_link * bpf_program__attach_xdp (const struct bpf_program * prog , int ifindex )
1190511905{
1190611906 /* target_fd/target_ifindex use the same field in LINK_CREATE */
11907- return bpf_program__attach_fd (prog , ifindex , 0 , "xdp" );
11907+ return bpf_program_attach_fd (prog , ifindex , "xdp" , NULL );
11908+ }
11909+
11910+ struct bpf_link *
11911+ bpf_program__attach_tcx (const struct bpf_program * prog , int ifindex ,
11912+ const struct bpf_tcx_opts * opts )
11913+ {
11914+ LIBBPF_OPTS (bpf_link_create_opts , link_create_opts );
11915+ __u32 relative_id ;
11916+ int relative_fd ;
11917+
11918+ if (!OPTS_VALID (opts , bpf_tcx_opts ))
11919+ return libbpf_err_ptr (- EINVAL );
11920+
11921+ relative_id = OPTS_GET (opts , relative_id , 0 );
11922+ relative_fd = OPTS_GET (opts , relative_fd , 0 );
11923+
11924+ /* validate we don't have unexpected combinations of non-zero fields */
11925+ if (!ifindex ) {
11926+ pr_warn ("prog '%s': target netdevice ifindex cannot be zero\n" ,
11927+ prog -> name );
11928+ return libbpf_err_ptr (- EINVAL );
11929+ }
11930+ if (relative_fd && relative_id ) {
11931+ pr_warn ("prog '%s': relative_fd and relative_id cannot be set at the same time\n" ,
11932+ prog -> name );
11933+ return libbpf_err_ptr (- EINVAL );
11934+ }
11935+
11936+ link_create_opts .tcx .expected_revision = OPTS_GET (opts , expected_revision , 0 );
11937+ link_create_opts .tcx .relative_fd = relative_fd ;
11938+ link_create_opts .tcx .relative_id = relative_id ;
11939+ link_create_opts .flags = OPTS_GET (opts , flags , 0 );
11940+
11941+ /* target_fd/target_ifindex use the same field in LINK_CREATE */
11942+ return bpf_program_attach_fd (prog , ifindex , "tcx" , & link_create_opts );
1190811943}
1190911944
1191011945struct bpf_link * bpf_program__attach_freplace (const struct bpf_program * prog ,
@@ -11926,11 +11961,16 @@ struct bpf_link *bpf_program__attach_freplace(const struct bpf_program *prog,
1192611961 }
1192711962
1192811963 if (target_fd ) {
11964+ LIBBPF_OPTS (bpf_link_create_opts , target_opts );
11965+
1192911966 btf_id = libbpf_find_prog_btf_id (attach_func_name , target_fd );
1193011967 if (btf_id < 0 )
1193111968 return libbpf_err_ptr (btf_id );
1193211969
11933- return bpf_program__attach_fd (prog , target_fd , btf_id , "freplace" );
11970+ target_opts .target_btf_id = btf_id ;
11971+
11972+ return bpf_program_attach_fd (prog , target_fd , "freplace" ,
11973+ & target_opts );
1193411974 } else {
1193511975 /* no target, so use raw_tracepoint_open for compatibility
1193611976 * with old kernels
0 commit comments