@@ -134,6 +134,7 @@ static const char * const link_type_name[] = {
134
134
[BPF_LINK_TYPE_KPROBE_MULTI ] = "kprobe_multi" ,
135
135
[BPF_LINK_TYPE_STRUCT_OPS ] = "struct_ops" ,
136
136
[BPF_LINK_TYPE_NETFILTER ] = "netfilter" ,
137
+ [BPF_LINK_TYPE_TCX ] = "tcx" ,
137
138
};
138
139
139
140
static const char * const map_type_name [] = {
@@ -11854,11 +11855,10 @@ static int attach_lsm(const struct bpf_program *prog, long cookie, struct bpf_li
11854
11855
}
11855
11856
11856
11857
static 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 )
11859
11861
{
11860
- DECLARE_LIBBPF_OPTS (bpf_link_create_opts , opts ,
11861
- .target_btf_id = btf_id );
11862
11862
enum bpf_attach_type attach_type ;
11863
11863
char errmsg [STRERR_BUFSIZE ];
11864
11864
struct bpf_link * link ;
@@ -11876,7 +11876,7 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
11876
11876
link -> detach = & bpf_link__detach_fd ;
11877
11877
11878
11878
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 );
11880
11880
if (link_fd < 0 ) {
11881
11881
link_fd = - errno ;
11882
11882
free (link );
@@ -11892,19 +11892,54 @@ bpf_program__attach_fd(const struct bpf_program *prog, int target_fd, int btf_id
11892
11892
struct bpf_link *
11893
11893
bpf_program__attach_cgroup (const struct bpf_program * prog , int cgroup_fd )
11894
11894
{
11895
- return bpf_program__attach_fd (prog , cgroup_fd , 0 , "cgroup" );
11895
+ return bpf_program_attach_fd (prog , cgroup_fd , "cgroup" , NULL );
11896
11896
}
11897
11897
11898
11898
struct bpf_link *
11899
11899
bpf_program__attach_netns (const struct bpf_program * prog , int netns_fd )
11900
11900
{
11901
- return bpf_program__attach_fd (prog , netns_fd , 0 , "netns" );
11901
+ return bpf_program_attach_fd (prog , netns_fd , "netns" , NULL );
11902
11902
}
11903
11903
11904
11904
struct bpf_link * bpf_program__attach_xdp (const struct bpf_program * prog , int ifindex )
11905
11905
{
11906
11906
/* 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 );
11908
11943
}
11909
11944
11910
11945
struct 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,
11926
11961
}
11927
11962
11928
11963
if (target_fd ) {
11964
+ LIBBPF_OPTS (bpf_link_create_opts , target_opts );
11965
+
11929
11966
btf_id = libbpf_find_prog_btf_id (attach_func_name , target_fd );
11930
11967
if (btf_id < 0 )
11931
11968
return libbpf_err_ptr (btf_id );
11932
11969
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 );
11934
11974
} else {
11935
11975
/* no target, so use raw_tracepoint_open for compatibility
11936
11976
* with old kernels
0 commit comments