Skip to content

Commit 46627f4

Browse files
AndrewAtDaynixjasowang
authored andcommitted
ebpf: Added eBPF RSS loader.
Added function that loads RSS eBPF program. Added stub functions for RSS eBPF loader. Added meson and configuration options. By default, eBPF feature enabled if libbpf is present in the build system. libbpf checked in configuration shell script and meson script. Signed-off-by: Yuri Benditovich <[email protected]> Signed-off-by: Andrew Melnychenko <[email protected]> Signed-off-by: Jason Wang <[email protected]>
1 parent f3fa412 commit 46627f4

10 files changed

+718
-1
lines changed

configure

+7-1
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ vhost_vsock="$default_feature"
348348
vhost_user="no"
349349
vhost_user_blk_server="auto"
350350
vhost_user_fs="$default_feature"
351+
bpf="auto"
351352
kvm="auto"
352353
hax="auto"
353354
hvf="auto"
@@ -1240,6 +1241,10 @@ for opt do
12401241
;;
12411242
--enable-membarrier) membarrier="yes"
12421243
;;
1244+
--disable-bpf) bpf="disabled"
1245+
;;
1246+
--enable-bpf) bpf="enabled"
1247+
;;
12431248
--disable-blobs) blobs="false"
12441249
;;
12451250
--with-pkgversion=*) pkgversion="$optarg"
@@ -1878,6 +1883,7 @@ disabled with --disable-FEATURE, default is enabled if available
18781883
vhost-user vhost-user backend support
18791884
vhost-user-blk-server vhost-user-blk server support
18801885
vhost-vdpa vhost-vdpa kernel backend support
1886+
bpf BPF kernel support
18811887
spice spice
18821888
spice-protocol spice-protocol
18831889
rbd rados block device (rbd)
@@ -6476,7 +6482,7 @@ if test "$skip_meson" = no; then
64766482
-Dattr=$attr -Ddefault_devices=$default_devices \
64776483
-Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
64786484
-Dvhost_user_blk_server=$vhost_user_blk_server -Dmultiprocess=$multiprocess \
6479-
-Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi \
6485+
-Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi -Dbpf=$bpf\
64806486
$(if test "$default_features" = no; then echo "-Dauto_features=disabled"; fi) \
64816487
-Dtcg_interpreter=$tcg_interpreter \
64826488
$cross_arg \

ebpf/ebpf_rss-stub.c

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* eBPF RSS stub file
3+
*
4+
* Developed by Daynix Computing LTD (http://www.daynix.com)
5+
*
6+
* Authors:
7+
* Yuri Benditovich <[email protected]>
8+
*
9+
* This work is licensed under the terms of the GNU GPL, version 2. See
10+
* the COPYING file in the top-level directory.
11+
*/
12+
13+
#include "qemu/osdep.h"
14+
#include "ebpf/ebpf_rss.h"
15+
16+
void ebpf_rss_init(struct EBPFRSSContext *ctx)
17+
{
18+
19+
}
20+
21+
bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx)
22+
{
23+
return false;
24+
}
25+
26+
bool ebpf_rss_load(struct EBPFRSSContext *ctx)
27+
{
28+
return false;
29+
}
30+
31+
bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
32+
uint16_t *indirections_table, uint8_t *toeplitz_key)
33+
{
34+
return false;
35+
}
36+
37+
void ebpf_rss_unload(struct EBPFRSSContext *ctx)
38+
{
39+
40+
}

ebpf/ebpf_rss.c

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* eBPF RSS loader
3+
*
4+
* Developed by Daynix Computing LTD (http://www.daynix.com)
5+
*
6+
* Authors:
7+
* Andrew Melnychenko <[email protected]>
8+
* Yuri Benditovich <[email protected]>
9+
*
10+
* This work is licensed under the terms of the GNU GPL, version 2. See
11+
* the COPYING file in the top-level directory.
12+
*/
13+
14+
#include "qemu/osdep.h"
15+
#include "qemu/error-report.h"
16+
17+
#include <bpf/libbpf.h>
18+
#include <bpf/bpf.h>
19+
20+
#include "hw/virtio/virtio-net.h" /* VIRTIO_NET_RSS_MAX_TABLE_LEN */
21+
22+
#include "ebpf/ebpf_rss.h"
23+
#include "ebpf/rss.bpf.skeleton.h"
24+
#include "trace.h"
25+
26+
void ebpf_rss_init(struct EBPFRSSContext *ctx)
27+
{
28+
if (ctx != NULL) {
29+
ctx->obj = NULL;
30+
}
31+
}
32+
33+
bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx)
34+
{
35+
return ctx != NULL && ctx->obj != NULL;
36+
}
37+
38+
bool ebpf_rss_load(struct EBPFRSSContext *ctx)
39+
{
40+
struct rss_bpf *rss_bpf_ctx;
41+
42+
if (ctx == NULL) {
43+
return false;
44+
}
45+
46+
rss_bpf_ctx = rss_bpf__open();
47+
if (rss_bpf_ctx == NULL) {
48+
trace_ebpf_error("eBPF RSS", "can not open eBPF RSS object");
49+
goto error;
50+
}
51+
52+
bpf_program__set_socket_filter(rss_bpf_ctx->progs.tun_rss_steering_prog);
53+
54+
if (rss_bpf__load(rss_bpf_ctx)) {
55+
trace_ebpf_error("eBPF RSS", "can not load RSS program");
56+
goto error;
57+
}
58+
59+
ctx->obj = rss_bpf_ctx;
60+
ctx->program_fd = bpf_program__fd(
61+
rss_bpf_ctx->progs.tun_rss_steering_prog);
62+
ctx->map_configuration = bpf_map__fd(
63+
rss_bpf_ctx->maps.tap_rss_map_configurations);
64+
ctx->map_indirections_table = bpf_map__fd(
65+
rss_bpf_ctx->maps.tap_rss_map_indirection_table);
66+
ctx->map_toeplitz_key = bpf_map__fd(
67+
rss_bpf_ctx->maps.tap_rss_map_toeplitz_key);
68+
69+
return true;
70+
error:
71+
rss_bpf__destroy(rss_bpf_ctx);
72+
ctx->obj = NULL;
73+
74+
return false;
75+
}
76+
77+
static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx,
78+
struct EBPFRSSConfig *config)
79+
{
80+
uint32_t map_key = 0;
81+
82+
if (!ebpf_rss_is_loaded(ctx)) {
83+
return false;
84+
}
85+
if (bpf_map_update_elem(ctx->map_configuration,
86+
&map_key, config, 0) < 0) {
87+
return false;
88+
}
89+
return true;
90+
}
91+
92+
static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx,
93+
uint16_t *indirections_table,
94+
size_t len)
95+
{
96+
uint32_t i = 0;
97+
98+
if (!ebpf_rss_is_loaded(ctx) || indirections_table == NULL ||
99+
len > VIRTIO_NET_RSS_MAX_TABLE_LEN) {
100+
return false;
101+
}
102+
103+
for (; i < len; ++i) {
104+
if (bpf_map_update_elem(ctx->map_indirections_table, &i,
105+
indirections_table + i, 0) < 0) {
106+
return false;
107+
}
108+
}
109+
return true;
110+
}
111+
112+
static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx,
113+
uint8_t *toeplitz_key)
114+
{
115+
uint32_t map_key = 0;
116+
117+
/* prepare toeplitz key */
118+
uint8_t toe[VIRTIO_NET_RSS_MAX_KEY_SIZE] = {};
119+
120+
if (!ebpf_rss_is_loaded(ctx) || toeplitz_key == NULL) {
121+
return false;
122+
}
123+
memcpy(toe, toeplitz_key, VIRTIO_NET_RSS_MAX_KEY_SIZE);
124+
*(uint32_t *)toe = ntohl(*(uint32_t *)toe);
125+
126+
if (bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe,
127+
0) < 0) {
128+
return false;
129+
}
130+
return true;
131+
}
132+
133+
bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
134+
uint16_t *indirections_table, uint8_t *toeplitz_key)
135+
{
136+
if (!ebpf_rss_is_loaded(ctx) || config == NULL ||
137+
indirections_table == NULL || toeplitz_key == NULL) {
138+
return false;
139+
}
140+
141+
if (!ebpf_rss_set_config(ctx, config)) {
142+
return false;
143+
}
144+
145+
if (!ebpf_rss_set_indirections_table(ctx, indirections_table,
146+
config->indirections_len)) {
147+
return false;
148+
}
149+
150+
if (!ebpf_rss_set_toepliz_key(ctx, toeplitz_key)) {
151+
return false;
152+
}
153+
154+
return true;
155+
}
156+
157+
void ebpf_rss_unload(struct EBPFRSSContext *ctx)
158+
{
159+
if (!ebpf_rss_is_loaded(ctx)) {
160+
return;
161+
}
162+
163+
rss_bpf__destroy(ctx->obj);
164+
ctx->obj = NULL;
165+
}

ebpf/ebpf_rss.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* eBPF RSS header
3+
*
4+
* Developed by Daynix Computing LTD (http://www.daynix.com)
5+
*
6+
* Authors:
7+
* Andrew Melnychenko <[email protected]>
8+
* Yuri Benditovich <[email protected]>
9+
*
10+
* This work is licensed under the terms of the GNU GPL, version 2. See
11+
* the COPYING file in the top-level directory.
12+
*/
13+
14+
#ifndef QEMU_EBPF_RSS_H
15+
#define QEMU_EBPF_RSS_H
16+
17+
struct EBPFRSSContext {
18+
void *obj;
19+
int program_fd;
20+
int map_configuration;
21+
int map_toeplitz_key;
22+
int map_indirections_table;
23+
};
24+
25+
struct EBPFRSSConfig {
26+
uint8_t redirect;
27+
uint8_t populate_hash;
28+
uint32_t hash_types;
29+
uint16_t indirections_len;
30+
uint16_t default_queue;
31+
} __attribute__((packed));
32+
33+
void ebpf_rss_init(struct EBPFRSSContext *ctx);
34+
35+
bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx);
36+
37+
bool ebpf_rss_load(struct EBPFRSSContext *ctx);
38+
39+
bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
40+
uint16_t *indirections_table, uint8_t *toeplitz_key);
41+
42+
void ebpf_rss_unload(struct EBPFRSSContext *ctx);
43+
44+
#endif /* QEMU_EBPF_RSS_H */

ebpf/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
common_ss.add(when: libbpf, if_true: files('ebpf_rss.c'), if_false: files('ebpf_rss-stub.c'))

0 commit comments

Comments
 (0)