The program load_cg_skb can be used to load BPF_PROG_TYPE_CGROUP_SKB type bpf_prog which currently can be attached to the ingress and egress patch. It can also be used to detach the bpf_prog.
Examples: load_cg_skb [-i] <cg-path> <prog filename> Load and attaches a cg skb program to the specified cgroup. If "-i" is used, the program is attached as ingress (default is egress). load_cg_skb -r[i] <cg-path> Detaches the currnetly attached egress (or ingress if -ri is used) cg skb program from the specified cgroup. Signed-off-by: Lawrence Brakmo <bra...@fb.com> --- samples/bpf/Makefile | 2 + samples/bpf/load_cg_skb.c | 109 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 samples/bpf/load_cg_skb.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index a0ef7eddd0b3..0cf3347c7443 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -53,6 +53,7 @@ hostprogs-y += xdpsock hostprogs-y += xdp_fwd hostprogs-y += task_fd_query hostprogs-y += xdp_sample_pkts +hostprogs-y += load_cg_skb # Libbpf dependencies LIBBPF = $(TOOLS_PATH)/lib/bpf/libbpf.a @@ -109,6 +110,7 @@ xdpsock-objs := xdpsock_user.o xdp_fwd-objs := xdp_fwd_user.o task_fd_query-objs := bpf_load.o task_fd_query_user.o $(TRACE_HELPERS) xdp_sample_pkts-objs := xdp_sample_pkts_user.o $(TRACE_HELPERS) +load_cg_skb-objs := bpf_load.o load_cg_skb.o # Tell kbuild to always build the programs always := $(hostprogs-y) diff --git a/samples/bpf/load_cg_skb.c b/samples/bpf/load_cg_skb.c new file mode 100644 index 000000000000..619ff834fc8c --- /dev/null +++ b/samples/bpf/load_cg_skb.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Facebook + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <linux/bpf.h> +#include <bpf/bpf.h> +#include "bpf_load.h" +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <linux/unistd.h> + +static void usage(char *pname) +{ + printf("USAGE:\n %s [-i] [-l] <cg-path> <prog filename>\n", pname); + printf("\tLoad and attach a cgroup/skb egress/ingress program to" + " the specified\n" + "\tcgroup\n" + "\tIf \"-i\" is used, an ingress program is loaded (default is" + " egress)\n" + "\tIf \"-l\" is used, the program will continue to run" + " printing the BPF log\n" + "\tbuffer\n" + "\tIf the specified filename does not end in \".o\", it" + " appends \"_kern.o\"\n" + "\tto the name\n\n"); + printf(" %s -r <cg-path>\n", pname); + printf("\tDetaches the currently attached cgroup/skb egress program\n" + "\tfrom the specified cgroup\n"); + printf(" %s -ri <cg-path>\n", pname); + printf("\tDetaches the currently attached cgroup/skb ingress program\n" + "\tfrom the specified cgroup\n\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int logFlag = 0; + int error = 0; + char *cg_path; + char fn[500]; + char *prog; + int cg_fd; + int mode = BPF_CGROUP_INET_EGRESS; + + if (argc < 3) + usage(argv[0]); + + if (!strcmp(argv[1], "-i")) { + mode = BPF_CGROUP_INET_INGRESS; + } else if (!strncmp(argv[1], "-r", 2)) { + if (argv[1][2] == 'i') + mode = BPF_CGROUP_INET_INGRESS; + cg_path = argv[2]; + cg_fd = open(cg_path, O_DIRECTORY, O_RDONLY); + error = bpf_prog_detach(cg_fd, mode); + if (error) { + printf("ERROR: bpf_prog_detach: %d (%s)\n", + error, strerror(errno)); + return 2; + } + return 0; + } else if (!strcmp(argv[1], "-h")) { + usage(argv[0]); + } else if (!strcmp(argv[1], "-l")) { + logFlag = 1; + if (argc < 4) + usage(argv[0]); + } + + prog = argv[argc - 1]; + cg_path = argv[argc - 2]; + if (strlen(prog) > 480) { + fprintf(stderr, "ERROR: program name too long (> 480 chars)\n"); + return 3; + } + cg_fd = open(cg_path, O_DIRECTORY, O_RDONLY); + + if (!strcmp(prog + strlen(prog)-2, ".o")) + strcpy(fn, prog); + else + sprintf(fn, "%s_kern.o", prog); + if (logFlag) + printf("loading bpf file:%s\n", fn); + if (load_bpf_file(fn)) { + printf("ERROR: load_bpf_file failed for: %s\n", fn); + printf("%s", bpf_log_buf); + return 4; + } + if (logFlag) + printf("TCP BPF Loaded %s\n", fn); + + error = bpf_prog_attach(prog_fd[0], cg_fd, BPF_CGROUP_INET_EGRESS, 0); + if (error) { + printf("ERROR: bpf_prog_attach: %d (%s)\n", + error, strerror(errno)); + return 5; + } else if (logFlag) { + read_trace_pipe(); + } + + return error; +} -- 2.17.1