1. 07 8月, 2020 1 次提交
  2. 14 7月, 2020 1 次提交
  3. 01 7月, 2020 1 次提交
  4. 03 6月, 2020 1 次提交
  5. 02 6月, 2020 1 次提交
    • A
      bpf: Add BPF ringbuf and perf buffer benchmarks · c97099b0
      Andrii Nakryiko 提交于
      Extend bench framework with ability to have benchmark-provided child argument
      parser for custom benchmark-specific parameters. This makes bench generic code
      modular and independent from any specific benchmark.
      
      Also implement a set of benchmarks for new BPF ring buffer and existing perf
      buffer. 4 benchmarks were implemented: 2 variations for each of BPF ringbuf
      and perfbuf:,
        - rb-libbpf utilizes stock libbpf ring_buffer manager for reading data;
        - rb-custom implements custom ring buffer setup and reading code, to
          eliminate overheads inherent in generic libbpf code due to callback
          functions and the need to update consumer position after each consumed
          record, instead of batching updates (due to pessimistic assumption that
          user callback might take long time and thus could unnecessarily hold ring
          buffer space for too long);
        - pb-libbpf uses stock libbpf perf_buffer code with all the default
          settings, though uses higher-performance raw event callback to minimize
          unnecessary overhead;
        - pb-custom implements its own custom consumer code to minimize any possible
          overhead of generic libbpf implementation and indirect function calls.
      
      All of the test support default, no data notification skipped, mode, as well
      as sampled mode (with --rb-sampled flag), which allows to trigger epoll
      notification less frequently and reduce overhead. As will be shown, this mode
      is especially critical for perf buffer, which suffers from high overhead of
      wakeups in kernel.
      
      Otherwise, all benchamrks implement similar way to generate a batch of records
      by using fentry/sys_getpgid BPF program, which pushes a bunch of records in
      a tight loop and records number of successful and dropped samples. Each record
      is a small 8-byte integer, to minimize the effect of memory copying with
      bpf_perf_event_output() and bpf_ringbuf_output().
      
      Benchmarks that have only one producer implement optional back-to-back mode,
      in which record production and consumption is alternating on the same CPU.
      This is the highest-throughput happy case, showing ultimate performance
      achievable with either BPF ringbuf or perfbuf.
      
      All the below scenarios are implemented in a script in
      benchs/run_bench_ringbufs.sh. Tests were performed on 28-core/56-thread
      Intel Xeon CPU E5-2680 v4 @ 2.40GHz CPU.
      
      Single-producer, parallel producer
      ==================================
      rb-libbpf            12.054 ± 0.320M/s (drops 0.000 ± 0.000M/s)
      rb-custom            8.158 ± 0.118M/s (drops 0.001 ± 0.003M/s)
      pb-libbpf            0.931 ± 0.007M/s (drops 0.000 ± 0.000M/s)
      pb-custom            0.965 ± 0.003M/s (drops 0.000 ± 0.000M/s)
      
      Single-producer, parallel producer, sampled notification
      ========================================================
      rb-libbpf            11.563 ± 0.067M/s (drops 0.000 ± 0.000M/s)
      rb-custom            15.895 ± 0.076M/s (drops 0.000 ± 0.000M/s)
      pb-libbpf            9.889 ± 0.032M/s (drops 0.000 ± 0.000M/s)
      pb-custom            9.866 ± 0.028M/s (drops 0.000 ± 0.000M/s)
      
      Single producer on one CPU, consumer on another one, both running at full
      speed. Curiously, rb-libbpf has higher throughput than objectively faster (due
      to more lightweight consumer code path) rb-custom. It appears that faster
      consumer causes kernel to send notifications more frequently, because consumer
      appears to be caught up more frequently. Performance of perfbuf suffers from
      default "no sampling" policy and huge overhead that causes.
      
      In sampled mode, rb-custom is winning very significantly eliminating too
      frequent in-kernel wakeups, the gain appears to be more than 2x.
      
      Perf buffer achieves even more impressive wins, compared to stock perfbuf
      settings, with 10x improvements in throughput with 1:500 sampling rate. The
      trade-off is that with sampling, application might not get next X events until
      X+1st arrives, which is not always acceptable. With steady influx of events,
      though, this shouldn't be a problem.
      
      Overall, single-producer performance of ring buffers seems to be better no
      matter the sampled/non-sampled modes, but it especially beats ring buffer
      without sampling due to its adaptive notification approach.
      
      Single-producer, back-to-back mode
      ==================================
      rb-libbpf            15.507 ± 0.247M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf-sampled    14.692 ± 0.195M/s (drops 0.000 ± 0.000M/s)
      rb-custom            21.449 ± 0.157M/s (drops 0.000 ± 0.000M/s)
      rb-custom-sampled    20.024 ± 0.386M/s (drops 0.000 ± 0.000M/s)
      pb-libbpf            1.601 ± 0.015M/s (drops 0.000 ± 0.000M/s)
      pb-libbpf-sampled    8.545 ± 0.064M/s (drops 0.000 ± 0.000M/s)
      pb-custom            1.607 ± 0.022M/s (drops 0.000 ± 0.000M/s)
      pb-custom-sampled    8.988 ± 0.144M/s (drops 0.000 ± 0.000M/s)
      
      Here we test a back-to-back mode, which is arguably best-case scenario both
      for BPF ringbuf and perfbuf, because there is no contention and for ringbuf
      also no excessive notification, because consumer appears to be behind after
      the first record. For ringbuf, custom consumer code clearly wins with 21.5 vs
      16 million records per second exchanged between producer and consumer. Sampled
      mode actually hurts a bit due to slightly slower producer logic (it needs to
      fetch amount of data available to decide whether to skip or force notification).
      
      Perfbuf with wakeup sampling gets 5.5x throughput increase, compared to
      no-sampling version. There also doesn't seem to be noticeable overhead from
      generic libbpf handling code.
      
      Perfbuf back-to-back, effect of sample rate
      ===========================================
      pb-sampled-1         1.035 ± 0.012M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-5         3.476 ± 0.087M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-10        5.094 ± 0.136M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-25        7.118 ± 0.153M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-50        8.169 ± 0.156M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-100       8.887 ± 0.136M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-250       9.180 ± 0.209M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-500       9.353 ± 0.281M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-1000      9.411 ± 0.217M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-2000      9.464 ± 0.167M/s (drops 0.000 ± 0.000M/s)
      pb-sampled-3000      9.575 ± 0.273M/s (drops 0.000 ± 0.000M/s)
      
      This benchmark shows the effect of event sampling for perfbuf. Back-to-back
      mode for highest throughput. Just doing every 5th record notification gives
      3.5x speed up. 250-500 appears to be the point of diminishing return, with
      almost 9x speed up. Most benchmarks use 500 as the default sampling for pb-raw
      and pb-custom.
      
      Ringbuf back-to-back, effect of sample rate
      ===========================================
      rb-sampled-1         1.106 ± 0.010M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-5         4.746 ± 0.149M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-10        7.706 ± 0.164M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-25        12.893 ± 0.273M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-50        15.961 ± 0.361M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-100       18.203 ± 0.445M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-250       19.962 ± 0.786M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-500       20.881 ± 0.551M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-1000      21.317 ± 0.532M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-2000      21.331 ± 0.535M/s (drops 0.000 ± 0.000M/s)
      rb-sampled-3000      21.688 ± 0.392M/s (drops 0.000 ± 0.000M/s)
      
      Similar benchmark for ring buffer also shows a great advantage (in terms of
      throughput) of skipping notifications. Skipping every 5th one gives 4x boost.
      Also similar to perfbuf case, 250-500 seems to be the point of diminishing
      returns, giving roughly 20x better results.
      
      Keep in mind, for this test, notifications are controlled manually with
      BPF_RB_NO_WAKEUP and BPF_RB_FORCE_WAKEUP. As can be seen from previous
      benchmarks, adaptive notifications based on consumer's positions provides same
      (or even slightly better due to simpler load generator on BPF side) benefits in
      favorable back-to-back scenario. Over zealous and fast consumer, which is
      almost always caught up, will make thoughput numbers smaller. That's the case
      when manual notification control might prove to be extremely beneficial.
      
      Ringbuf back-to-back, reserve+commit vs output
      ==============================================
      reserve              22.819 ± 0.503M/s (drops 0.000 ± 0.000M/s)
      output               18.906 ± 0.433M/s (drops 0.000 ± 0.000M/s)
      
      Ringbuf sampled, reserve+commit vs output
      =========================================
      reserve-sampled      15.350 ± 0.132M/s (drops 0.000 ± 0.000M/s)
      output-sampled       14.195 ± 0.144M/s (drops 0.000 ± 0.000M/s)
      
      BPF ringbuf supports two sets of APIs with various usability and performance
      tradeoffs: bpf_ringbuf_reserve()+bpf_ringbuf_commit() vs bpf_ringbuf_output().
      This benchmark clearly shows superiority of reserve+commit approach, despite
      using a small 8-byte record size.
      
      Single-producer, consumer/producer competing on the same CPU, low batch count
      =============================================================================
      rb-libbpf            3.045 ± 0.020M/s (drops 3.536 ± 0.148M/s)
      rb-custom            3.055 ± 0.022M/s (drops 3.893 ± 0.066M/s)
      pb-libbpf            1.393 ± 0.024M/s (drops 0.000 ± 0.000M/s)
      pb-custom            1.407 ± 0.016M/s (drops 0.000 ± 0.000M/s)
      
      This benchmark shows one of the worst-case scenarios, in which producer and
      consumer do not coordinate *and* fight for the same CPU. No batch count and
      sampling settings were able to eliminate drops for ringbuffer, producer is
      just too fast for consumer to keep up. But ringbuf and perfbuf still able to
      pass through quite a lot of messages, which is more than enough for a lot of
      applications.
      
      Ringbuf, multi-producer contention
      ==================================
      rb-libbpf nr_prod 1  10.916 ± 0.399M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 2  4.931 ± 0.030M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 3  4.880 ± 0.006M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 4  3.926 ± 0.004M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 8  4.011 ± 0.004M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 12 3.967 ± 0.016M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 16 2.604 ± 0.030M/s (drops 0.001 ± 0.002M/s)
      rb-libbpf nr_prod 20 2.233 ± 0.003M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 24 2.085 ± 0.015M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 28 2.055 ± 0.004M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 32 1.962 ± 0.004M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 36 2.089 ± 0.005M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 40 2.118 ± 0.006M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 44 2.105 ± 0.004M/s (drops 0.000 ± 0.000M/s)
      rb-libbpf nr_prod 48 2.120 ± 0.058M/s (drops 0.000 ± 0.001M/s)
      rb-libbpf nr_prod 52 2.074 ± 0.024M/s (drops 0.007 ± 0.014M/s)
      
      Ringbuf uses a very short-duration spinlock during reservation phase, to check
      few invariants, increment producer count and set record header. This is the
      biggest point of contention for ringbuf implementation. This benchmark
      evaluates the effect of multiple competing writers on overall throughput of
      a single shared ringbuffer.
      
      Overall throughput drops almost 2x when going from single to two
      highly-contended producers, gradually dropping with additional competing
      producers.  Performance drop stabilizes at around 20 producers and hovers
      around 2mln even with 50+ fighting producers, which is a 5x drop compared to
      non-contended case. Good kernel implementation in kernel helps maintain decent
      performance here.
      
      Note, that in the intended real-world scenarios, it's not expected to get even
      close to such a high levels of contention. But if contention will become
      a problem, there is always an option of sharding few ring buffers across a set
      of CPUs.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
      Link: https://lore.kernel.org/bpf/20200529075424.3139988-5-andriin@fb.comSigned-off-by: NAlexei Starovoitov <ast@kernel.org>
      c97099b0
  6. 14 5月, 2020 4 次提交
    • A
      selftest/bpf: Add BPF triggering benchmark · c5d420c3
      Andrii Nakryiko 提交于
      It is sometimes desirable to be able to trigger BPF program from user-space
      with minimal overhead. sys_enter would seem to be a good candidate, yet in
      a lot of cases there will be a lot of noise from syscalls triggered by other
      processes on the system. So while searching for low-overhead alternative, I've
      stumbled upon getpgid() syscall, which seems to be specific enough to not
      suffer from accidental syscall by other apps.
      
      This set of benchmarks compares tp, raw_tp w/ filtering by syscall ID, kprobe,
      fentry and fmod_ret with returning error (so that syscall would not be
      executed), to determine the lowest-overhead way. Here are results on my
      machine (using benchs/run_bench_trigger.sh script):
      
        base      :    9.200 ± 0.319M/s
        tp        :    6.690 ± 0.125M/s
        rawtp     :    8.571 ± 0.214M/s
        kprobe    :    6.431 ± 0.048M/s
        fentry    :    8.955 ± 0.241M/s
        fmodret   :    8.903 ± 0.135M/s
      
      So it seems like fmodret doesn't give much benefit for such lightweight
      syscall. Raw tracepoint is pretty decent despite additional filtering logic,
      but it will be called for any other syscall in the system, which rules it out.
      Fentry, though, seems to be adding the least amoung of overhead and achieves
      97.3% of performance of baseline no-BPF-attached syscall.
      
      Using getpgid() seems to be preferable to set_task_comm() approach from
      test_overhead, as it's about 2.35x faster in a baseline performance.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NJohn Fastabend <john.fastabend@gmail.com>
      Acked-by: NYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20200512192445.2351848-5-andriin@fb.com
      c5d420c3
    • A
      selftest/bpf: Fmod_ret prog and implement test_overhead as part of bench · 4eaf0b5c
      Andrii Nakryiko 提交于
      Add fmod_ret BPF program to existing test_overhead selftest. Also re-implement
      user-space benchmarking part into benchmark runner to compare results. Results
      with ./bench are consistently somewhat lower than test_overhead's, but relative
      performance of various types of BPF programs stay consisten (e.g., kretprobe is
      noticeably slower). This slowdown seems to be coming from the fact that
      test_overhead is single-threaded, while benchmark always spins off at least
      one thread for producer. This has been confirmed by hacking multi-threaded
      test_overhead variant and also single-threaded bench variant. Resutls are
      below. run_bench_rename.sh script from benchs/ subdirectory was used to
      produce results for ./bench.
      
      Single-threaded implementations
      ===============================
      
      /* bench: single-threaded, atomics */
      base      :    4.622 ± 0.049M/s
      kprobe    :    3.673 ± 0.052M/s
      kretprobe :    2.625 ± 0.052M/s
      rawtp     :    4.369 ± 0.089M/s
      fentry    :    4.201 ± 0.558M/s
      fexit     :    4.309 ± 0.148M/s
      fmodret   :    4.314 ± 0.203M/s
      
      /* selftest: single-threaded, no atomics */
      task_rename base        4555K events per sec
      task_rename kprobe      3643K events per sec
      task_rename kretprobe   2506K events per sec
      task_rename raw_tp      4303K events per sec
      task_rename fentry      4307K events per sec
      task_rename fexit       4010K events per sec
      task_rename fmod_ret    3984K events per sec
      
      Multi-threaded implementations
      ==============================
      
      /* bench: multi-threaded w/ atomics */
      base      :    3.910 ± 0.023M/s
      kprobe    :    3.048 ± 0.037M/s
      kretprobe :    2.300 ± 0.015M/s
      rawtp     :    3.687 ± 0.034M/s
      fentry    :    3.740 ± 0.087M/s
      fexit     :    3.510 ± 0.009M/s
      fmodret   :    3.485 ± 0.050M/s
      
      /* selftest: multi-threaded w/ atomics */
      task_rename base        3872K events per sec
      task_rename kprobe      3068K events per sec
      task_rename kretprobe   2350K events per sec
      task_rename raw_tp      3731K events per sec
      task_rename fentry      3639K events per sec
      task_rename fexit       3558K events per sec
      task_rename fmod_ret    3511K events per sec
      
      /* selftest: multi-threaded, no atomics */
      task_rename base        3945K events per sec
      task_rename kprobe      3298K events per sec
      task_rename kretprobe   2451K events per sec
      task_rename raw_tp      3718K events per sec
      task_rename fentry      3782K events per sec
      task_rename fexit       3543K events per sec
      task_rename fmod_ret    3526K events per sec
      
      Note that the fact that ./bench benchmark always uses atomic increments for
      counting, while test_overhead doesn't, doesn't influence test results all that
      much.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NJohn Fastabend <john.fastabend@gmail.com>
      Acked-by: NYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20200512192445.2351848-4-andriin@fb.com
      4eaf0b5c
    • A
      selftests/bpf: Add benchmark runner infrastructure · 8e7c2a02
      Andrii Nakryiko 提交于
      While working on BPF ringbuf implementation, testing, and benchmarking, I've
      developed a pretty generic and modular benchmark runner, which seems to be
      generically useful, as I've already used it for one more purpose (testing
      fastest way to trigger BPF program, to minimize overhead of in-kernel code).
      
      This patch adds generic part of benchmark runner and sets up Makefile for
      extending it with more sets of benchmarks.
      
      Benchmarker itself operates by spinning up specified number of producer and
      consumer threads, setting up interval timer sending SIGALARM signal to
      application once a second. Every second, current snapshot with hits/drops
      counters are collected and stored in an array. Drops are useful for
      producer/consumer benchmarks in which producer might overwhelm consumers.
      
      Once test finishes after given amount of warm-up and testing seconds, mean and
      stddev are calculated (ignoring warm-up results) and is printed out to stdout.
      This setup seems to give consistent and accurate results.
      
      To validate behavior, I added two atomic counting tests: global and local.
      For global one, all the producer threads are atomically incrementing same
      counter as fast as possible. This, of course, leads to huge drop of
      performance once there is more than one producer thread due to CPUs fighting
      for the same memory location.
      
      Local counting, on the other hand, maintains one counter per each producer
      thread, incremented independently. Once per second, all counters are read and
      added together to form final "counting throughput" measurement. As expected,
      such setup demonstrates linear scalability with number of producers (as long
      as there are enough physical CPU cores, of course). See example output below.
      Also, this setup can nicely demonstrate disastrous effects of false sharing,
      if care is not taken to take those per-producer counters apart into
      independent cache lines.
      
      Demo output shows global counter first with 1 producer, then with 4. Both
      total and per-producer performance significantly drop. The last run is local
      counter with 4 producers, demonstrating near-perfect scalability.
      
      $ ./bench -a -w1 -d2 -p1 count-global
      Setting up benchmark 'count-global'...
      Benchmark 'count-global' started.
      Iter   0 ( 24.822us): hits  148.179M/s (148.179M/prod), drops    0.000M/s
      Iter   1 ( 37.939us): hits  149.308M/s (149.308M/prod), drops    0.000M/s
      Iter   2 (-10.774us): hits  150.717M/s (150.717M/prod), drops    0.000M/s
      Iter   3 (  3.807us): hits  151.435M/s (151.435M/prod), drops    0.000M/s
      Summary: hits  150.488 ± 1.079M/s (150.488M/prod), drops    0.000 ± 0.000M/s
      
      $ ./bench -a -w1 -d2 -p4 count-global
      Setting up benchmark 'count-global'...
      Benchmark 'count-global' started.
      Iter   0 ( 60.659us): hits   53.910M/s ( 13.477M/prod), drops    0.000M/s
      Iter   1 (-17.658us): hits   53.722M/s ( 13.431M/prod), drops    0.000M/s
      Iter   2 (  5.865us): hits   53.495M/s ( 13.374M/prod), drops    0.000M/s
      Iter   3 (  0.104us): hits   53.606M/s ( 13.402M/prod), drops    0.000M/s
      Summary: hits   53.608 ± 0.113M/s ( 13.402M/prod), drops    0.000 ± 0.000M/s
      
      $ ./bench -a -w1 -d2 -p4 count-local
      Setting up benchmark 'count-local'...
      Benchmark 'count-local' started.
      Iter   0 ( 23.388us): hits  640.450M/s (160.113M/prod), drops    0.000M/s
      Iter   1 (  2.291us): hits  605.661M/s (151.415M/prod), drops    0.000M/s
      Iter   2 ( -6.415us): hits  607.092M/s (151.773M/prod), drops    0.000M/s
      Iter   3 ( -1.361us): hits  601.796M/s (150.449M/prod), drops    0.000M/s
      Summary: hits  604.849 ± 2.739M/s (151.212M/prod), drops    0.000 ± 0.000M/s
      
      Benchmark runner supports setting thread affinity for producer and consumer
      threads. You can use -a flag for default CPU selection scheme, where first
      consumer gets CPU #0, next one gets CPU #1, and so on. Then producer threads
      pick up next CPU and increment one-by-one as well. But user can also specify
      a set of CPUs independently for producers and consumers with --prod-affinity
      1,2-10,15 and --cons-affinity <set-of-cpus>. The latter allows to force
      producers and consumers to share same set of CPUs, if necessary.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20200512192445.2351848-3-andriin@fb.com
      8e7c2a02
    • A
      selftests/bpf: Extract parse_num_list into generic testing_helpers.c · cd49291c
      Andrii Nakryiko 提交于
      Add testing_helpers.c, which will contain generic helpers for test runners and
      tests needing some common generic functionality, like parsing a set of
      numbers.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NYonghong Song <yhs@fb.com>
      Link: https://lore.kernel.org/bpf/20200512192445.2351848-2-andriin@fb.com
      cd49291c
  7. 13 5月, 2020 1 次提交
  8. 09 5月, 2020 1 次提交
  9. 30 4月, 2020 1 次提交
  10. 29 4月, 2020 4 次提交
  11. 14 3月, 2020 2 次提交
  12. 13 3月, 2020 1 次提交
  13. 05 3月, 2020 1 次提交
  14. 27 2月, 2020 1 次提交
  15. 26 2月, 2020 1 次提交
    • A
      selftests/bpf: Print backtrace on SIGSEGV in test_progs · 9fb156bb
      Andrii Nakryiko 提交于
      Due to various bugs in tests clean up code (usually), if host system is
      misconfigured, it happens that test_progs will just crash in the middle of
      running a test with little to no indication of where and why the crash
      happened. For cases where coredump is not readily available (e.g., inside
      a CI), it's very helpful to have a stack trace, which lead to crash, to be
      printed out. This change adds a signal handler that will capture and print out
      symbolized backtrace:
      
        $ sudo ./test_progs -t mmap
        test_mmap:PASS:skel_open_and_load 0 nsec
        test_mmap:PASS:bss_mmap 0 nsec
        test_mmap:PASS:data_mmap 0 nsec
        Caught signal #11!
        Stack trace:
        ./test_progs(crash_handler+0x18)[0x42a888]
        /lib64/libpthread.so.0(+0xf5d0)[0x7f2aab5175d0]
        ./test_progs(test_mmap+0x3c0)[0x41f0a0]
        ./test_progs(main+0x160)[0x407d10]
        /lib64/libc.so.6(__libc_start_main+0xf5)[0x7f2aab15d3d5]
        ./test_progs[0x407ebc]
        [1]    1988412 segmentation fault (core dumped)  sudo ./test_progs -t mmap
      
      Unfortunately, glibc's symbolization support is unable to symbolize static
      functions, only global ones will be present in stack trace. But it's still a
      step forward without adding extra libraries to get a better symbolization.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NDaniel Borkmann <daniel@iogearbox.net>
      Acked-by: NSong Liu <songliubraving@fb.com>
      Link: https://lore.kernel.org/bpf/20200225000847.3965188-1-andriin@fb.com
      9fb156bb
  16. 20 2月, 2020 1 次提交
  17. 24 1月, 2020 1 次提交
  18. 23 1月, 2020 1 次提交
  19. 21 1月, 2020 3 次提交
  20. 15 1月, 2020 1 次提交
  21. 14 1月, 2020 1 次提交
  22. 10 1月, 2020 3 次提交
  23. 27 12月, 2019 1 次提交
  24. 23 12月, 2019 1 次提交
  25. 20 12月, 2019 1 次提交
    • A
      selftests/bpf: Convert test_cgroup_attach to prog_tests · 257c8855
      Andrey Ignatov 提交于
      Convert test_cgroup_attach to prog_tests.
      
      This change does a lot of things but in many cases it's pretty expensive
      to separate them, so they go in one commit. Nevertheless the logic is
      ketp as is and changes made are just moving things around, simplifying
      them (w/o changing the meaning of the tests) and making prog_tests
      compatible:
      
      * split the 3 tests in the file into 3 separate files in prog_tests/;
      
      * rename the test functions to test_<file_base_name>;
      
      * remove unused includes, constants, variables and functions from every
        test;
      
      * replace `if`-s with or `if (CHECK())` where additional context should
        be logged and with `if (CHECK_FAIL())` where line number is enough;
      
      * switch from `log_err()` to logging via `CHECK()`;
      
      * replace `assert`-s with `CHECK_FAIL()` to avoid crashing the whole
        test_progs if one assertion fails;
      
      * replace cgroup_helpers with test__join_cgroup() in
        cgroup_attach_override only, other tests need more fine-grained
        control for cgroup creation/deletion so cgroup_helpers are still used
        there;
      
      * simplify cgroup_attach_autodetach by switching to easiest possible
        program since this test doesn't really need such a complicated program
        as cgroup_attach_multi does;
      
      * remove test_cgroup_attach.c itself.
      Signed-off-by: NAndrey Ignatov <rdna@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NAndrii Nakryiko <andriin@fb.com>
      Link: https://lore.kernel.org/bpf/0ff19cc64d2dc5cf404349f07131119480e10e32.1576741281.git.rdna@fb.com
      257c8855
  26. 18 12月, 2019 1 次提交
  27. 16 12月, 2019 2 次提交
    • A
      libbpf: Support libbpf-provided extern variables · 166750bc
      Andrii Nakryiko 提交于
      Add support for extern variables, provided to BPF program by libbpf. Currently
      the following extern variables are supported:
        - LINUX_KERNEL_VERSION; version of a kernel in which BPF program is
          executing, follows KERNEL_VERSION() macro convention, can be 4- and 8-byte
          long;
        - CONFIG_xxx values; a set of values of actual kernel config. Tristate,
          boolean, strings, and integer values are supported.
      
      Set of possible values is determined by declared type of extern variable.
      Supported types of variables are:
      - Tristate values. Are represented as `enum libbpf_tristate`. Accepted values
        are **strictly** 'y', 'n', or 'm', which are represented as TRI_YES, TRI_NO,
        or TRI_MODULE, respectively.
      - Boolean values. Are represented as bool (_Bool) types. Accepted values are
        'y' and 'n' only, turning into true/false values, respectively.
      - Single-character values. Can be used both as a substritute for
        bool/tristate, or as a small-range integer:
        - 'y'/'n'/'m' are represented as is, as characters 'y', 'n', or 'm';
        - integers in a range [-128, 127] or [0, 255] (depending on signedness of
          char in target architecture) are recognized and represented with
          respective values of char type.
      - Strings. String values are declared as fixed-length char arrays. String of
        up to that length will be accepted and put in first N bytes of char array,
        with the rest of bytes zeroed out. If config string value is longer than
        space alloted, it will be truncated and warning message emitted. Char array
        is always zero terminated. String literals in config have to be enclosed in
        double quotes, just like C-style string literals.
      - Integers. 8-, 16-, 32-, and 64-bit integers are supported, both signed and
        unsigned variants. Libbpf enforces parsed config value to be in the
        supported range of corresponding integer type. Integers values in config can
        be:
        - decimal integers, with optional + and - signs;
        - hexadecimal integers, prefixed with 0x or 0X;
        - octal integers, starting with 0.
      
      Config file itself is searched in /boot/config-$(uname -r) location with
      fallback to /proc/config.gz, unless config path is specified explicitly
      through bpf_object_open_opts' kernel_config_path option. Both gzipped and
      plain text formats are supported. Libbpf adds explicit dependency on zlib
      because of this, but this shouldn't be a problem, given libelf already depends
      on zlib.
      
      All detected extern variables, are put into a separate .extern internal map.
      It, similarly to .rodata map, is marked as read-only from BPF program side, as
      well as is frozen on load. This allows BPF verifier to track extern values as
      constants and perform enhanced branch prediction and dead code elimination.
      This can be relied upon for doing kernel version/feature detection and using
      potentially unsupported field relocations or BPF helpers in a CO-RE-based BPF
      program, while still having a single version of BPF program running on old and
      new kernels. Selftests are validating this explicitly for unexisting BPF
      helper.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Link: https://lore.kernel.org/bpf/20191214014710.3449601-3-andriin@fb.com
      166750bc
    • A
      selftests/bpf: Add BPF skeletons selftests and convert attach_probe.c · f3c926a4
      Andrii Nakryiko 提交于
      Add BPF skeleton generation to selftest/bpf's Makefile. Convert attach_probe.c
      to use skeleton.
      Signed-off-by: NAndrii Nakryiko <andriin@fb.com>
      Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
      Acked-by: NMartin KaFai Lau <kafai@fb.com>
      Link: https://lore.kernel.org/bpf/20191214014341.3442258-15-andriin@fb.com
      f3c926a4
  28. 14 12月, 2019 1 次提交