1. 30 Jul, 2024 9 commits
    • Tony Ambardar's avatar
      selftests/bpf: Fix error compiling tc_redirect.c with musl libc · 21c5f4f5
      Tony Ambardar authored
      Linux 5.1 implemented 64-bit time types and related syscalls to address the
      Y2038 problem generally across archs. Userspace handling of Y2038 varies
      with the libc however. While musl libc uses 64-bit time across all 32-bit
      and 64-bit platforms, GNU glibc uses 64-bit time on 64-bit platforms but
      defaults to 32-bit time on 32-bit platforms unless they "opt-in" to 64-bit
      time or explicitly use 64-bit syscalls and time structures.
      
      One specific area is the standard setsockopt() call, SO_TIMESTAMPNS option
      used for timestamping, and the related output 'struct timespec'. GNU glibc
      defaults as above, also exposing the SO_TIMESTAMPNS_NEW flag to explicitly
      use a 64-bit call and 'struct __kernel_timespec'. Since these are not
      exposed or needed with musl libc, their use in tc_redirect.c leads to
      compile errors building for mips64el/musl:
      
        tc_redirect.c: In function 'rcv_tstamp':
        tc_redirect.c:425:32: error: 'SO_TIMESTAMPNS_NEW' undeclared (first use in this function); did you mean 'SO_TIMESTAMPNS'?
          425 |             cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
              |                                ^~~~~~~~~~~~~~~~~~
              |                                SO_TIMESTAMPNS
        tc_redirect.c:425:32: note: each undeclared identifier is reported only once for each function it appears in
        tc_redirect.c: In function 'test_inet_dtime':
        tc_redirect.c:491:49: error: 'SO_TIMESTAMPNS_NEW' undeclared (first use in this function); did you mean 'SO_TIMESTAMPNS'?
          491 |         err = setsockopt(listen_fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
              |                                                 ^~~~~~~~~~~~~~~~~~
              |                                                 SO_TIMESTAMPNS
      
      However, using SO_TIMESTAMPNS_NEW isn't strictly needed, nor is Y2038 being
      explicitly tested. The timestamp checks in tc_redirect.c are simple: the
      packet receive timestamp is non-zero and processed/handled in less than 5
      seconds.
      
      Switch to using the standard setsockopt() call and SO_TIMESTAMPNS option to
      ensure compatibility across glibc and musl libc. In the worst-case, there
      is a 5-second window 14 years from now where tc_redirect tests may fail on
      32-bit systems. However, we should reasonably expect glibc to adopt a
      64-bit mandate rather than the current "opt-in" policy before the Y2038
      roll-over.
      
      Fixes: ce6f6cff ("selftests/bpf: Wait for the netstamp_needed_key static key to be turned on")
      Fixes: c803475f ("bpf: selftests: test skb->tstamp in redirect_neigh")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/031d656c058b4e55ceae56ef49c4e1729b5090f3.1722244708.git.tony.ambardar@gmail.com
      21c5f4f5
    • Tony Ambardar's avatar
      selftests/bpf: Fix using stdout, stderr as struct field names · 06eeca12
      Tony Ambardar authored
      Typically stdin, stdout, stderr are treated as reserved identifiers under
      ISO/ANSI C and libc implementations further define these as macros, both in
      glibc and musl <stdio.h>.
      
      However, while glibc defines:
          ...
          /* Standard streams.  */
          extern FILE *stdin;             /* Standard input stream.  */
          extern FILE *stdout;            /* Standard output stream.  */
          extern FILE *stderr;            /* Standard error output stream.  */
          /* C89/C99 say they're macros.  Make them happy.  */
          #define stdin stdin
          #define stdout stdout
          #define stderr stderr
          ...
      
      musl instead uses (legally):
          ...
          extern FILE *const stdin;
          extern FILE *const stdout;
          extern FILE *const stderr;
      
          #define stdin  (stdin)
          #define stdout (stdout)
          #define stderr (stderr)
          ...
      
      The latter results in compile errors when the names are reused as fields of
      'struct test_env' and elsewhere in test_progs.[ch] and reg_bounds.c.
      
      Rename the fields to stdout_saved and stderr_saved to avoid many errors
      seen building against musl, e.g.:
      
        In file included from test_progs.h:6,
                         from test_progs.c:5:
        test_progs.c: In function 'print_test_result':
        test_progs.c:237:21: error: expected identifier before '(' token
          237 |         fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
              |                     ^~~~~~
        test_progs.c:237:9: error: too few arguments to function 'fprintf'
          237 |         fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
              |         ^~~~~~~
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/ZqR2DuHdBXPX%2Fyx8@kodidev-ubuntu/
      Link: https://lore.kernel.org/bpf/684ea17548e237f39dfb3f7a3d33450069015b21.1722244708.git.tony.ambardar@gmail.com
      06eeca12
    • Tony Ambardar's avatar
      selftests/bpf: Fix compile if backtrace support missing in libc · c9a83e76
      Tony Ambardar authored
      Include GNU <execinfo.h> header only with glibc and provide weak, stubbed
      backtrace functions as a fallback in test_progs.c. This allows for non-GNU
      replacements while avoiding compile errors (e.g. with musl libc) like:
      
        test_progs.c:13:10: fatal error: execinfo.h: No such file or directory
           13 | #include <execinfo.h> /* backtrace */
              |          ^~~~~~~~~~~~
        test_progs.c: In function 'crash_handler':
        test_progs.c:1034:14: error: implicit declaration of function 'backtrace' [-Werror=implicit-function-declaration]
         1034 |         sz = backtrace(bt, ARRAY_SIZE(bt));
              |              ^~~~~~~~~
        test_progs.c:1045:9: error: implicit declaration of function 'backtrace_symbols_fd' [-Werror=implicit-function-declaration]
         1045 |         backtrace_symbols_fd(bt, sz, STDERR_FILENO);
              |         ^~~~~~~~~~~~~~~~~~~~
      
      Fixes: 9fb156bb ("selftests/bpf: Print backtrace on SIGSEGV in test_progs")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/aa6dc8e23710cb457b278039d0081de7e7b4847d.1722244708.git.tony.ambardar@gmail.com
      c9a83e76
    • Tony Ambardar's avatar
      selftests/bpf: Fix redefinition errors compiling lwt_reroute.c · 16b795cc
      Tony Ambardar authored
      Compiling lwt_reroute.c with GCC 12.3 for mips64el/musl-libc yields errors:
      
      In file included from .../include/arpa/inet.h:9,
                       from ./test_progs.h:18,
                       from tools/testing/selftests/bpf/prog_tests/lwt_helpers.h:11,
                       from tools/testing/selftests/bpf/prog_tests/lwt_reroute.c:52:
      .../include/netinet/in.h:23:8: error: redefinition of 'struct in6_addr'
         23 | struct in6_addr {
            |        ^~~~~~~~
      In file included from .../include/linux/icmp.h:24,
                       from tools/testing/selftests/bpf/prog_tests/lwt_helpers.h:9:
      .../include/linux/in6.h:33:8: note: originally defined here
         33 | struct in6_addr {
            |        ^~~~~~~~
      .../include/netinet/in.h:34:8: error: redefinition of 'struct sockaddr_in6'
         34 | struct sockaddr_in6 {
            |        ^~~~~~~~~~~~
      .../include/linux/in6.h:50:8: note: originally defined here
         50 | struct sockaddr_in6 {
            |        ^~~~~~~~~~~~
      .../include/netinet/in.h:42:8: error: redefinition of 'struct ipv6_mreq'
         42 | struct ipv6_mreq {
            |        ^~~~~~~~~
      .../include/linux/in6.h:60:8: note: originally defined here
         60 | struct ipv6_mreq {
            |        ^~~~~~~~~
      
      These errors occur because <linux/in6.h> is included before <netinet/in.h>,
      bypassing the Linux uapi/libc compat mechanism's partial musl support. As
      described in [1] and [2], fix these errors by including <netinet/in.h> in
      lwt_reroute.c before any uapi headers.
      
      [1]: commit c0bace79 ("uapi libc compat: add fallback for unsupported libcs")
      [2]: https://git.musl-libc.org/cgit/musl/commit/?id=04983f227238
      
      Fixes: 6c77997b ("selftests/bpf: Add lwt_xmit tests for BPF_REROUTE")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/bd2908aec0755ba8b75f5dc41848b00585f5c73e.1722244708.git.tony.ambardar@gmail.com
      16b795cc
    • Tony Ambardar's avatar
      selftests/bpf: Fix C++ compile error from missing _Bool type · aa95073f
      Tony Ambardar authored
      While building, bpftool makes a skeleton from test_core_extern.c, which
      itself includes <stdbool.h> and uses the 'bool' type. However, the skeleton
      test_core_extern.skel.h generated *does not* include <stdbool.h> or use the
      'bool' type, instead using the C-only '_Bool' type. Compiling test_cpp.cpp
      with g++ 12.3 for mips64el/musl-libc then fails with error:
      
        In file included from test_cpp.cpp:9:
        test_core_extern.skel.h:45:17: error: '_Bool' does not name a type
           45 |                 _Bool CONFIG_BOOL;
              |                 ^~~~~
      
      This was likely missed previously because glibc uses a GNU extension for
      <stdbool.h> with C++ (#define _Bool bool), not supported by musl libc.
      
      Normally, a C fragment would include <stdbool.h> and use the 'bool' type,
      and thus cleanly work after import by C++. The ideal fix would be for
      'bpftool gen skeleton' to output the correct type/include supporting C++,
      but in the meantime add a conditional define as above.
      
      Fixes: 7c8dce4b ("bpftool: Make skeleton C code compilable with C++ compiler")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/6fc1dd28b8bda49e51e4f610bdc9d22f4455632d.1722244708.git.tony.ambardar@gmail.com
      aa95073f
    • Tony Ambardar's avatar
      selftests/bpf: Fix error compiling test_lru_map.c · cacf2a5a
      Tony Ambardar authored
      Although the post-increment in macro 'CPU_SET(next++, &cpuset)' seems safe,
      the sequencing can raise compile errors, so move the increment outside the
      macro. This avoids an error seen using gcc 12.3.0 for mips64el/musl-libc:
      
        In file included from test_lru_map.c:11:
        test_lru_map.c: In function 'sched_next_online':
        test_lru_map.c:129:29: error: operation on 'next' may be undefined [-Werror=sequence-point]
          129 |                 CPU_SET(next++, &cpuset);
              |                             ^
        cc1: all warnings being treated as errors
      
      Fixes: 3fbfadce ("bpf: Fix test_lru_sanity5() in test_lru_map.c")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/22993dfb11ccf27925a626b32672fd3324cb76c4.1722244708.git.tony.ambardar@gmail.com
      cacf2a5a
    • Tony Ambardar's avatar
      selftests/bpf: Fix arg parsing in veristat, test_progs · 03bfcda1
      Tony Ambardar authored
      Current code parses arguments with strtok_r() using a construct like
      
          char *state = NULL;
          while ((next = strtok_r(state ? NULL : input, ",", &state))) {
              ...
          }
      
      where logic assumes the 'state' var can distinguish between first and
      subsequent strtok_r() calls, and adjusts parameters accordingly. However,
      'state' is strictly internal context for strtok_r() and no such assumptions
      are supported in the man page. Moreover, the exact behaviour of 'state'
      depends on the libc implementation, making the above code fragile.
      
      Indeed, invoking "./test_progs -t <test_name>" on mips64el/musl will hang,
      with the above code in an infinite loop.
      
      Similarly, we see strange behaviour running 'veristat' on mips64el/musl:
      
          $ ./veristat -e file,prog,verdict,insns -C two-ok add-failure
          Can't specify more than 9 stats
      
      Rewrite code using a counter to distinguish between strtok_r() calls.
      
      Fixes: 61ddff37 ("selftests/bpf: Improve by-name subtest selection logic in prog_tests")
      Fixes: 394169b0 ("selftests/bpf: add comparison mode to veristat")
      Fixes: c8bc5e05 ("selftests/bpf: Add veristat tool for mass-verifying BPF object files")
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/392d8bf5559f85fa37926c1494e62312ef252c3d.1722244708.git.tony.ambardar@gmail.com
      03bfcda1
    • Tony Ambardar's avatar
      selftests/bpf: Use portable POSIX basename() · c0247800
      Tony Ambardar authored
      Use the POSIX version of basename() to allow compilation against non-gnu
      libc (e.g. musl). Include <libgen.h> ahead of <string.h> to enable using
      functions from the latter while preferring POSIX over GNU basename().
      
      In veristat.c, rely on strdupa() to avoid basename() altering the passed
      "const char" argument. This is not needed in xskxceiver.c since the arg
      is mutable and the program exits immediately after usage.
      Signed-off-by: default avatarTony Ambardar <tony.ambardar@gmail.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Link: https://lore.kernel.org/bpf/0fd3c9f3c605e6cba33504213c9df287817ade04.1722244708.git.tony.ambardar@gmail.com
      c0247800
    • Zhu Jun's avatar
      tools/bpf: Fix the wrong format specifier · 781f0bbb
      Zhu Jun authored
      The format specifier of "unsigned int" in printf() should be "%u", not
      "%d".
      Signed-off-by: default avatarZhu Jun <zhujun2@cmss.chinamobile.com>
      Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
      Acked-by: default avatarQuentin Monnet <qmo@kernel.org>
      Link: https://lore.kernel.org/bpf/20240724111120.11625-1-zhujun2@cmss.chinamobile.com
      781f0bbb
  2. 29 Jul, 2024 31 commits