Add cBPF origin to rte_bpf_load_ex to allow loading PCAP filters and other cBPF code through the unified interface.
Signed-off-by: Marat Khalili <[email protected]> --- lib/bpf/bpf_convert.c | 79 +++++++++++++++++++++++++++++++++++++++++-- lib/bpf/bpf_impl.h | 11 ++++++ lib/bpf/bpf_load.c | 12 ++++++- lib/bpf/bpf_stub.c | 27 --------------- lib/bpf/meson.build | 11 +++--- lib/bpf/rte_bpf.h | 8 ++++- 6 files changed, 111 insertions(+), 37 deletions(-) delete mode 100644 lib/bpf/bpf_stub.c diff --git a/lib/bpf/bpf_convert.c b/lib/bpf/bpf_convert.c index 953ca80670c4..c997116c691f 100644 --- a/lib/bpf/bpf_convert.c +++ b/lib/bpf/bpf_convert.c @@ -9,6 +9,12 @@ * Copyright (c) 2011 - 2014 PLUMgrid, http://plumgrid.com */ +#include "bpf_impl.h" +#include <eal_export.h> +#include <rte_errno.h> + +#ifdef RTE_HAS_LIBPCAP + #include <assert.h> #include <errno.h> #include <stdbool.h> @@ -17,17 +23,14 @@ #include <stdlib.h> #include <string.h> -#include <eal_export.h> #include <rte_common.h> #include <rte_bpf.h> #include <rte_log.h> #include <rte_malloc.h> -#include <rte_errno.h> #include <pcap/pcap.h> #include <pcap/bpf.h> -#include "bpf_impl.h" #include "bpf_def.h" #ifndef BPF_MAXINSNS @@ -572,3 +575,73 @@ rte_bpf_convert(const struct bpf_program *prog) return prm; } + +void +__rte_bpf_convert_cleanup(struct __rte_bpf_load *load) +{ + free(load->ins); +} + +int __rte_bpf_convert(struct __rte_bpf_load *load) +{ + struct rte_bpf_prm_ex *const prm = &load->prm; + uint32_t nb_ins = 0; + int ret; + + RTE_ASSERT(prm->origin == RTE_BPF_ORIGIN_CBPF); + + if (prm->cbpf.ins == NULL || prm->cbpf.nb_ins == 0) + return -EINVAL; + + /* 1st pass: calculate the eBPF program length */ + ret = bpf_convert_filter(prm->cbpf.ins, prm->cbpf.nb_ins, NULL, &nb_ins); + if (ret < 0) { + RTE_BPF_LOG_FUNC_LINE(ERR, "cannot get eBPF length"); + return ret; + } + + RTE_ASSERT(load->ins == NULL); + load->ins = malloc(nb_ins * sizeof(load->ins[0])); + if (load->ins == NULL) + return -ENOMEM; + + /* 2nd pass: remap cBPF to eBPF instructions */ + ret = bpf_convert_filter(prm->cbpf.ins, prm->cbpf.nb_ins, load->ins, &nb_ins); + if (ret < 0) { + RTE_BPF_LOG_FUNC_LINE(ERR, "cannot convert cBPF to eBPF"); + return ret; + } + + prm->origin = RTE_BPF_ORIGIN_RAW; + prm->raw.ins = load->ins; + prm->raw.nb_ins = nb_ins; + + return 0; +} + +#else /* RTE_HAS_LIBPCAP */ + +RTE_EXPORT_SYMBOL(rte_bpf_convert) +struct rte_bpf_prm * +rte_bpf_convert(const struct bpf_program *prog) +{ + RTE_SET_USED(prog); + RTE_BPF_LOG_FUNC_LINE(ERR, "not supported, rebuild with libpcap installed"); + rte_errno = ENOTSUP; + return NULL; +} + +void +__rte_bpf_convert_cleanup(struct __rte_bpf_load *load) +{ + RTE_ASSERT(load->ins == NULL); +} + +int __rte_bpf_convert(struct __rte_bpf_load *load) +{ + RTE_SET_USED(load); + RTE_BPF_LOG_FUNC_LINE(ERR, "not supported, rebuild with libpcap installed"); + return -ENOTSUP; +} + +#endif /* RTE_HAS_LIBPCAP */ diff --git a/lib/bpf/bpf_impl.h b/lib/bpf/bpf_impl.h index 4a98b3373067..92d03583d977 100644 --- a/lib/bpf/bpf_impl.h +++ b/lib/bpf/bpf_impl.h @@ -21,6 +21,9 @@ struct rte_bpf { struct __rte_bpf_load { struct rte_bpf_prm_ex prm; + /* Conversion from cBPF. */ + struct ebpf_insn *ins; + /* Loading ELF and applying relocations. */ int elf_fd; /* ELF fd, must be negative (not zero) by default. */ void *elf; /* Using void to avoid dependency on libelf. */ @@ -34,6 +37,14 @@ struct __rte_bpf_load { * to avoid potential name conflict with other libraries. */ +/* Free temporary resources created by converting from cBPF to eBPF. */ +void +__rte_bpf_convert_cleanup(struct __rte_bpf_load *load); + +/* Convert program from cBPF to eBPF. */ +int +__rte_bpf_convert(struct __rte_bpf_load *load); + /* Free temporary resources created by opening ELF. */ void __rte_bpf_load_elf_cleanup(struct __rte_bpf_load *load); diff --git a/lib/bpf/bpf_load.c b/lib/bpf/bpf_load.c index c9cbaf6ded7e..c3c49ac49b1b 100644 --- a/lib/bpf/bpf_load.c +++ b/lib/bpf/bpf_load.c @@ -230,6 +230,9 @@ load_try(struct __rte_bpf_load *load, const struct rte_bpf_prm_ex *app_prm) switch (load->prm.origin) { case RTE_BPF_ORIGIN_RAW: break; + case RTE_BPF_ORIGIN_CBPF: + rc = rc < 0 ? rc : __rte_bpf_convert(load); + break; case RTE_BPF_ORIGIN_ELF_FILE: rc = rc < 0 ? rc : __rte_bpf_load_elf_file(load); rc = rc < 0 ? rc : __rte_bpf_load_elf_code(load); @@ -244,6 +247,13 @@ load_try(struct __rte_bpf_load *load, const struct rte_bpf_prm_ex *app_prm) return rc; } +static void +load_cleanup(struct __rte_bpf_load *load) +{ + __rte_bpf_convert_cleanup(load); + __rte_bpf_load_elf_cleanup(load); +} + RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_bpf_load_ex, 26.11) struct rte_bpf * rte_bpf_load_ex(const struct rte_bpf_prm_ex *prm) @@ -252,7 +262,7 @@ rte_bpf_load_ex(const struct rte_bpf_prm_ex *prm) const int rc = load_try(&load, prm); - __rte_bpf_load_elf_cleanup(&load); + load_cleanup(&load); RTE_ASSERT((rc < 0) == (load.bpf == NULL)); diff --git a/lib/bpf/bpf_stub.c b/lib/bpf/bpf_stub.c deleted file mode 100644 index 4c329832c264..000000000000 --- a/lib/bpf/bpf_stub.c +++ /dev/null @@ -1,27 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2018-2021 Intel Corporation - */ - -#include "bpf_impl.h" -#include <eal_export.h> -#include <rte_errno.h> - -/** - * Contains stubs for unimplemented public API functions - */ - -#ifndef RTE_HAS_LIBPCAP -RTE_EXPORT_SYMBOL(rte_bpf_convert) -struct rte_bpf_prm * -rte_bpf_convert(const struct bpf_program *prog) -{ - if (prog == NULL) { - rte_errno = EINVAL; - return NULL; - } - - RTE_BPF_LOG_FUNC_LINE(ERR, "not supported, rebuild with libpcap installed"); - rte_errno = ENOTSUP; - return NULL; -} -#endif diff --git a/lib/bpf/meson.build b/lib/bpf/meson.build index 4901b6ee1463..7e8a300e3f87 100644 --- a/lib/bpf/meson.build +++ b/lib/bpf/meson.build @@ -15,14 +15,16 @@ if arch_subdir == 'x86' and dpdk_conf.get('RTE_ARCH_32') subdir_done() endif -sources = files('bpf.c', +sources = files( + 'bpf.c', + 'bpf_convert.c', 'bpf_dump.c', 'bpf_exec.c', 'bpf_load.c', 'bpf_load_elf.c', 'bpf_pkt.c', - 'bpf_stub.c', - 'bpf_validate.c') + 'bpf_validate.c', +) if arch_subdir == 'x86' and dpdk_conf.get('RTE_ARCH_64') sources += files('bpf_jit_x86.c') @@ -45,8 +47,7 @@ else endif if dpdk_conf.has('RTE_HAS_LIBPCAP') - sources += files('bpf_convert.c') ext_deps += pcap_dep else - warning('libpcap is missing, rte_bpf_convert API will be disabled') + warning('libpcap is missing, cBPF API will be disabled') endif diff --git a/lib/bpf/rte_bpf.h b/lib/bpf/rte_bpf.h index 751b879bb7fd..dcb709352e17 100644 --- a/lib/bpf/rte_bpf.h +++ b/lib/bpf/rte_bpf.h @@ -95,10 +95,12 @@ struct rte_bpf_xsym { */ enum rte_bpf_origin { RTE_BPF_ORIGIN_RAW, /**< code loaded from raw array */ - RTE_BPF_ORIGIN_RESERVED, /**< reserved for cBPF */ + RTE_BPF_ORIGIN_CBPF, /**< code converted from cbpf */ RTE_BPF_ORIGIN_ELF_FILE, /**< code loaded from elf_file */ }; +struct bpf_insn; + /** * Input parameters for loading eBPF code, extensible version. * @@ -117,6 +119,10 @@ struct rte_bpf_prm_ex { const struct ebpf_insn *ins; /**< eBPF instructions */ uint32_t nb_ins; /**< number of instructions in ins */ } raw; + struct { + const struct bpf_insn *ins; /**< cBPF instructions */ + uint32_t nb_ins; /**< number of instructions in ins */ + } cbpf; struct { const char *path; /**< path to the ELF file */ const char *section; /**< ELF section with the code */ -- 2.43.0

