--- v3
+++ v2
@@ -1,96 +1,213 @@
-Add option to detach programs from a cgroup.
+Update sock test to set mark and priority on socket create.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
- samples/bpf/test_cgrp2_sock.c | 50 ++++++++++++++++++++++++++++++-------------
- 1 file changed, 35 insertions(+), 15 deletions(-)
+ samples/bpf/test_cgrp2_sock.c | 139 ++++++++++++++++++++++++++++++++++++-----
+ samples/bpf/test_cgrp2_sock.sh | 2 +-
+ 2 files changed, 123 insertions(+), 18 deletions(-)
diff --git a/samples/bpf/test_cgrp2_sock.c b/samples/bpf/test_cgrp2_sock.c
-index 681abbe6c85e..15396761c5cc 100644
+index c3cfb23e23b5..b018bf948933 100644
--- a/samples/bpf/test_cgrp2_sock.c
+++ b/samples/bpf/test_cgrp2_sock.c
-@@ -114,7 +114,12 @@ static int prog_load(__u32 idx, __u32 mark, __u32 prio)
+@@ -19,63 +19,168 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <net/if.h>
++#include <inttypes.h>
+ #include <linux/bpf.h>
+
+ #include "libbpf.h"
+
+ char bpf_log_buf[BPF_LOG_BUF_SIZE];
+
+-static int prog_load(int idx)
++static int prog_load(__u32 idx, __u32 mark, __u32 prio)
+ {
+- struct bpf_insn prog[] = {
++ /* save pointer to context */
++ struct bpf_insn prog_start[] = {
+ BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
++ };
++ struct bpf_insn prog_end[] = {
++ BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
++ BPF_EXIT_INSN(),
++ };
++
++ /* set sk_bound_dev_if on socket */
++ struct bpf_insn prog_dev[] = {
+ BPF_MOV64_IMM(BPF_REG_3, idx),
+ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, bound_dev_if)),
+ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, bound_dev_if)),
+- BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = verdict */
+- BPF_EXIT_INSN(),
+ };
+- size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
+
+- return bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
++ /* set mark on socket */
++ struct bpf_insn prog_mark[] = {
++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
++ BPF_MOV64_IMM(BPF_REG_3, mark),
++ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, mark)),
++ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, mark)),
++ };
++
++ /* set priority on socket */
++ struct bpf_insn prog_prio[] = {
++ BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
++ BPF_MOV64_IMM(BPF_REG_3, prio),
++ BPF_MOV64_IMM(BPF_REG_2, offsetof(struct bpf_sock, priority)),
++ BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_3, offsetof(struct bpf_sock, priority)),
++ };
++
++ struct bpf_insn *prog;
++ size_t insns_cnt;
++ void *p;
++ int ret;
++
++ insns_cnt = sizeof(prog_start) + sizeof(prog_end);
++ if (idx)
++ insns_cnt += sizeof(prog_dev);
++
++ if (mark)
++ insns_cnt += sizeof(prog_mark);
++
++ if (prio)
++ insns_cnt += sizeof(prog_prio);
++
++ p = prog = malloc(insns_cnt);
++ if (!prog) {
++ fprintf(stderr, "Failed to allocate memory for instructions\n");
++ return EXIT_FAILURE;
++ }
++
++ memcpy(p, prog_start, sizeof(prog_start));
++ p += sizeof(prog_start);
++
++ if (idx) {
++ memcpy(p, prog_dev, sizeof(prog_dev));
++ p += sizeof(prog_dev);
++ }
++
++ if (mark) {
++ memcpy(p, prog_mark, sizeof(prog_mark));
++ p += sizeof(prog_mark);
++ }
++
++ if (prio) {
++ memcpy(p, prog_prio, sizeof(prog_prio));
++ p += sizeof(prog_prio);
++ }
++
++ memcpy(p, prog_end, sizeof(prog_end));
++ p += sizeof(prog_end);
++
++ insns_cnt /= sizeof(struct bpf_insn);
++
++ ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SOCK, prog, insns_cnt,
+ "GPL", 0, bpf_log_buf, BPF_LOG_BUF_SIZE);
++
++ free(prog);
++
++ return ret;
+ }
static int usage(const char *argv0)
{
-- printf("Usage: %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
-+ printf("Usage:\n");
-+ printf(" Attach a program\n");
-+ printf(" %s -b bind-to-dev -m mark -p prio cg-path\n", argv0);
-+ printf("\n");
-+ printf(" Detach a program\n");
-+ printf(" %s -d cg-path\n", argv0);
+- printf("Usage: %s cg-path device-index\n", argv0);
++ printf("Usage: %s -b bind-to-dev -m mark -p prio -r cg-path\n", argv0);
return EXIT_FAILURE;
}
-@@ -123,10 +128,14 @@ int main(int argc, char **argv)
- __u32 idx = 0, mark = 0, prio = 0;
- const char *cgrp_path = NULL;
+ int main(int argc, char **argv)
+ {
++ __u32 attach_flags = BPF_F_ALLOW_OVERRIDE;
++ __u32 idx = 0, mark = 0, prio = 0;
++ const char *cgrp_path = NULL;
int cg_fd, prog_fd, ret;
-+ int do_attach = 1;
- int rc;
-
-- while ((rc = getopt(argc, argv, "b:m:p:")) != -1) {
-+ while ((rc = getopt(argc, argv, "db:m:p:")) != -1) {
- switch (rc) {
-+ case 'd':
-+ do_attach = 0;
-+ break;
- case 'b':
- idx = if_nametoindex(optarg);
- if (!idx) {
-@@ -157,7 +166,7 @@ int main(int argc, char **argv)
+- unsigned int idx;
++ int rc;
++
++ while ((rc = getopt(argc, argv, "b:m:p:r")) != -1) {
++ switch (rc) {
++ case 'b':
++ idx = if_nametoindex(optarg);
++ if (!idx) {
++ idx = strtoumax(optarg, NULL, 0);
++ if (!idx) {
++ printf("Invalid device name\n");
++ return EXIT_FAILURE;
++ }
++ }
++ break;
++ case 'm':
++ mark = strtoumax(optarg, NULL, 0);
++ break;
++ case 'p':
++ prio = strtoumax(optarg, NULL, 0);
++ break;
++ case 'r':
++ attach_flags |= BPF_F_RECURSIVE;
++ break;
++ default:
++ return usage(argv[0]);
++ }
++ }
+
+- if (argc < 2)
++ if (optind == argc)
+ return usage(argv[0]);
+
+- idx = if_nametoindex(argv[2]);
+- if (!idx) {
+- printf("Invalid device name\n");
++ cgrp_path = argv[optind];
++ if (!cgrp_path) {
++ fprintf(stderr, "cgroup path not given\n");
return EXIT_FAILURE;
}
-- if (!idx && !mark && !prio) {
-+ if (do_attach && !idx && !mark && !prio) {
- fprintf(stderr,
- "One of device, mark or priority must be given\n");
- return EXIT_FAILURE;
-@@ -169,20 +178,31 @@ int main(int argc, char **argv)
+- cg_fd = open(argv[1], O_DIRECTORY | O_RDONLY);
++ if (!idx && !mark && !prio) {
++ fprintf(stderr, "One of device, mark or priority must be given\n");
++ return EXIT_FAILURE;
++ }
++
++ cg_fd = open(cgrp_path, O_DIRECTORY | O_RDONLY);
+ if (cg_fd < 0) {
+ printf("Failed to open cgroup path: '%s'\n", strerror(errno));
return EXIT_FAILURE;
}
-- prog_fd = prog_load(idx, mark, prio);
-- if (prog_fd < 0) {
-- printf("Failed to load prog: '%s'\n", strerror(errno));
-- printf("Output from kernel verifier:\n%s\n-------\n",
-- bpf_log_buf);
-- return EXIT_FAILURE;
-- }
-+ if (do_attach) {
-+ prog_fd = prog_load(idx, mark, prio);
-+ if (prog_fd < 0) {
-+ printf("Failed to load prog: '%s'\n", strerror(errno));
-+ printf("Output from kernel verifier:\n%s\n-------\n",
-+ bpf_log_buf);
-+ return EXIT_FAILURE;
-+ }
+- prog_fd = prog_load(idx);
+- printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
+-
++ prog_fd = prog_load(idx, mark, prio);
+ if (prog_fd < 0) {
+ printf("Failed to load prog: '%s'\n", strerror(errno));
++ printf("Output from kernel verifier:\n%s\n-------\n", bpf_log_buf);
+ return EXIT_FAILURE;
+ }
- ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE, 0);
-- if (ret < 0) {
-- printf("Failed to attach prog to cgroup: '%s'\n",
-- strerror(errno));
-- return EXIT_FAILURE;
-+ ret = bpf_prog_attach(prog_fd, cg_fd,
-+ BPF_CGROUP_INET_SOCK_CREATE, 0);
-+ if (ret < 0) {
-+ printf("Failed to attach prog to cgroup: '%s'\n",
-+ strerror(errno));
-+ return EXIT_FAILURE;
-+ }
-+ } else {
-+ ret = bpf_prog_detach(cg_fd, BPF_CGROUP_INET_SOCK_CREATE);
-+ if (ret < 0) {
-+ printf("Failed to detach prog from cgroup: '%s'\n",
-+ strerror(errno));
-+ return EXIT_FAILURE;
-+ }
- }
-
-+ close(cg_fd);
- return EXIT_SUCCESS;
++ ret = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_INET_SOCK_CREATE,
++ attach_flags);
+ if (ret < 0) {
+ printf("Failed to attach prog to cgroup: '%s'\n",
+ strerror(errno));
+diff --git a/samples/bpf/test_cgrp2_sock.sh b/samples/bpf/test_cgrp2_sock.sh
+index 925fd467c7cc..1153c33e8964 100755
+--- a/samples/bpf/test_cgrp2_sock.sh
++++ b/samples/bpf/test_cgrp2_sock.sh
+@@ -20,7 +20,7 @@ function attach_bpf {
+ mkdir -p /tmp/cgroupv2
+ mount -t cgroup2 none /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2/foo
+- test_cgrp2_sock /tmp/cgroupv2/foo foo
++ test_cgrp2_sock -b foo /tmp/cgroupv2/foo
+ echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
}
+
--
2.1.4