blob: fc6092fdc3b050897f52b5f406651b7a9d05b353 [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
Joe Stringerd40fc182016-12-14 14:43:38 -080035char bpf_log_buf[BPF_LOG_BUF_SIZE];
36
Sargun Dhillon9b474ec2016-12-02 02:42:32 -080037static int prog_load(int verdict)
38{
39 int ret;
40 struct bpf_insn prog[] = {
41 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
42 BPF_EXIT_INSN(),
43 };
44
Joe Stringerd40fc182016-12-14 14:43:38 -080045 ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
46 prog, sizeof(prog), "GPL", 0,
47 bpf_log_buf, BPF_LOG_BUF_SIZE);
Sargun Dhillon9b474ec2016-12-02 02:42:32 -080048
49 if (ret < 0) {
50 log_err("Loading program");
51 printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
52 return 0;
53 }
54 return ret;
55}
56
57
58int main(int argc, char **argv)
59{
60 int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0;
61
62 allow_prog = prog_load(1);
63 if (!allow_prog)
64 goto err;
65
66 drop_prog = prog_load(0);
67 if (!drop_prog)
68 goto err;
69
70 if (setup_cgroup_environment())
71 goto err;
72
73 /* Create cgroup /foo, get fd, and join it */
74 foo = create_and_get_cgroup(FOO);
75 if (!foo)
76 goto err;
77
78 if (join_cgroup(FOO))
79 goto err;
80
81 if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS)) {
82 log_err("Attaching prog to /foo");
83 goto err;
84 }
85
86 assert(system(PING_CMD) != 0);
87
88 /* Create cgroup /foo/bar, get fd, and join it */
89 bar = create_and_get_cgroup(BAR);
90 if (!bar)
91 goto err;
92
93 if (join_cgroup(BAR))
94 goto err;
95
96 assert(system(PING_CMD) != 0);
97
98 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
99 log_err("Attaching prog to /foo/bar");
100 goto err;
101 }
102
103 assert(system(PING_CMD) == 0);
104
105
106 if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) {
107 log_err("Detaching program from /foo/bar");
108 goto err;
109 }
110
111 assert(system(PING_CMD) != 0);
112
113 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS)) {
114 log_err("Attaching prog to /foo/bar");
115 goto err;
116 }
117
118 if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) {
119 log_err("Detaching program from /foo");
120 goto err;
121 }
122
123 assert(system(PING_CMD) == 0);
124
125 goto out;
126
127err:
128 rc = 1;
129
130out:
131 close(foo);
132 close(bar);
133 cleanup_cgroup_environment();
134 return rc;
135}