selftests/bpf: fix bpf_loop_bench for new callback verification scheme
authorEduard Zingerman <eddyz87@gmail.com>
Tue, 21 Nov 2023 02:06:53 +0000 (04:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Dec 2023 16:01:57 +0000 (17:01 +0100)
[ Upstream commit f40bfd1679446b22d321e64a1fa98b7d07d2be08 ]

This is a preparatory change. A follow-up patch "bpf: verify callbacks
as if they are called unknown number of times" changes logic for
callbacks handling. While previously callbacks were verified as a
single function call, new scheme takes into account that callbacks
could be executed unknown number of times.

This has dire implications for bpf_loop_bench:

    SEC("fentry/" SYS_PREFIX "sys_getpgid")
    int benchmark(void *ctx)
    {
            for (int i = 0; i < 1000; i++) {
                    bpf_loop(nr_loops, empty_callback, NULL, 0);
                    __sync_add_and_fetch(&hits, nr_loops);
            }
            return 0;
    }

W/o callbacks change verifier sees it as a 1000 calls to
empty_callback(). However, with callbacks change things become
exponential:
- i=0: state exploring empty_callback is scheduled with i=0 (a);
- i=1: state exploring empty_callback is scheduled with i=1;
  ...
- i=999: state exploring empty_callback is scheduled with i=999;
- state (a) is popped from stack;
- i=1: state exploring empty_callback is scheduled with i=1;
  ...

Avoid this issue by rewriting outer loop as bpf_loop().
Unfortunately, this adds a function call to a loop at runtime, which
negatively affects performance:

            throughput               latency
   before:  149.919 ± 0.168 M ops/s, 6.670 ns/op
   after :  137.040 ± 0.187 M ops/s, 7.297 ns/op

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20231121020701.26440-4-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
tools/testing/selftests/bpf/progs/bpf_loop_bench.c

index 4ce76eb..d461746 100644 (file)
@@ -15,13 +15,16 @@ static int empty_callback(__u32 index, void *data)
        return 0;
 }
 
+static int outer_loop(__u32 index, void *data)
+{
+       bpf_loop(nr_loops, empty_callback, NULL, 0);
+       __sync_add_and_fetch(&hits, nr_loops);
+       return 0;
+}
+
 SEC("fentry/" SYS_PREFIX "sys_getpgid")
 int benchmark(void *ctx)
 {
-       for (int i = 0; i < 1000; i++) {
-               bpf_loop(nr_loops, empty_callback, NULL, 0);
-
-               __sync_add_and_fetch(&hits, nr_loops);
-       }
+       bpf_loop(1000, outer_loop, NULL, 0);
        return 0;
 }