bpf: add BPF loading and execution framework
[dpdk.git] / lib / librte_bpf / bpf_load.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <stdint.h>
10 #include <unistd.h>
11 #include <inttypes.h>
12
13 #include <rte_common.h>
14 #include <rte_log.h>
15 #include <rte_debug.h>
16 #include <rte_memory.h>
17 #include <rte_eal.h>
18 #include <rte_byteorder.h>
19 #include <rte_errno.h>
20
21 #include "bpf_impl.h"
22
23 static struct rte_bpf *
24 bpf_load(const struct rte_bpf_prm *prm)
25 {
26         uint8_t *buf;
27         struct rte_bpf *bpf;
28         size_t sz, bsz, insz, xsz;
29
30         xsz =  prm->nb_xsym * sizeof(prm->xsym[0]);
31         insz = prm->nb_ins * sizeof(prm->ins[0]);
32         bsz = sizeof(bpf[0]);
33         sz = insz + xsz + bsz;
34
35         buf = mmap(NULL, sz, PROT_READ | PROT_WRITE,
36                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
37         if (buf == MAP_FAILED)
38                 return NULL;
39
40         bpf = (void *)buf;
41         bpf->sz = sz;
42
43         memcpy(&bpf->prm, prm, sizeof(bpf->prm));
44
45         memcpy(buf + bsz, prm->xsym, xsz);
46         memcpy(buf + bsz + xsz, prm->ins, insz);
47
48         bpf->prm.xsym = (void *)(buf + bsz);
49         bpf->prm.ins = (void *)(buf + bsz + xsz);
50
51         return bpf;
52 }
53
54 __rte_experimental struct rte_bpf *
55 rte_bpf_load(const struct rte_bpf_prm *prm)
56 {
57         struct rte_bpf *bpf;
58         int32_t rc;
59
60         if (prm == NULL || prm->ins == NULL) {
61                 rte_errno = EINVAL;
62                 return NULL;
63         }
64
65         bpf = bpf_load(prm);
66         if (bpf == NULL) {
67                 rte_errno = ENOMEM;
68                 return NULL;
69         }
70
71         rc = bpf_validate(bpf);
72         if (rc == 0) {
73                 bpf_jit(bpf);
74                 if (mprotect(bpf, bpf->sz, PROT_READ) != 0)
75                         rc = -ENOMEM;
76         }
77
78         if (rc != 0) {
79                 rte_bpf_destroy(bpf);
80                 rte_errno = -rc;
81                 return NULL;
82         }
83
84         return bpf;
85 }