Skip to content

Commit 39323e7

Browse files
4astdavem330
authored andcommitted
samples/bpf: add multi-prog cgroup test case
create 5 cgroups, attach 6 progs and check that progs are executed as: cgrp1 (MULTI progs A, B) -> cgrp2 (OVERRIDE prog C) -> cgrp3 (MULTI prog D) -> cgrp4 (OVERRIDE prog E) -> cgrp5 (NONE prog F) the event in cgrp5 triggers execution of F,D,A,B in that order. if prog F is detached, the execution is E,D,A,B if prog F and D are detached, the execution is E,A,B if prog F, E and D are detached, the execution is C,A,B Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Daniel Borkmann <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 244d20e commit 39323e7

File tree

2 files changed

+185
-7
lines changed

2 files changed

+185
-7
lines changed

samples/bpf/cgroup_helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ int setup_cgroup_environment(void)
5656
return 1;
5757
}
5858

59-
if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL)) {
59+
if (mount("none", CGROUP_MOUNT_PATH, "cgroup2", 0, NULL) && errno != EBUSY) {
6060
log_err("mount cgroup2");
6161
return 1;
6262
}
@@ -163,7 +163,7 @@ int create_and_get_cgroup(char *path)
163163

164164
format_cgroup_path(cgroup_path, path);
165165
if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
166-
log_err("mkdiring cgroup");
166+
log_err("mkdiring cgroup %s .. %s", path, cgroup_path);
167167
return 0;
168168
}
169169

samples/bpf/test_cgrp2_attach2.c

Lines changed: 183 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
#define FOO "/foo"
3232
#define BAR "/foo/bar/"
33-
#define PING_CMD "ping -c1 -w1 127.0.0.1"
33+
#define PING_CMD "ping -c1 -w1 127.0.0.1 > /dev/null"
3434

3535
char bpf_log_buf[BPF_LOG_BUF_SIZE];
3636

@@ -55,8 +55,7 @@ static int prog_load(int verdict)
5555
return ret;
5656
}
5757

58-
59-
int main(int argc, char **argv)
58+
static int test_foo_bar(void)
6059
{
6160
int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0;
6261

@@ -189,8 +188,187 @@ int main(int argc, char **argv)
189188
close(bar);
190189
cleanup_cgroup_environment();
191190
if (!rc)
192-
printf("PASS\n");
191+
printf("### override:PASS\n");
192+
else
193+
printf("### override:FAIL\n");
194+
return rc;
195+
}
196+
197+
static int map_fd = -1;
198+
199+
static int prog_load_cnt(int verdict, int val)
200+
{
201+
if (map_fd < 0)
202+
map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, 4, 8, 1, 0);
203+
if (map_fd < 0) {
204+
printf("failed to create map '%s'\n", strerror(errno));
205+
return -1;
206+
}
207+
208+
struct bpf_insn prog[] = {
209+
BPF_MOV32_IMM(BPF_REG_0, 0),
210+
BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4), /* *(u32 *)(fp - 4) = r0 */
211+
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
212+
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4), /* r2 = fp - 4 */
213+
BPF_LD_MAP_FD(BPF_REG_1, map_fd),
214+
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
215+
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
216+
BPF_MOV64_IMM(BPF_REG_1, val), /* r1 = 1 */
217+
BPF_RAW_INSN(BPF_STX | BPF_XADD | BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0), /* xadd r0 += r1 */
218+
BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */
219+
BPF_EXIT_INSN(),
220+
};
221+
size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
222+
int ret;
223+
224+
ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
225+
prog, insns_cnt, "GPL", 0,
226+
bpf_log_buf, BPF_LOG_BUF_SIZE);
227+
228+
if (ret < 0) {
229+
log_err("Loading program");
230+
printf("Output from verifier:\n%s\n-------\n", bpf_log_buf);
231+
return 0;
232+
}
233+
return ret;
234+
}
235+
236+
237+
static int test_multiprog(void)
238+
{
239+
int cg1 = 0, cg2 = 0, cg3 = 0, cg4 = 0, cg5 = 0, key = 0;
240+
int drop_prog, allow_prog[6] = {}, rc = 0;
241+
unsigned long long value;
242+
int i = 0;
243+
244+
for (i = 0; i < 6; i++) {
245+
allow_prog[i] = prog_load_cnt(1, 1 << i);
246+
if (!allow_prog[i])
247+
goto err;
248+
}
249+
drop_prog = prog_load_cnt(0, 1);
250+
if (!drop_prog)
251+
goto err;
252+
253+
if (setup_cgroup_environment())
254+
goto err;
255+
256+
cg1 = create_and_get_cgroup("/cg1");
257+
if (!cg1)
258+
goto err;
259+
cg2 = create_and_get_cgroup("/cg1/cg2");
260+
if (!cg2)
261+
goto err;
262+
cg3 = create_and_get_cgroup("/cg1/cg2/cg3");
263+
if (!cg3)
264+
goto err;
265+
cg4 = create_and_get_cgroup("/cg1/cg2/cg3/cg4");
266+
if (!cg4)
267+
goto err;
268+
cg5 = create_and_get_cgroup("/cg1/cg2/cg3/cg4/cg5");
269+
if (!cg5)
270+
goto err;
271+
272+
if (join_cgroup("/cg1/cg2/cg3/cg4/cg5"))
273+
goto err;
274+
275+
if (bpf_prog_attach(allow_prog[0], cg1, BPF_CGROUP_INET_EGRESS, 2)) {
276+
log_err("Attaching prog to cg1");
277+
goto err;
278+
}
279+
if (!bpf_prog_attach(allow_prog[0], cg1, BPF_CGROUP_INET_EGRESS, 2)) {
280+
log_err("Unexpected success attaching the same prog to cg1");
281+
goto err;
282+
}
283+
if (bpf_prog_attach(allow_prog[1], cg1, BPF_CGROUP_INET_EGRESS, 2)) {
284+
log_err("Attaching prog2 to cg1");
285+
goto err;
286+
}
287+
if (bpf_prog_attach(allow_prog[2], cg2, BPF_CGROUP_INET_EGRESS, 1)) {
288+
log_err("Attaching prog to cg2");
289+
goto err;
290+
}
291+
if (bpf_prog_attach(allow_prog[3], cg3, BPF_CGROUP_INET_EGRESS, 2)) {
292+
log_err("Attaching prog to cg3");
293+
goto err;
294+
}
295+
if (bpf_prog_attach(allow_prog[4], cg4, BPF_CGROUP_INET_EGRESS, 1)) {
296+
log_err("Attaching prog to cg4");
297+
goto err;
298+
}
299+
if (bpf_prog_attach(allow_prog[5], cg5, BPF_CGROUP_INET_EGRESS, 0)) {
300+
log_err("Attaching prog to cg5");
301+
goto err;
302+
}
303+
assert(system(PING_CMD) == 0);
304+
assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
305+
assert(value == 1 + 2 + 8 + 32);
306+
307+
/* detach bottom program and ping again */
308+
if (bpf_prog_detach2(-1, cg5, BPF_CGROUP_INET_EGRESS)) {
309+
log_err("Detaching prog from cg5");
310+
goto err;
311+
}
312+
value = 0;
313+
assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0);
314+
assert(system(PING_CMD) == 0);
315+
assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
316+
assert(value == 1 + 2 + 8 + 16);
317+
318+
/* detach 3rd from bottom program and ping again */
319+
errno = 0;
320+
if (!bpf_prog_detach2(0, cg3, BPF_CGROUP_INET_EGRESS)) {
321+
log_err("Unexpected success on detach from cg3");
322+
goto err;
323+
}
324+
if (bpf_prog_detach2(allow_prog[3], cg3, BPF_CGROUP_INET_EGRESS)) {
325+
log_err("Detaching from cg3");
326+
goto err;
327+
}
328+
value = 0;
329+
assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0);
330+
assert(system(PING_CMD) == 0);
331+
assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
332+
assert(value == 1 + 2 + 16);
333+
334+
/* detach 2nd from bottom program and ping again */
335+
if (bpf_prog_detach2(-1, cg4, BPF_CGROUP_INET_EGRESS)) {
336+
log_err("Detaching prog from cg4");
337+
goto err;
338+
}
339+
value = 0;
340+
assert(bpf_map_update_elem(map_fd, &key, &value, 0) == 0);
341+
assert(system(PING_CMD) == 0);
342+
assert(bpf_map_lookup_elem(map_fd, &key, &value) == 0);
343+
assert(value == 1 + 2 + 4);
344+
goto out;
345+
err:
346+
rc = 1;
347+
348+
out:
349+
for (i = 0; i < 6; i++)
350+
if (allow_prog[i] > 0)
351+
close(allow_prog[i]);
352+
close(cg1);
353+
close(cg2);
354+
close(cg3);
355+
close(cg4);
356+
close(cg5);
357+
cleanup_cgroup_environment();
358+
if (!rc)
359+
printf("### multi:PASS\n");
193360
else
194-
printf("FAIL\n");
361+
printf("### multi:FAIL\n");
195362
return rc;
196363
}
364+
365+
int main(int argc, char **argv)
366+
{
367+
int rc = 0;
368+
369+
rc = test_foo_bar();
370+
if (rc)
371+
return rc;
372+
373+
return test_multiprog();
374+
}

0 commit comments

Comments
 (0)