blob: ddfac42ed4df65636b9a1c2b1e405d04c343f7b7 [file] [log] [blame]
Sargun Dhillon9b474ec2016-12-02 02:42:32 -08001/* eBPF example program:
2 *
3 * - Creates arraymap in kernel with 4 bytes keys and 8 byte values
4 *
5 * - Loads eBPF program
6 *
7 * The eBPF program accesses the map passed in to store two pieces of
8 * information. The number of invocations of the program, which maps
9 * to the number of packets received, is stored to key 0. Key 1 is
10 * incremented on each iteration by the number of bytes stored in
11 * the skb.
12 *
13 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH
14 *
15 * - Every second, reads map[0] and map[1] to see how many bytes and
16 * packets were seen on any socket of tasks in the given cgroup.
17 */
18
19#define _GNU_SOURCE
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <assert.h>
24#include <unistd.h>
25
26#include <linux/bpf.h>
27
28#include "libbpf.h"
29#include "cgroup_helpers.h"
30
31#define FOO "/foo"
32#define BAR "/foo/bar/"
33#define PING_CMD "ping -c1 -w1 127.0.0.1"
34
35static int prog_load(int verdict)
36{
37 int ret;
38 struct bpf_insn prog[] = {
39 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
40 BPF_EXIT_INSN(),
41 };
42
43 ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SKB,
44 prog, sizeof(prog), "GPL", 0);
45
46 if (ret < 0) {
47 log_err("Loading program");
48 printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
49 return 0;
50 }
51 return ret;
52}
53
54
55int main(int argc, char **argv)
56{
57 int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0;
58
59 allow_prog = prog_load(1);
60 if (!allow_prog)
61 goto err;
62
63 drop_prog = prog_load(0);
64 if (!drop_prog)
65 goto err;
66
67 if (setup_cgroup_environment())
68 goto err;
69
70 /* Create cgroup /foo, get fd, and join it */
71 foo = create_and_get_cgroup(FOO);
72 if (!foo)
73 goto err;
74
75 if (join_cgroup(FOO))
76 goto err;
77
78 if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS)) {
79 log_err("Attaching prog to /foo");
80 goto err;
81 }
82
83 assert(system(PING_CMD) != 0);
84
85 /* Create cgroup /foo/bar, get fd, and join it */
86 bar = create_and_get_cgroup(BAR);
87 if (!bar)
88 goto err;
89
90 if (join_cgroup(BAR))
91 goto err;
92
93 assert(system(PING_CMD) != 0);
94
95 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
96 log_err("Attaching prog to /foo/bar");
97 goto err;
98 }
99
100 assert(system(PING_CMD) == 0);
101
102
103 if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
104 log_err("Detaching program from /foo/bar");
105 goto err;
106 }
107
108 assert(system(PING_CMD) != 0);
109
110 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
111 log_err("Attaching prog to /foo/bar");
112 goto err;
113 }
114
115 if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) {
116 log_err("Detaching program from /foo");
117 goto err;
118 }
119
120 assert(system(PING_CMD) == 0);
121
122 goto out;
123
124err:
125 rc = 1;
126
127out:
128 close(foo);
129 close(bar);
130 cleanup_cgroup_environment();
131 return rc;
132}