summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Ananyev <konstantin.ananyev@intel.com>2019-05-17 15:09:42 +0100
committerThomas Monjalon <thomas@monjalon.net>2019-06-05 18:34:56 +0200
commit64ac6feb8291eb0fe74cf965dd3890625f8f3171 (patch)
treef318a08dc73c7151d63f0dc50e72535df9b02565
parent9bd75b508e11fcb38589c90ae435734d6343ad78 (diff)
downloaddpdk-next-eventdev-64ac6feb8291eb0fe74cf965dd3890625f8f3171.zip
dpdk-next-eventdev-64ac6feb8291eb0fe74cf965dd3890625f8f3171.tar.gz
dpdk-next-eventdev-64ac6feb8291eb0fe74cf965dd3890625f8f3171.tar.xz
bpf: fix pseudo calls for program loaded from ELF
clang 6.0 and onwards, for the external function call generates BPF_PSEUDO_CALL instruction: call pseudo +-off -> call another bpf function. More details about that change: https://lwn.net/Articles/741773/ DPDK BPF implementation right now doesn't support multiple BPF functions per module. To overcome that problem, and preserve existing functionality (ability to call allowed by user external functions), bpf_elf_load() clears EBPF_PSEUDO_CALL value. For details how to reproduce the issue: https://bugs.dpdk.org/show_bug.cgi?id=259 Fixes: 5dba93ae5f2d ("bpf: add ability to load eBPF program from ELF object file") Cc: stable@dpdk.org Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
-rw-r--r--lib/librte_bpf/bpf_def.h8
-rw-r--r--lib/librte_bpf/bpf_load_elf.c15
-rw-r--r--lib/librte_bpf/rte_bpf.h3
3 files changed, 24 insertions, 2 deletions
diff --git a/lib/librte_bpf/bpf_def.h b/lib/librte_bpf/bpf_def.h
index c10f3ae..d399929 100644
--- a/lib/librte_bpf/bpf_def.h
+++ b/lib/librte_bpf/bpf_def.h
@@ -121,6 +121,14 @@ enum {
};
/*
+ * When EBPF_CALL instruction has src_reg == EBPF_PSEUDO_CALL,
+ * it should be treated as pseudo-call instruction, where
+ * imm value contains pc-relative offset to another EBPF function.
+ * Right now DPDK EBPF library doesn't support it.
+ */
+#define EBPF_PSEUDO_CALL EBPF_REG_1
+
+/*
* eBPF instruction format
*/
struct ebpf_insn {
diff --git a/lib/librte_bpf/bpf_load_elf.c b/lib/librte_bpf/bpf_load_elf.c
index 96d3630..926317b 100644
--- a/lib/librte_bpf/bpf_load_elf.c
+++ b/lib/librte_bpf/bpf_load_elf.c
@@ -77,10 +77,21 @@ resolve_xsym(const char *sn, size_t ofs, struct ebpf_insn *ins, size_t ins_sz,
return -ENOENT;
/* for function we just need an index in our xsym table */
- if (type == RTE_BPF_XTYPE_FUNC)
+ if (type == RTE_BPF_XTYPE_FUNC) {
+
+ /* we don't support multiple functions per BPF module,
+ * so treat EBPF_PSEUDO_CALL to extrernal function
+ * as an ordinary EBPF_CALL.
+ */
+ if (ins[idx].src_reg == EBPF_PSEUDO_CALL) {
+ RTE_BPF_LOG(INFO, "%s(%u): "
+ "EBPF_PSEUDO_CALL to external function: %s\n",
+ __func__, idx, sn);
+ ins[idx].src_reg = EBPF_REG_0;
+ }
ins[idx].imm = fidx;
/* for variable we need to store its absolute address */
- else {
+ } else {
ins[idx].imm = (uintptr_t)prm->xsym[fidx].var.val;
ins[idx + 1].imm =
(uint64_t)(uintptr_t)prm->xsym[fidx].var.val >> 32;
diff --git a/lib/librte_bpf/rte_bpf.h b/lib/librte_bpf/rte_bpf.h
index ab92af8..c8b9601 100644
--- a/lib/librte_bpf/rte_bpf.h
+++ b/lib/librte_bpf/rte_bpf.h
@@ -134,6 +134,9 @@ rte_bpf_load(const struct rte_bpf_prm *prm);
/**
* Create a new eBPF execution context and load BPF code from given ELF
* file into it.
+ * Note that if the function will encounter EBPF_PSEUDO_CALL instruction
+ * that references external symbol, it will treat is as standard BPF_CALL
+ * to the external helper function.
*
* @param prm
* Parameters used to create and initialise the BPF execution context.