Add a kselftest to cover bpf auto-detachment functionality.
The test creates a cgroup, associates some resources with it,
attaches a couple of bpf programs and deletes the cgroup.

Then it checks that bpf programs are going away in 5 seconds.

Expected output:
  $ ./test_cgroup_attach
  #override:PASS
  #multi:PASS
  #autodetach:PASS
  test_cgroup_attach:PASS

On a kernel without auto-detaching:
  $ ./test_cgroup_attach
  #override:PASS
  #multi:PASS
  #autodetach:FAIL
  test_cgroup_attach:FAIL

Signed-off-by: Roman Gushchin <g...@fb.com>
---
 .../selftests/bpf/test_cgroup_attach.c        | 99 ++++++++++++++++++-
 1 file changed, 98 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/test_cgroup_attach.c 
b/tools/testing/selftests/bpf/test_cgroup_attach.c
index 93d4fe295e7d..bc5bd0f1728e 100644
--- a/tools/testing/selftests/bpf/test_cgroup_attach.c
+++ b/tools/testing/selftests/bpf/test_cgroup_attach.c
@@ -456,9 +456,106 @@ static int test_multiprog(void)
        return rc;
 }
 
+static int test_autodetach(void)
+{
+       __u32 prog_cnt = 4, attach_flags;
+       int allow_prog[2] = {0};
+       __u32 prog_ids[2] = {0};
+       int cg = 0, i, rc = -1;
+       void *ptr = NULL;
+       int attempts;
+
+
+       for (i = 0; i < ARRAY_SIZE(allow_prog); i++) {
+               allow_prog[i] = prog_load_cnt(1, 1 << i);
+               if (!allow_prog[i])
+                       goto err;
+       }
+
+       if (setup_cgroup_environment())
+               goto err;
+
+       /* create a cgroup, attach two programs and remember their ids */
+       cg = create_and_get_cgroup("/cg_autodetach");
+       if (cg < 0)
+               goto err;
+
+       if (join_cgroup("/cg_autodetach"))
+               goto err;
+
+       for (i = 0; i < ARRAY_SIZE(allow_prog); i++) {
+               if (bpf_prog_attach(allow_prog[i], cg, BPF_CGROUP_INET_EGRESS,
+                                   BPF_F_ALLOW_MULTI)) {
+                       log_err("Attaching prog[%d] to cg:egress", i);
+                       goto err;
+               }
+       }
+
+       /* make sure that programs are attached and run some traffic */
+       assert(bpf_prog_query(cg, BPF_CGROUP_INET_EGRESS, 0, &attach_flags,
+                             prog_ids, &prog_cnt) == 0);
+       assert(system(PING_CMD) == 0);
+
+       /* allocate some memory (4Mb) to pin the original cgroup */
+       ptr = malloc(4 * (1 << 20));
+       if (!ptr)
+               goto err;
+
+       /* close programs and cgroup fd */
+       for (i = 0; i < ARRAY_SIZE(allow_prog); i++) {
+               close(allow_prog[i]);
+               allow_prog[i] = 0;
+       }
+
+       close(cg);
+       cg = 0;
+
+       /* leave the cgroup and remove it. don't detach programs */
+       cleanup_cgroup_environment();
+
+       /* wait for the asynchronous auto-detachment.
+        * wait for no more than 5 sec and give up.
+        */
+       for (i = 0; i < ARRAY_SIZE(prog_ids); i++) {
+               for (attempts = 5; attempts >= 0; attempts--) {
+                       int fd = bpf_prog_get_fd_by_id(prog_ids[i]);
+
+                       if (fd < 0)
+                               break;
+
+                       /* don't leave the fd open */
+                       close(fd);
+
+                       if (!attempts)
+                               goto err;
+
+                       sleep(1);
+               }
+       }
+
+       rc = 0;
+err:
+       for (i = 0; i < ARRAY_SIZE(allow_prog); i++)
+               if (allow_prog[i] > 0)
+                       close(allow_prog[i]);
+       if (cg)
+               close(cg);
+       free(ptr);
+       cleanup_cgroup_environment();
+       if (!rc)
+               printf("#autodetach:PASS\n");
+       else
+               printf("#autodetach:FAIL\n");
+       return rc;
+}
+
 int main(int argc, char **argv)
 {
-       int (*tests[])(void) = {test_foo_bar, test_multiprog};
+       int (*tests[])(void) = {
+               test_foo_bar,
+               test_multiprog,
+               test_autodetach,
+       };
        int errors = 0;
        int i;
 
-- 
2.20.1

Reply via email to