/
phprus
/
github_dpdk
Обзор
Документация
Войти
/
phprus
/
github_dpdk
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
lib/bpf/bpf_load.c
292 строки
7 KB
Stephen Hemminger
bpf: silence noisy message
11 июл 2026, 15:56
11 июл 2026, 15:56
dc37792
Код
Авторство
О чём код?
/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2018 Intel Corporation */ #include <stdio.h> #include <string.h> #include <errno.h> #include <stdint.h> #include <eal_export.h> #include <rte_log.h> #include <rte_errno.h> #include "bpf_impl.h" static struct rte_bpf * bpf_load(const struct rte_bpf_prm_ex *prm) { uint8_t *buf; struct rte_bpf *bpf; size_t sz, bsz, insz, xsz; xsz = prm->nb_xsym * sizeof(prm->xsym[0]); insz = prm->raw.nb_ins * sizeof(prm->raw.ins[0]); bsz = sizeof(bpf[0]); sz = insz + xsz + bsz; buf = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (buf == MAP_FAILED) return NULL; bpf = (void *)buf; bpf->sz = sz; memcpy(&bpf->prm, prm, sizeof(bpf->prm)); if (xsz > 0) memcpy(buf + bsz, prm->xsym, xsz); memcpy(buf + bsz + xsz, prm->raw.ins, insz); bpf->prm.xsym = (void *)(buf + bsz); bpf->prm.raw.ins = (void *)(buf + bsz + xsz); return bpf; } /* * Check that user provided external symbol. */ static int bpf_check_xsym(const struct rte_bpf_xsym *xsym) { uint32_t i; if (xsym->name == NULL) return -EINVAL; if (xsym->type == RTE_BPF_XTYPE_VAR) { if (xsym->var.desc.type == RTE_BPF_ARG_UNDEF) return -EINVAL; } else if (xsym->type == RTE_BPF_XTYPE_FUNC) { if (xsym->func.nb_args > EBPF_FUNC_MAX_ARGS) return -EINVAL; /* check function arguments */ for (i = 0; i != xsym->func.nb_args; i++) { if (xsym->func.args[i].type == RTE_BPF_ARG_UNDEF) return -EINVAL; } /* check return value info */ if (xsym->func.ret.type != RTE_BPF_ARG_UNDEF && xsym->func.ret.size == 0) return -EINVAL; } else return -EINVAL; return 0; } static int bpf_check_xsyms(const struct rte_bpf_xsym *xsym, uint32_t nb_xsym) { int32_t rc; uint32_t i; if (nb_xsym != 0 && xsym == NULL) return -EINVAL; rc = 0; for (i = 0; i != nb_xsym && rc == 0; i++) rc = bpf_check_xsym(xsym + i); if (rc != 0) { RTE_BPF_LOG_FUNC_LINE(ERR, "%d-th xsym is invalid", i); return rc; } return 0; } static int bpf_load_raw(struct __rte_bpf_load *load) { const struct rte_bpf_prm_ex *const prm = &load->prm; struct rte_bpf *bpf; int32_t rc; RTE_ASSERT(prm->origin == RTE_BPF_ORIGIN_RAW); if (prm->raw.ins == NULL || prm->raw.nb_ins == 0) return -EINVAL; bpf = bpf_load(prm); if (bpf == NULL) return -ENOMEM; rc = __rte_bpf_validate(&load->prm, &bpf->stack_sz); if (rc == 0) { __rte_bpf_jit(bpf); if (mprotect(bpf, bpf->sz, PROT_READ) != 0) rc = -ENOMEM; } if (rc != 0) { rte_bpf_destroy(bpf); return rc; } load->bpf = bpf; return 0; } RTE_EXPORT_SYMBOL(rte_bpf_load) struct rte_bpf * rte_bpf_load(const struct rte_bpf_prm *prm) { if (prm == NULL) { rte_errno = EINVAL; return NULL; } return rte_bpf_load_ex(&(struct rte_bpf_prm_ex){ .sz = sizeof(struct rte_bpf_prm_ex), .origin = RTE_BPF_ORIGIN_RAW, .raw.ins = prm->ins, .raw.nb_ins = prm->nb_ins, .xsym = prm->xsym, .nb_xsym = prm->nb_xsym, .prog_arg[0] = prm->prog_arg, .nb_prog_arg = 1, }); } RTE_EXPORT_SYMBOL(rte_bpf_elf_load) struct rte_bpf * rte_bpf_elf_load(const struct rte_bpf_prm *prm, const char *fname, const char *sname) { if (prm == NULL) { rte_errno = EINVAL; return NULL; } return rte_bpf_load_ex(&(struct rte_bpf_prm_ex){ .sz = sizeof(struct rte_bpf_prm_ex), .origin = RTE_BPF_ORIGIN_ELF_FILE, .elf_file.path = fname, .elf_file.section = sname, .xsym = prm->xsym, .nb_xsym = prm->nb_xsym, .prog_arg[0] = prm->prog_arg, .nb_prog_arg = 1, }); } /* * Check extensible opts for invalid size or non-zero unsupported members. * * This code provides forward compatibility with applications compiled against * newer version of this library. `opts_sz` is the size of struct `opts` in the * version used for compiling the application, read from the member `sz`; * `type_sz` is the size of the same struct in the version used for compiling * the library. * * If new fields were added to the struct in the application version, `opts_sz` * will be greater than `type_sz`. In this case we are making sure all bytes we * don't know how to interpret are zeroes, that is any new features that are * there are not being used. * * This function can be used to check any struct following this convention. */ static bool opts_valid(const void *opts, size_t opts_sz, size_t type_sz) { if (opts == NULL) return true; if (opts_sz < sizeof(opts_sz)) /* Size of the struct is too small even for sz member. */ return false; /* Verify that all extra bytes are zeroed. */ for (size_t offset = type_sz; offset < opts_sz; ++offset) if (((const char *)opts)[offset] != 0) return false; return true; } static int load_try(struct __rte_bpf_load *load, const struct rte_bpf_prm_ex *app_prm) { int rc; if (app_prm == NULL || !opts_valid(app_prm, app_prm->sz, sizeof(load->prm))) return -EINVAL; /* * Convert extensible prm of application size to the size known to us. * * This code provides compatibility with applications compiled against * different version of this library. `app_prm->sz` is the size of * struct `rte_bpf_prm_ex` in the version used for compiling the * application; `sizeof(load->prm)` is the size of the same struct in * the version used for compiling the library. * * We are copying only the fields known to the application and leave * the rest filled with zeroes. Any features not known to the * application will have backward-compatible default behaviour. */ memcpy(&load->prm, app_prm, RTE_MIN(app_prm->sz, sizeof(load->prm))); load->prm.sz = sizeof(load->prm); rc = bpf_check_xsyms(load->prm.xsym, load->prm.nb_xsym); /* Convert prm origin to raw unless it already is. */ 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); break; case RTE_BPF_ORIGIN_ELF_MEMORY: rc = rc < 0 ? rc : __rte_bpf_load_elf_memory(load); rc = rc < 0 ? rc : __rte_bpf_load_elf_code(load); break; default: rc = rc < 0 ? rc : -EINVAL; } /* Now that it is raw load it as such. */ rc = rc < 0 ? rc : bpf_load_raw(load); 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.07) struct rte_bpf * rte_bpf_load_ex(const struct rte_bpf_prm_ex *prm) { struct __rte_bpf_load load = { .elf_fd = -1 }; const int rc = load_try(&load, prm); load_cleanup(&load); RTE_ASSERT((rc < 0) == (load.bpf == NULL)); if (rc < 0) { RTE_BPF_LOG_FUNC_LINE(ERR, "failed, error code: %d", -rc); rte_errno = -rc; return NULL; } RTE_BPF_LOG_FUNC_LINE(DEBUG, "successfully creates %p(jit={.func=%p,.sz=%zu});", load.bpf, load.bpf->jit.raw, load.bpf->jit.sz); return load.bpf; }