1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (C) 2017 Facebook
3 // Author: Roman Gushchin <guro@fb.com>
16 #define HELP_SPEC_ATTACH_FLAGS \
17 "ATTACH_FLAGS := { multi | override }"
19 #define HELP_SPEC_ATTACH_TYPES \
20 "ATTACH_TYPE := { ingress | egress | sock_create | sock_ops | device }"
22 static const char * const attach_type_strings
[] = {
23 [BPF_CGROUP_INET_INGRESS
] = "ingress",
24 [BPF_CGROUP_INET_EGRESS
] = "egress",
25 [BPF_CGROUP_INET_SOCK_CREATE
] = "sock_create",
26 [BPF_CGROUP_SOCK_OPS
] = "sock_ops",
27 [BPF_CGROUP_DEVICE
] = "device",
28 [__MAX_BPF_ATTACH_TYPE
] = NULL
,
31 static enum bpf_attach_type
parse_attach_type(const char *str
)
33 enum bpf_attach_type type
;
35 for (type
= 0; type
< __MAX_BPF_ATTACH_TYPE
; type
++) {
36 if (attach_type_strings
[type
] &&
37 is_prefix(str
, attach_type_strings
[type
]))
41 return __MAX_BPF_ATTACH_TYPE
;
44 static int show_bpf_prog(int id
, const char *attach_type_str
,
45 const char *attach_flags_str
)
47 struct bpf_prog_info info
= {};
48 __u32 info_len
= sizeof(info
);
51 prog_fd
= bpf_prog_get_fd_by_id(id
);
55 if (bpf_obj_get_info_by_fd(prog_fd
, &info
, &info_len
)) {
61 jsonw_start_object(json_wtr
);
62 jsonw_uint_field(json_wtr
, "id", info
.id
);
63 jsonw_string_field(json_wtr
, "attach_type",
65 jsonw_string_field(json_wtr
, "attach_flags",
67 jsonw_string_field(json_wtr
, "name", info
.name
);
68 jsonw_end_object(json_wtr
);
70 printf("%-8u %-15s %-15s %-15s\n", info
.id
,
80 static int show_attached_bpf_progs(int cgroup_fd
, enum bpf_attach_type type
)
82 __u32 prog_ids
[1024] = {0};
83 char *attach_flags_str
;
89 prog_cnt
= ARRAY_SIZE(prog_ids
);
90 ret
= bpf_prog_query(cgroup_fd
, type
, 0, &attach_flags
, prog_ids
,
98 switch (attach_flags
) {
99 case BPF_F_ALLOW_MULTI
:
100 attach_flags_str
= "multi";
102 case BPF_F_ALLOW_OVERRIDE
:
103 attach_flags_str
= "override";
106 attach_flags_str
= "";
109 snprintf(buf
, sizeof(buf
), "unknown(%x)", attach_flags
);
110 attach_flags_str
= buf
;
113 for (iter
= 0; iter
< prog_cnt
; iter
++)
114 show_bpf_prog(prog_ids
[iter
], attach_type_strings
[type
],
120 static int do_show(int argc
, char **argv
)
122 enum bpf_attach_type type
;
127 p_err("too few parameters for cgroup show");
129 } else if (argc
> 1) {
130 p_err("too many parameters for cgroup show");
134 cgroup_fd
= open(argv
[0], O_RDONLY
);
136 p_err("can't open cgroup %s", argv
[1]);
141 jsonw_start_array(json_wtr
);
143 printf("%-8s %-15s %-15s %-15s\n", "ID", "AttachType",
144 "AttachFlags", "Name");
146 for (type
= 0; type
< __MAX_BPF_ATTACH_TYPE
; type
++) {
148 * Not all attach types may be supported, so it's expected,
149 * that some requests will fail.
150 * If we were able to get the show for at least one
151 * attach type, let's return 0.
153 if (show_attached_bpf_progs(cgroup_fd
, type
) == 0)
158 jsonw_end_array(json_wtr
);
165 static int do_attach(int argc
, char **argv
)
167 enum bpf_attach_type attach_type
;
168 int cgroup_fd
, prog_fd
;
169 int attach_flags
= 0;
174 p_err("too few parameters for cgroup attach");
178 cgroup_fd
= open(argv
[0], O_RDONLY
);
180 p_err("can't open cgroup %s", argv
[1]);
184 attach_type
= parse_attach_type(argv
[1]);
185 if (attach_type
== __MAX_BPF_ATTACH_TYPE
) {
186 p_err("invalid attach type");
192 prog_fd
= prog_parse_fd(&argc
, &argv
);
196 for (i
= 0; i
< argc
; i
++) {
197 if (is_prefix(argv
[i
], "multi")) {
198 attach_flags
|= BPF_F_ALLOW_MULTI
;
199 } else if (is_prefix(argv
[i
], "override")) {
200 attach_flags
|= BPF_F_ALLOW_OVERRIDE
;
202 p_err("unknown option: %s", argv
[i
]);
207 if (bpf_prog_attach(prog_fd
, cgroup_fd
, attach_type
, attach_flags
)) {
208 p_err("failed to attach program");
213 jsonw_null(json_wtr
);
225 static int do_detach(int argc
, char **argv
)
227 enum bpf_attach_type attach_type
;
228 int prog_fd
, cgroup_fd
;
232 p_err("too few parameters for cgroup detach");
236 cgroup_fd
= open(argv
[0], O_RDONLY
);
238 p_err("can't open cgroup %s", argv
[1]);
242 attach_type
= parse_attach_type(argv
[1]);
243 if (attach_type
== __MAX_BPF_ATTACH_TYPE
) {
244 p_err("invalid attach type");
250 prog_fd
= prog_parse_fd(&argc
, &argv
);
254 if (bpf_prog_detach2(prog_fd
, cgroup_fd
, attach_type
)) {
255 p_err("failed to detach program");
260 jsonw_null(json_wtr
);
272 static int do_help(int argc
, char **argv
)
275 jsonw_null(json_wtr
);
280 "Usage: %s %s { show | list } CGROUP\n"
281 " %s %s attach CGROUP ATTACH_TYPE PROG [ATTACH_FLAGS]\n"
282 " %s %s detach CGROUP ATTACH_TYPE PROG\n"
285 " " HELP_SPEC_ATTACH_TYPES
"\n"
286 " " HELP_SPEC_ATTACH_FLAGS
"\n"
287 " " HELP_SPEC_PROGRAM
"\n"
288 " " HELP_SPEC_OPTIONS
"\n"
290 bin_name
, argv
[-2], bin_name
, argv
[-2],
291 bin_name
, argv
[-2], bin_name
, argv
[-2]);
296 static const struct cmd cmds
[] = {
299 { "attach", do_attach
},
300 { "detach", do_detach
},
305 int do_cgroup(int argc
, char **argv
)
307 return cmd_select(cmds
, argc
, argv
, do_help
);