This patch add the cgattach command to bpftool. It allows to load a bpf program from a binary file and attach it to a given cgroup.
Example: $ bpftool cgattach ./mybpfprog.o /sys/fs/cgroup/user.slice/ ingress Signed-off-by: Roman Gushchin <g...@fb.com> Cc: Alexei Starovoitov <a...@kernel.org> Cc: Daniel Borkmann <dan...@iogearbox.net> Cc: Jakub Kicinski <jakub.kicin...@netronome.com> Cc: Martin KaFai Lau <ka...@fb.com> --- tools/bpf/bpftool/main.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index d6e4762170a4..8eb3b9bf5bb2 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -41,9 +41,14 @@ #include <linux/version.h> #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include <bpf.h> +#include <libbpf.h> #include "main.h" @@ -75,12 +80,13 @@ static int do_help(int argc, char **argv) fprintf(stderr, "Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n" " %s batch file FILE\n" + " %s cgattach FILE CGROUP TYPE\n" " %s version\n" "\n" " OBJECT := { prog | map }\n" " " HELP_SPEC_OPTIONS "\n" "", - bin_name, bin_name, bin_name); + bin_name, bin_name, bin_name, bin_name); return 0; } @@ -159,12 +165,14 @@ void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep) } static int do_batch(int argc, char **argv); +static int do_cgattach(int argc, char **argv); static const struct cmd cmds[] = { { "help", do_help }, { "batch", do_batch }, { "prog", do_prog }, { "map", do_map }, + { "cgattach", do_cgattach }, { "version", do_version }, { 0 } }; @@ -259,6 +267,77 @@ static int do_batch(int argc, char **argv) return err; } +static const char * const attach_type_strings[] = { + [BPF_CGROUP_INET_INGRESS] = "ingress", + [BPF_CGROUP_INET_EGRESS] = "egress", + [BPF_CGROUP_INET_SOCK_CREATE] = "sock_create", + [BPF_CGROUP_SOCK_OPS] = "sock_ops", + [BPF_CGROUP_DEVICE] = "device", + [__MAX_BPF_ATTACH_TYPE] = NULL, +}; + +enum bpf_attach_type parse_attach_type(const char *str) +{ + enum bpf_attach_type type; + + for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) { + if (attach_type_strings[type] && + strcmp(str, attach_type_strings[type]) == 0) + return type; + } + + return __MAX_BPF_ATTACH_TYPE; +} + +static int do_cgattach(int argc, char **argv) +{ + struct bpf_object *obj; + int prog_fd, cgroup_fd; + enum bpf_attach_type attach_type; + + if (argc < 3) { + p_err("too few parameters for cgattach\n"); + return -1; + } else if (argc > 3) { + p_err("too many parameters for cgattach\n"); + return -1; + } + + if (bpf_prog_load(argv[0], BPF_PROG_TYPE_UNSPEC, &obj, &prog_fd)) + return -1; + + cgroup_fd = open(argv[1], O_RDONLY); + if (cgroup_fd < 0) { + bpf_object__close(obj); + close(prog_fd); + p_err("can't open cgroup %s\n", argv[1]); + return -1; + } + + attach_type = parse_attach_type(argv[2]); + if (attach_type == __MAX_BPF_ATTACH_TYPE) { + bpf_object__close(obj); + close(prog_fd); + close(cgroup_fd); + p_err("Invalid attach type\n"); + return -1; + } + + if (bpf_prog_attach(prog_fd, cgroup_fd, attach_type, 0)) { + bpf_object__close(obj); + close(prog_fd); + close(cgroup_fd); + p_err("Failed to attach program"); + return -1; + } + + bpf_object__close(obj); + close(prog_fd); + close(cgroup_fd); + + return 0; +} + int main(int argc, char **argv) { static const struct option options[] = { -- 2.14.3