diff mbox series

[v2,bpf-next,2/4] bpftool: add net attach/detach command to tcx prog

Message ID 20240717174749.1511366-1-chen.dylane@gmail.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpftool: add tcx subcommand in net | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for bpf-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7 this patch: 7
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 7 maintainers not CCed: kpsingh@kernel.org haoluo@google.com hawk@kernel.org kuba@kernel.org netdev@vger.kernel.org sdf@fomichev.me jolsa@kernel.org
netdev/build_clang success Errors and warnings before: 7 this patch: 7
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 7 this patch: 7
netdev/checkpatch warning WARNING: line length of 83 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18

Commit Message

Tao Chen July 17, 2024, 5:47 p.m. UTC
Now, attach/detach tcx prog supported in libbpf, so we can add new
command 'bpftool attach/detach tcx' to attach tcx prog with bpftool
for user.

 # bpftool prog load tc_prog.bpf.o /sys/fs/bpf/tc_prog
 # bpftool prog show
	...
	192: sched_cls  name tc_prog  tag 187aeb611ad00cfc  gpl
	loaded_at 2024-07-11T15:58:16+0800  uid 0
	xlated 152B  jited 97B  memlock 4096B  map_ids 100,99,97
	btf_id 260
 # bpftool net attach tcx_ingress name tc_prog dev lo
 # bpftool net
	...
	tc:
	lo(1) tcx/ingress tc_prog prog_id 29

 # bpftool net detach tcx_ingress dev lo
 # bpftool net
	...
	tc:
 # bpftool net attach tcx_ingress name tc_prog dev lo
 # bpftool net
	tc:
	lo(1) tcx/ingress tc_prog prog_id 29

Test environment: ubuntu_22_04, 6.7.0-060700-generic

Signed-off-by: Tao Chen <chen.dylane@gmail.com>
---
 tools/bpf/bpftool/net.c | 43 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

Comments

Quentin Monnet July 19, 2024, 4:17 p.m. UTC | #1
On 17/07/2024 18:47, Tao Chen wrote:
> Now, attach/detach tcx prog supported in libbpf, so we can add new
> command 'bpftool attach/detach tcx' to attach tcx prog with bpftool
> for user.
> 
>  # bpftool prog load tc_prog.bpf.o /sys/fs/bpf/tc_prog
>  # bpftool prog show
> 	...
> 	192: sched_cls  name tc_prog  tag 187aeb611ad00cfc  gpl
> 	loaded_at 2024-07-11T15:58:16+0800  uid 0
> 	xlated 152B  jited 97B  memlock 4096B  map_ids 100,99,97
> 	btf_id 260
>  # bpftool net attach tcx_ingress name tc_prog dev lo
>  # bpftool net
> 	...
> 	tc:
> 	lo(1) tcx/ingress tc_prog prog_id 29
> 
>  # bpftool net detach tcx_ingress dev lo
>  # bpftool net
> 	...
> 	tc:
>  # bpftool net attach tcx_ingress name tc_prog dev lo
>  # bpftool net
> 	tc:
> 	lo(1) tcx/ingress tc_prog prog_id 29
> 
> Test environment: ubuntu_22_04, 6.7.0-060700-generic
> 
> Signed-off-by: Tao Chen <chen.dylane@gmail.com>
> ---
>  tools/bpf/bpftool/net.c | 43 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
> index 1b9f4225b394..60b0af40109a 100644
> --- a/tools/bpf/bpftool/net.c
> +++ b/tools/bpf/bpftool/net.c
> @@ -67,6 +67,8 @@ enum net_attach_type {
>  	NET_ATTACH_TYPE_XDP_GENERIC,
>  	NET_ATTACH_TYPE_XDP_DRIVER,
>  	NET_ATTACH_TYPE_XDP_OFFLOAD,
> +	NET_ATTACH_TYPE_TCX_INGRESS,
> +	NET_ATTACH_TYPE_TCX_EGRESS,
>  };
>  
>  static const char * const attach_type_strings[] = {
> @@ -74,6 +76,8 @@ static const char * const attach_type_strings[] = {
>  	[NET_ATTACH_TYPE_XDP_GENERIC]	= "xdpgeneric",
>  	[NET_ATTACH_TYPE_XDP_DRIVER]	= "xdpdrv",
>  	[NET_ATTACH_TYPE_XDP_OFFLOAD]	= "xdpoffload",
> +	[NET_ATTACH_TYPE_TCX_INGRESS]	= "tcx_ingress",
> +	[NET_ATTACH_TYPE_TCX_EGRESS]	= "tcx_egress",
>  };
>  
>  static const char * const attach_loc_strings[] = {
> @@ -647,6 +651,32 @@ static int do_attach_detach_xdp(int progfd, enum net_attach_type attach_type,
>  	return bpf_xdp_attach(ifindex, progfd, flags, NULL);
>  }
>  
> +static int get_tcx_type(enum net_attach_type attach_type)
> +{
> +	switch (attach_type) {
> +	case NET_ATTACH_TYPE_TCX_INGRESS:
> +		return BPF_TCX_INGRESS;
> +	case NET_ATTACH_TYPE_TCX_EGRESS:
> +		return BPF_TCX_EGRESS;
> +	default:
> +		return __MAX_BPF_ATTACH_TYPE;


Can we return -1 here instead, please? In the current code, we validate
the attach_type before entering this function and the "default" case is
never reached, it's only here to discard compiler's warning. But if we
ever reuse this function elsewhere, this could cause bugs: if the header
file used for compiling the bpftool binary is not in sync with the
header corresponding to the running kernel, __MAX_BPF_ATTACH_TYPE could
correspond to a newly introduced type, and bpftool/libbpf would try to
use that to attach the program, instead of detecting an error.


> +	}
> +}
> +
> +static int do_attach_tcx(int progfd, enum net_attach_type attach_type, int ifindex)
> +{
> +	int type = get_tcx_type(attach_type);
> +
> +	return bpf_prog_attach(progfd, ifindex, type, 0);
> +}
> +
> +static int do_detach_tcx(int targetfd, enum net_attach_type attach_type)
> +{
> +	int type = get_tcx_type(attach_type);
> +
> +	return bpf_prog_detach(targetfd, type);
> +}
> +
>  static int do_attach(int argc, char **argv)
>  {
>  	enum net_attach_type attach_type;
> @@ -692,6 +722,11 @@ static int do_attach(int argc, char **argv)
>  	case NET_ATTACH_TYPE_XDP_OFFLOAD:
>  		err = do_attach_detach_xdp(progfd, attach_type, ifindex, overwrite);
>  		break;
> +	/* attach tcx prog */
> +	case NET_ATTACH_TYPE_TCX_INGRESS:
> +	case NET_ATTACH_TYPE_TCX_EGRESS:
> +		err = do_attach_tcx(progfd, attach_type, ifindex);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -738,6 +773,11 @@ static int do_detach(int argc, char **argv)
>  		progfd = -1;
>  		err = do_attach_detach_xdp(progfd, attach_type, ifindex, NULL);
>  		break;
> +	/* detach tcx prog */
> +	case NET_ATTACH_TYPE_TCX_INGRESS:
> +	case NET_ATTACH_TYPE_TCX_EGRESS:
> +		err = do_detach_tcx(ifindex, attach_type);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -944,7 +984,8 @@ static int do_help(int argc, char **argv)
>  		"       %1$s %2$s help\n"
>  		"\n"
>  		"       " HELP_SPEC_PROGRAM "\n"
> -		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload }\n"
> +		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload | tcx_ingress\n"
> +		"			 | tcx_egress }\n"

                 ^^^^^^^^^^^^^^^^^^^^^^^
This indent space between the quote and the pipe needs to be spaces
instead of three tabs, please.

The rest of the patches looks good, thank you!

Quentin
Tao Chen July 20, 2024, 9:57 a.m. UTC | #2
在 2024/7/20 00:17, Quentin Monnet 写道:
> On 17/07/2024 18:47, Tao Chen wrote:
>> Now, attach/detach tcx prog supported in libbpf, so we can add new
>> command 'bpftool attach/detach tcx' to attach tcx prog with bpftool
>> for user.
>>
>>   # bpftool prog load tc_prog.bpf.o /sys/fs/bpf/tc_prog
>>   # bpftool prog show
>> 	...
>> 	192: sched_cls  name tc_prog  tag 187aeb611ad00cfc  gpl
>> 	loaded_at 2024-07-11T15:58:16+0800  uid 0
>> 	xlated 152B  jited 97B  memlock 4096B  map_ids 100,99,97
>> 	btf_id 260
>>   # bpftool net attach tcx_ingress name tc_prog dev lo
>>   # bpftool net
>> 	...
>> 	tc:
>> 	lo(1) tcx/ingress tc_prog prog_id 29
>>
>>   # bpftool net detach tcx_ingress dev lo
>>   # bpftool net
>> 	...
>> 	tc:
>>   # bpftool net attach tcx_ingress name tc_prog dev lo
>>   # bpftool net
>> 	tc:
>> 	lo(1) tcx/ingress tc_prog prog_id 29
>>
>> Test environment: ubuntu_22_04, 6.7.0-060700-generic
>>
>> Signed-off-by: Tao Chen <chen.dylane@gmail.com>
>> ---
>>   tools/bpf/bpftool/net.c | 43 ++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 42 insertions(+), 1 deletion(-)
>>
>> diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
>> index 1b9f4225b394..60b0af40109a 100644
>> --- a/tools/bpf/bpftool/net.c
>> +++ b/tools/bpf/bpftool/net.c
>> @@ -67,6 +67,8 @@ enum net_attach_type {
>>   	NET_ATTACH_TYPE_XDP_GENERIC,
>>   	NET_ATTACH_TYPE_XDP_DRIVER,
>>   	NET_ATTACH_TYPE_XDP_OFFLOAD,
>> +	NET_ATTACH_TYPE_TCX_INGRESS,
>> +	NET_ATTACH_TYPE_TCX_EGRESS,
>>   };
>>   
>>   static const char * const attach_type_strings[] = {
>> @@ -74,6 +76,8 @@ static const char * const attach_type_strings[] = {
>>   	[NET_ATTACH_TYPE_XDP_GENERIC]	= "xdpgeneric",
>>   	[NET_ATTACH_TYPE_XDP_DRIVER]	= "xdpdrv",
>>   	[NET_ATTACH_TYPE_XDP_OFFLOAD]	= "xdpoffload",
>> +	[NET_ATTACH_TYPE_TCX_INGRESS]	= "tcx_ingress",
>> +	[NET_ATTACH_TYPE_TCX_EGRESS]	= "tcx_egress",
>>   };
>>   
>>   static const char * const attach_loc_strings[] = {
>> @@ -647,6 +651,32 @@ static int do_attach_detach_xdp(int progfd, enum net_attach_type attach_type,
>>   	return bpf_xdp_attach(ifindex, progfd, flags, NULL);
>>   }
>>   
>> +static int get_tcx_type(enum net_attach_type attach_type)
>> +{
>> +	switch (attach_type) {
>> +	case NET_ATTACH_TYPE_TCX_INGRESS:
>> +		return BPF_TCX_INGRESS;
>> +	case NET_ATTACH_TYPE_TCX_EGRESS:
>> +		return BPF_TCX_EGRESS;
>> +	default:
>> +		return __MAX_BPF_ATTACH_TYPE;
> 
> 
> Can we return -1 here instead, please? In the current code, we validate
> the attach_type before entering this function and the "default" case is
> never reached, it's only here to discard compiler's warning. But if we
> ever reuse this function elsewhere, this could cause bugs: if the header
> file used for compiling the bpftool binary is not in sync with the
> header corresponding to the running kernel, __MAX_BPF_ATTACH_TYPE could
> correspond to a newly introduced type, and bpftool/libbpf would try to
> use that to attach the program, instead of detecting an error.
> 
> 

Hi, Quentin, i didn’t take the use case you mentioned into account. As 
you said, -1 looks more reasonable. I will fix it in the next revisions.

>> +	}
>> +}
>> +
>> +static int do_attach_tcx(int progfd, enum net_attach_type attach_type, int ifindex)
>> +{
>> +	int type = get_tcx_type(attach_type);
>> +
>> +	return bpf_prog_attach(progfd, ifindex, type, 0);
>> +}
>> +
>> +static int do_detach_tcx(int targetfd, enum net_attach_type attach_type)
>> +{
>> +	int type = get_tcx_type(attach_type);
>> +
>> +	return bpf_prog_detach(targetfd, type);
>> +}
>> +
>>   static int do_attach(int argc, char **argv)
>>   {
>>   	enum net_attach_type attach_type;
>> @@ -692,6 +722,11 @@ static int do_attach(int argc, char **argv)
>>   	case NET_ATTACH_TYPE_XDP_OFFLOAD:
>>   		err = do_attach_detach_xdp(progfd, attach_type, ifindex, overwrite);
>>   		break;
>> +	/* attach tcx prog */
>> +	case NET_ATTACH_TYPE_TCX_INGRESS:
>> +	case NET_ATTACH_TYPE_TCX_EGRESS:
>> +		err = do_attach_tcx(progfd, attach_type, ifindex);
>> +		break;
>>   	default:
>>   		break;
>>   	}
>> @@ -738,6 +773,11 @@ static int do_detach(int argc, char **argv)
>>   		progfd = -1;
>>   		err = do_attach_detach_xdp(progfd, attach_type, ifindex, NULL);
>>   		break;
>> +	/* detach tcx prog */
>> +	case NET_ATTACH_TYPE_TCX_INGRESS:
>> +	case NET_ATTACH_TYPE_TCX_EGRESS:
>> +		err = do_detach_tcx(ifindex, attach_type);
>> +		break;
>>   	default:
>>   		break;
>>   	}
>> @@ -944,7 +984,8 @@ static int do_help(int argc, char **argv)
>>   		"       %1$s %2$s help\n"
>>   		"\n"
>>   		"       " HELP_SPEC_PROGRAM "\n"
>> -		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload }\n"
>> +		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload | tcx_ingress\n"
>> +		"			 | tcx_egress }\n"
> 
>                   ^^^^^^^^^^^^^^^^^^^^^^^
> This indent space between the quote and the pipe needs to be spaces
> instead of three tabs, please.

My editor problem, i will fix it in the next revisions.

> 
> The rest of the patches looks good, thank you!
Thank you for reviewing all the patches. I appreciate your feedback.

> 
> Quentin
>
diff mbox series

Patch

diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
index 1b9f4225b394..60b0af40109a 100644
--- a/tools/bpf/bpftool/net.c
+++ b/tools/bpf/bpftool/net.c
@@ -67,6 +67,8 @@  enum net_attach_type {
 	NET_ATTACH_TYPE_XDP_GENERIC,
 	NET_ATTACH_TYPE_XDP_DRIVER,
 	NET_ATTACH_TYPE_XDP_OFFLOAD,
+	NET_ATTACH_TYPE_TCX_INGRESS,
+	NET_ATTACH_TYPE_TCX_EGRESS,
 };
 
 static const char * const attach_type_strings[] = {
@@ -74,6 +76,8 @@  static const char * const attach_type_strings[] = {
 	[NET_ATTACH_TYPE_XDP_GENERIC]	= "xdpgeneric",
 	[NET_ATTACH_TYPE_XDP_DRIVER]	= "xdpdrv",
 	[NET_ATTACH_TYPE_XDP_OFFLOAD]	= "xdpoffload",
+	[NET_ATTACH_TYPE_TCX_INGRESS]	= "tcx_ingress",
+	[NET_ATTACH_TYPE_TCX_EGRESS]	= "tcx_egress",
 };
 
 static const char * const attach_loc_strings[] = {
@@ -647,6 +651,32 @@  static int do_attach_detach_xdp(int progfd, enum net_attach_type attach_type,
 	return bpf_xdp_attach(ifindex, progfd, flags, NULL);
 }
 
+static int get_tcx_type(enum net_attach_type attach_type)
+{
+	switch (attach_type) {
+	case NET_ATTACH_TYPE_TCX_INGRESS:
+		return BPF_TCX_INGRESS;
+	case NET_ATTACH_TYPE_TCX_EGRESS:
+		return BPF_TCX_EGRESS;
+	default:
+		return __MAX_BPF_ATTACH_TYPE;
+	}
+}
+
+static int do_attach_tcx(int progfd, enum net_attach_type attach_type, int ifindex)
+{
+	int type = get_tcx_type(attach_type);
+
+	return bpf_prog_attach(progfd, ifindex, type, 0);
+}
+
+static int do_detach_tcx(int targetfd, enum net_attach_type attach_type)
+{
+	int type = get_tcx_type(attach_type);
+
+	return bpf_prog_detach(targetfd, type);
+}
+
 static int do_attach(int argc, char **argv)
 {
 	enum net_attach_type attach_type;
@@ -692,6 +722,11 @@  static int do_attach(int argc, char **argv)
 	case NET_ATTACH_TYPE_XDP_OFFLOAD:
 		err = do_attach_detach_xdp(progfd, attach_type, ifindex, overwrite);
 		break;
+	/* attach tcx prog */
+	case NET_ATTACH_TYPE_TCX_INGRESS:
+	case NET_ATTACH_TYPE_TCX_EGRESS:
+		err = do_attach_tcx(progfd, attach_type, ifindex);
+		break;
 	default:
 		break;
 	}
@@ -738,6 +773,11 @@  static int do_detach(int argc, char **argv)
 		progfd = -1;
 		err = do_attach_detach_xdp(progfd, attach_type, ifindex, NULL);
 		break;
+	/* detach tcx prog */
+	case NET_ATTACH_TYPE_TCX_INGRESS:
+	case NET_ATTACH_TYPE_TCX_EGRESS:
+		err = do_detach_tcx(ifindex, attach_type);
+		break;
 	default:
 		break;
 	}
@@ -944,7 +984,8 @@  static int do_help(int argc, char **argv)
 		"       %1$s %2$s help\n"
 		"\n"
 		"       " HELP_SPEC_PROGRAM "\n"
-		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload }\n"
+		"       ATTACH_TYPE := { xdp | xdpgeneric | xdpdrv | xdpoffload | tcx_ingress\n"
+		"			 | tcx_egress }\n"
 		"       " HELP_SPEC_OPTIONS " }\n"
 		"\n"
 		"Note: Only xdp, tcx, tc, netkit, flow_dissector and netfilter attachments\n"