From: Andrew Melnychenko <andrew@daynix.com>
To: jasowang@redhat.com, mst@redhat.com
Cc: yan@daynix.com, yuri.benditovich@daynix.com,
Andrew <andrew@daynix.com>,
qemu-devel@nongnu.org
Subject: [RFC PATCH 2/6] ebpf: Added basic eBPF API.
Date: Mon, 2 Nov 2020 20:51:12 +0200 [thread overview]
Message-ID: <20201102185115.7425-3-andrew@daynix.com> (raw)
In-Reply-To: <20201102185115.7425-1-andrew@daynix.com>
From: Andrew <andrew@daynix.com>
Added basic functions for creating eBPF maps and loading programs.
Also added helper function to 'fix' eBPF map descriptors in programs.
During runtime, different values of eBPF map file descriptors created,
and it required to place them into eBPF instructions for proper work.
It's similar to ELF's relocation table section routine.
Signed-off-by: Yuri Benditovich <yuri.benditovich@daynix.com>
Signed-off-by: Andrew Melnychenko <andrew@daynix.com>
---
ebpf/ebpf.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++
ebpf/ebpf.h | 35 +++++++++++++++
ebpf/trace-events | 4 ++
ebpf/trace.h | 2 +
4 files changed, 148 insertions(+)
create mode 100644 ebpf/ebpf.c
create mode 100644 ebpf/ebpf.h
create mode 100644 ebpf/trace-events
create mode 100644 ebpf/trace.h
diff --git a/ebpf/ebpf.c b/ebpf/ebpf.c
new file mode 100644
index 0000000000..cec35a484c
--- /dev/null
+++ b/ebpf/ebpf.c
@@ -0,0 +1,107 @@
+#include "ebpf/ebpf.h"
+#include <sys/syscall.h>
+#include "trace.h"
+
+#define ptr_to_u64(x) ((uint64_t)(uintptr_t)x)
+
+static inline int ebpf(enum bpf_cmd cmd, union bpf_attr *attr,
+ unsigned int size)
+{
+ int ret = syscall(__NR_bpf, cmd, attr, size);
+ if (ret < 0) {
+ trace_ebpf_error("eBPF syscall error", strerror(errno));
+ }
+
+ return ret;
+}
+
+int bpf_create_map(enum bpf_map_type map_type,
+ unsigned int key_size,
+ unsigned int value_size,
+ unsigned int max_entries)
+{
+ union bpf_attr attr = {
+ .map_type = map_type,
+ .key_size = key_size,
+ .value_size = value_size,
+ .max_entries = max_entries
+ };
+
+ return ebpf(BPF_MAP_CREATE, &attr, sizeof(attr));
+}
+
+int bpf_lookup_elem(int fd, const void *key, void *value)
+{
+ union bpf_attr attr = {
+ .map_fd = (uint32_t)fd,
+ .key = ptr_to_u64(key),
+ .value = ptr_to_u64(value),
+ };
+
+ return ebpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_update_elem(int fd, const void *key, const void *value,
+ uint64_t flags)
+{
+ union bpf_attr attr = {
+ .map_fd = (uint32_t)fd,
+ .key = ptr_to_u64(key),
+ .value = ptr_to_u64(value),
+ .flags = flags,
+ };
+
+ return ebpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
+}
+
+int bpf_delete_elem(int fd, const void *key)
+{
+ union bpf_attr attr = {
+ .map_fd = (uint32_t)fd,
+ .key = ptr_to_u64(key),
+ };
+
+ return ebpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+}
+
+#define BPF_LOG_BUF_SIZE (UINT32_MAX >> 8)
+static char bpf_log_buf[BPF_LOG_BUF_SIZE] = {};
+
+int bpf_prog_load(enum bpf_prog_type type,
+ const struct bpf_insn *insns, int insn_cnt,
+ const char *license)
+{
+ int ret = 0;
+ union bpf_attr attr = {};
+ attr.prog_type = type;
+ attr.insns = ptr_to_u64(insns);
+ attr.insn_cnt = (uint32_t)insn_cnt;
+ attr.license = ptr_to_u64(license);
+ attr.log_buf = ptr_to_u64(bpf_log_buf);
+ attr.log_size = BPF_LOG_BUF_SIZE;
+ attr.log_level = 1;
+
+ ret = ebpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+ if (ret < 0) {
+ trace_ebpf_error("eBPF program load error:", bpf_log_buf);
+ }
+
+ return ret;
+}
+
+unsigned int bpf_fixup_mapfd(struct fixup_mapfd_t *table,
+ size_t table_size, struct bpf_insn *insn,
+ size_t insn_len, const char *map_name, int fd) {
+ unsigned int ret = 0;
+ int i = 0;
+
+ for (; i < table_size; ++i) {
+ if (strcmp(table[i].map_name, map_name) == 0) {
+ insn[table[i].instruction_num].src_reg = 1;
+ insn[table[i].instruction_num].imm = fd;
+ ++ret;
+ }
+ }
+
+ return ret;
+}
diff --git a/ebpf/ebpf.h b/ebpf/ebpf.h
new file mode 100644
index 0000000000..511ad0a06f
--- /dev/null
+++ b/ebpf/ebpf.h
@@ -0,0 +1,35 @@
+#ifndef QEMU_EBPF_H
+#define QEMU_EBPF_H
+
+#include "qemu/osdep.h"
+
+#ifdef CONFIG_EBPF
+#include <linux/bpf.h>
+
+int bpf_create_map(enum bpf_map_type map_type,
+ unsigned int key_size,
+ unsigned int value_size,
+ unsigned int max_entries);
+
+int bpf_lookup_elem(int fd, const void *key, void *value);
+
+int bpf_update_elem(int fd, const void *key, const void *value,
+ uint64_t flags);
+
+int bpf_delete_elem(int fd, const void *key);
+
+int bpf_prog_load(enum bpf_prog_type type,
+ const struct bpf_insn *insns, int insn_cnt,
+ const char *license);
+
+struct fixup_mapfd_t {
+ const char *map_name;
+ size_t instruction_num;
+};
+
+unsigned int bpf_fixup_mapfd(struct fixup_mapfd_t *table,
+ size_t table_size, struct bpf_insn *insn,
+ size_t insn_len, const char *map_name, int fd);
+
+#endif /* CONFIG_EBPF */
+#endif /* QEMU_EBPF_H */
diff --git a/ebpf/trace-events b/ebpf/trace-events
new file mode 100644
index 0000000000..3c189516e3
--- /dev/null
+++ b/ebpf/trace-events
@@ -0,0 +1,4 @@
+# See docs/devel/tracing.txt for syntax documentation.
+
+# ebpf.c
+ebpf_error(const char *s1, const char *s2) "error in %s: %s"
diff --git a/ebpf/trace.h b/ebpf/trace.h
new file mode 100644
index 0000000000..ad570e6691
--- /dev/null
+++ b/ebpf/trace.h
@@ -0,0 +1,2 @@
+#include "trace/trace-ebpf.h"
+
--
2.28.0
next prev parent reply other threads:[~2020-11-02 18:26 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-02 18:51 [RFC PATCH 0/6] eBPF RSS support for virtio-net Andrew Melnychenko
2020-11-02 18:51 ` [RFC PATCH 1/6] net: Added SetSteeringEBPF method for NetClientState Andrew Melnychenko
2020-11-04 2:49 ` Jason Wang
2020-11-04 9:34 ` Yuri Benditovich
2020-11-02 18:51 ` Andrew Melnychenko [this message]
2020-11-02 18:51 ` [RFC PATCH 3/6] ebpf: Added eBPF RSS program Andrew Melnychenko
2020-11-03 13:07 ` Daniel P. Berrangé
2020-11-02 18:51 ` [RFC PATCH 4/6] ebpf: Added eBPF RSS loader Andrew Melnychenko
2020-11-02 18:51 ` [RFC PATCH 5/6] virtio-net: Added eBPF RSS to virtio-net Andrew Melnychenko
2020-11-04 3:09 ` Jason Wang
2020-11-04 11:07 ` Yuri Benditovich
2020-11-04 11:13 ` Daniel P. Berrangé
2020-11-04 15:51 ` Yuri Benditovich
2020-11-05 3:29 ` Jason Wang
2020-11-02 18:51 ` [RFC PATCH 6/6] docs: Added eBPF documentation Andrew Melnychenko
2020-11-04 3:15 ` Jason Wang
2020-11-05 3:56 ` Jason Wang
2020-11-05 9:40 ` Yuri Benditovich
2020-11-03 9:02 ` [RFC PATCH 0/6] eBPF RSS support for virtio-net Jason Wang
2020-11-03 10:32 ` Yuri Benditovich
2020-11-03 11:56 ` Daniel P. Berrangé
2020-11-04 2:15 ` Jason Wang
2020-11-04 2:07 ` Jason Wang
2020-11-04 9:31 ` Daniel P. Berrangé
2020-11-05 3:46 ` Jason Wang
2020-11-05 3:52 ` Jason Wang
2020-11-05 9:11 ` Yuri Benditovich
2020-11-05 10:01 ` Daniel P. Berrangé
2020-11-05 13:19 ` Daniel P. Berrangé
2020-11-05 15:13 ` Yuri Benditovich
2020-11-09 2:13 ` Jason Wang
2020-11-09 13:33 ` Yuri Benditovich
2020-11-10 2:23 ` Jason Wang
2020-11-10 8:00 ` Yuri Benditovich
2020-11-04 11:49 ` Yuri Benditovich
2020-11-04 12:04 ` Daniel P. Berrangé
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201102185115.7425-3-andrew@daynix.com \
--to=andrew@daynix.com \
--cc=jasowang@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=yan@daynix.com \
--cc=yuri.benditovich@daynix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).