123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- /* eBPF example program:
- *
- * - Creates arraymap in kernel with 4 bytes keys and 8 byte values
- *
- * - Loads eBPF program
- *
- * The eBPF program accesses the map passed in to store two pieces of
- * information. The number of invocations of the program, which maps
- * to the number of packets received, is stored to key 0. Key 1 is
- * incremented on each iteration by the number of bytes stored in
- * the skb.
- *
- * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
- *
- * - Every second, reads map[0] and map[1] to see how many bytes and
- * packets were seen on any socket of tasks in the given cgroup.
- */
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <unistd.h>
- #include <linux/bpf.h>
- #include "libbpf.h"
- #include "cgroup_helpers.h"
- #define FOO "/foo"
- #define BAR "/foo/bar/"
- #define PING_CMD "ping -c1 -w1 127.0.0.1"
- char bpf_log_buf[BPF_LOG_BUF_SIZE];
- static int prog_load(int verdict)
- {
- int ret;
- struct bpf_insn prog[] = {
- BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
- BPF_EXIT_INSN(),
- };
- size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
- ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
- prog, insns_cnt, "GPL", 0,
- bpf_log_buf, BPF_LOG_BUF_SIZE);
- if (ret < 0) {
- log_err("Loading program");
- printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
- return 0;
- }
- return ret;
- }
- int main(int argc, char **argv)
- {
- int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0;
- allow_prog = prog_load(1);
- if (!allow_prog)
- goto err;
- drop_prog = prog_load(0);
- if (!drop_prog)
- goto err;
- if (setup_cgroup_environment())
- goto err;
- /* Create cgroup /foo, get fd, and join it */
- foo = create_and_get_cgroup(FOO);
- if (!foo)
- goto err;
- if (join_cgroup(FOO))
- goto err;
- if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS)) {
- log_err("Attaching prog to /foo");
- goto err;
- }
- assert(system(PING_CMD) != 0);
- /* Create cgroup /foo/bar, get fd, and join it */
- bar = create_and_get_cgroup(BAR);
- if (!bar)
- goto err;
- if (join_cgroup(BAR))
- goto err;
- assert(system(PING_CMD) != 0);
- if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
- log_err("Attaching prog to /foo/bar");
- goto err;
- }
- assert(system(PING_CMD) == 0);
- if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
- log_err("Detaching program from /foo/bar");
- goto err;
- }
- assert(system(PING_CMD) != 0);
- if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
- log_err("Attaching prog to /foo/bar");
- goto err;
- }
- if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) {
- log_err("Detaching program from /foo");
- goto err;
- }
- assert(system(PING_CMD) == 0);
- goto out;
- err:
- rc = 1;
- out:
- close(foo);
- close(bar);
- cleanup_cgroup_environment();
- return rc;
- }
|