On Mon, 18 May 2026 09:49:02 +0100
Marat Khalili <[email protected]> wrote:

> Introduce new BPF load parameters struct rte_bpf_prm_ex that can be
> extended without breaking backward or forward compatibility. Introduce
> new function rte_bpf_load_ex consolidating in one code path loading from
> both ELF file and raw memory image, with possibility to add more options
> in the future.
> 
> Some changes in code layout and sequence:
> * Both old APIs now only forwarding calls to a new single entry point.
> * There is now a centralized cleanup point for all temporary resources
>   created during the load process.
> * External symbols (xsyms) are now checked for validity just after the
>   load started, not after they were already used for relocation.
> * File bpf_load_elf.c now only handles opening ELF file and providing
>   patched instruction array to the load process. These are left as two
>   separate functions to support other ELF sources like memory image in
>   the future.
> * Function stubs for the case libelf is not available are moved to
>   bpf_load_elf.c to make keeping track of them easier (forgetting to
>   update stubs is a common problem).
> 
> Signed-off-by: Marat Khalili <[email protected]>
> Acked-by: Konstantin Ananyev <[email protected]>
> ---Review of bundle-1895: bpf load (PATCH v3 01..10/10)

Lots of AI review on this (with Claude Opus 4.7)

====================================================

Patches 01, 06, 09, and 10 had no findings and are omitted from this
review.


PATCH v3 02/10 -- bpf: introduce extensible load API
----------------------------------------------------

Errors:

* lib/bpf/bpf_load.c, rte_bpf_load() and rte_bpf_elf_load() wrappers:
  These now unconditionally dereference `prm` when constructing the
  compound literal passed to rte_bpf_load_ex():

      return rte_bpf_load_ex(&(struct rte_bpf_prm_ex){
          ...
          .raw.ins = prm->ins,           /* NULL deref if prm == NULL */
          .raw.nb_ins = prm->nb_ins,
          .xsym = prm->xsym,
          .nb_xsym = prm->nb_xsym,
          .prog_arg = prm->prog_arg,
      });

  Pre-patch both functions explicitly checked `prm == NULL` and
  returned NULL with rte_errno = EINVAL. The NULL check inside
  load_try() does not help: NULL is dereferenced before
  rte_bpf_load_ex() is even called. Add explicit
  `if (prm == NULL) { rte_errno = EINVAL; return NULL; }` guards at
  the top of both wrappers.

Info:

* lib/bpf/bpf_load_elf.c: the success log
  "successfully creates %p(jit={.func=%p,.sz=%zu})" and the error log
  in rte_bpf_elf_load() are removed silently. If intentional, mention
  in the commit message.


PATCH v3 03/10 -- bpf: support up to 5 arguments
------------------------------------------------

Warnings:

* lib/bpf/bpf_exec.c, rte_bpf_exec_burst(), exec_jit_burst_ex(), and
  rte_bpf_exec_burst_ex(): these return `uint32_t` but the patch
  introduces `return -EINVAL` on error:

      if (bpf->prm.nb_prog_arg != 1)
          /* Use rte_bpf_exec_burst_ex with this program. */
          return -EINVAL;

  -22 reinterpreted as uint32_t is 0xFFFFFFEA, which the caller cannot
  distinguish from a valid "number of successfully processed inputs"
  result. The doxygen for rte_bpf_exec_burst_ex does not mention error
  returns. Either change the return type, document the encoding (e.g.
  any value > num indicates an error), or return 0 on these paths.


PATCH v3 04/10 -- bpf: add cBPF origin to rte_bpf_load_ex
---------------------------------------------------------

Info:

* lib/bpf/bpf_convert.c: the no-libpcap stub for rte_bpf_convert()
  loses its `if (prog == NULL) return EINVAL` check when moved out of
  bpf_stub.c. Previously rte_bpf_convert(NULL) returned EINVAL; now it
  returns ENOTSUP. Both produce NULL so pointer-checking callers are
  unaffected, but rte_errno semantics changed. Worth a mention or a
  restore for symmetry with the libpcap-enabled path.


PATCH v3 05/10 -- bpf: support rte_bpf_prm_ex with port callbacks
-----------------------------------------------------------------

Errors:

* lib/bpf/rte_bpf_ethdev.h: the doxygen comments for the two new
  functions are swapped:

      /**
       * Install callback to execute specified BPF program on given
       * TX port/queue.
       * ...
       * @param queue
       *   The identifier of the TX queue on the given port
       */
      __rte_experimental
      int
      rte_bpf_eth_rx_install(...);

      /**
       * Install callback to execute specified BPF program on given
       * RX port/queue.
       * ...
       * @param queue
       *   The identifier of the RX queue on the given port
       */
      __rte_experimental
      int
      rte_bpf_eth_tx_install(...);

  Swap the two doc blocks.


PATCH v3 07/10 -- test/bpf: test loading cBPF directly
------------------------------------------------------

Info:

* app/test/test_bpf.c, test_bpf_filter(): the failure path previously
  invoked test_bpf_dump(&fcode, prm) when load failed, useful for
  diagnosing converter regressions. The refactor drops this. Consider
  preserving the dump in the failure branch (or moving it into
  load_cbpf_program_convert on its NULL return).


PATCH v3 08/10 -- test/bpf: test loading ELF file from memory
-------------------------------------------------------------

Errors:

* app/test/test_bpf.c, bpf_rx_test(): when rte_bpf_eth_rx_install()
  fails, the loaded bpf program is leaked:

      ret = rte_bpf_eth_rx_install(port, 0, bpf, flags);
      if (ret != 0) {
          printf(...);
          return ret;            /* no rte_bpf_destroy(bpf) */
      }

  bpf_tx_test() in the same patch correctly calls rte_bpf_destroy(bpf)
  on the equivalent error path. Per the patch 05 contract, ownership
  transfers to the library only on successful install. Add
  `rte_bpf_destroy(bpf);` before the return.

Reply via email to