Skip to content

Commit

Permalink
ebpf: Added eBPF RSS loader.
Browse files Browse the repository at this point in the history
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 <yuri.benditovich@daynix.com>
Signed-off-by: Andrew Melnychenko <andrew@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
  • Loading branch information
AndrewAtDaynix authored and jasowang committed May 8, 2021
1 parent 403a407 commit 5d02a41
Show file tree
Hide file tree
Showing 10 changed files with 718 additions and 1 deletion.
8 changes: 7 additions & 1 deletion configure
Expand Up @@ -348,6 +348,7 @@ vhost_vsock="$default_feature"
vhost_user="no"
vhost_user_blk_server="auto"
vhost_user_fs="$default_feature"
bpf="auto"
kvm="auto"
hax="auto"
hvf="auto"
Expand Down Expand Up @@ -1228,6 +1229,10 @@ for opt do
;;
--enable-membarrier) membarrier="yes"
;;
--disable-bpf) bpf="disabled"
;;
--enable-bpf) bpf="enabled"
;;
--disable-blobs) blobs="false"
;;
--with-pkgversion=*) pkgversion="$optarg"
Expand Down Expand Up @@ -1865,6 +1870,7 @@ disabled with --disable-FEATURE, default is enabled if available
vhost-user vhost-user backend support
vhost-user-blk-server vhost-user-blk server support
vhost-vdpa vhost-vdpa kernel backend support
bpf BPF kernel support
spice spice
rbd rados block device (rbd)
libiscsi iscsi support
Expand Down Expand Up @@ -6423,7 +6429,7 @@ NINJA=$ninja $meson setup \
-Dattr=$attr -Ddefault_devices=$default_devices \
-Ddocs=$docs -Dsphinx_build=$sphinx_build -Dinstall_blobs=$blobs \
-Dvhost_user_blk_server=$vhost_user_blk_server -Dmultiprocess=$multiprocess \
-Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi \
-Dfuse=$fuse -Dfuse_lseek=$fuse_lseek -Dguest_agent_msi=$guest_agent_msi -Dbpf=$bpf\
$(if test "$default_features" = no; then echo "-Dauto_features=disabled"; fi) \
-Dtcg_interpreter=$tcg_interpreter \
$cross_arg \
Expand Down
40 changes: 40 additions & 0 deletions ebpf/ebpf_rss-stub.c
@@ -0,0 +1,40 @@
/*
* eBPF RSS stub file
*
* Developed by Daynix Computing LTD (http://www.daynix.com)
*
* Authors:
* Yuri Benditovich <yuri.benditovich@daynix.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/

#include "qemu/osdep.h"
#include "ebpf/ebpf_rss.h"

void ebpf_rss_init(struct EBPFRSSContext *ctx)
{

}

bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx)
{
return false;
}

bool ebpf_rss_load(struct EBPFRSSContext *ctx)
{
return false;
}

bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
uint16_t *indirections_table, uint8_t *toeplitz_key)
{
return false;
}

void ebpf_rss_unload(struct EBPFRSSContext *ctx)
{

}
165 changes: 165 additions & 0 deletions ebpf/ebpf_rss.c
@@ -0,0 +1,165 @@
/*
* eBPF RSS loader
*
* Developed by Daynix Computing LTD (http://www.daynix.com)
*
* Authors:
* Andrew Melnychenko <andrew@daynix.com>
* Yuri Benditovich <yuri.benditovich@daynix.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/

#include "qemu/osdep.h"
#include "qemu/error-report.h"

#include <bpf/libbpf.h>
#include <bpf/bpf.h>

#include "hw/virtio/virtio-net.h" /* VIRTIO_NET_RSS_MAX_TABLE_LEN */

#include "ebpf/ebpf_rss.h"
#include "ebpf/rss.bpf.skeleton.h"
#include "trace.h"

void ebpf_rss_init(struct EBPFRSSContext *ctx)
{
if (ctx != NULL) {
ctx->obj = NULL;
}
}

bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx)
{
return ctx != NULL && ctx->obj != NULL;
}

bool ebpf_rss_load(struct EBPFRSSContext *ctx)
{
struct rss_bpf *rss_bpf_ctx;

if (ctx == NULL) {
return false;
}

rss_bpf_ctx = rss_bpf__open();
if (rss_bpf_ctx == NULL) {
trace_ebpf_error("eBPF RSS", "can not open eBPF RSS object");
goto error;
}

bpf_program__set_socket_filter(rss_bpf_ctx->progs.tun_rss_steering_prog);

if (rss_bpf__load(rss_bpf_ctx)) {
trace_ebpf_error("eBPF RSS", "can not load RSS program");
goto error;
}

ctx->obj = rss_bpf_ctx;
ctx->program_fd = bpf_program__fd(
rss_bpf_ctx->progs.tun_rss_steering_prog);
ctx->map_configuration = bpf_map__fd(
rss_bpf_ctx->maps.tap_rss_map_configurations);
ctx->map_indirections_table = bpf_map__fd(
rss_bpf_ctx->maps.tap_rss_map_indirection_table);
ctx->map_toeplitz_key = bpf_map__fd(
rss_bpf_ctx->maps.tap_rss_map_toeplitz_key);

return true;
error:
rss_bpf__destroy(rss_bpf_ctx);
ctx->obj = NULL;

return false;
}

static bool ebpf_rss_set_config(struct EBPFRSSContext *ctx,
struct EBPFRSSConfig *config)
{
uint32_t map_key = 0;

if (!ebpf_rss_is_loaded(ctx)) {
return false;
}
if (bpf_map_update_elem(ctx->map_configuration,
&map_key, config, 0) < 0) {
return false;
}
return true;
}

static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext *ctx,
uint16_t *indirections_table,
size_t len)
{
uint32_t i = 0;

if (!ebpf_rss_is_loaded(ctx) || indirections_table == NULL ||
len > VIRTIO_NET_RSS_MAX_TABLE_LEN) {
return false;
}

for (; i < len; ++i) {
if (bpf_map_update_elem(ctx->map_indirections_table, &i,
indirections_table + i, 0) < 0) {
return false;
}
}
return true;
}

static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext *ctx,
uint8_t *toeplitz_key)
{
uint32_t map_key = 0;

/* prepare toeplitz key */
uint8_t toe[VIRTIO_NET_RSS_MAX_KEY_SIZE] = {};

if (!ebpf_rss_is_loaded(ctx) || toeplitz_key == NULL) {
return false;
}
memcpy(toe, toeplitz_key, VIRTIO_NET_RSS_MAX_KEY_SIZE);
*(uint32_t *)toe = ntohl(*(uint32_t *)toe);

if (bpf_map_update_elem(ctx->map_toeplitz_key, &map_key, toe,
0) < 0) {
return false;
}
return true;
}

bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
uint16_t *indirections_table, uint8_t *toeplitz_key)
{
if (!ebpf_rss_is_loaded(ctx) || config == NULL ||
indirections_table == NULL || toeplitz_key == NULL) {
return false;
}

if (!ebpf_rss_set_config(ctx, config)) {
return false;
}

if (!ebpf_rss_set_indirections_table(ctx, indirections_table,
config->indirections_len)) {
return false;
}

if (!ebpf_rss_set_toepliz_key(ctx, toeplitz_key)) {
return false;
}

return true;
}

void ebpf_rss_unload(struct EBPFRSSContext *ctx)
{
if (!ebpf_rss_is_loaded(ctx)) {
return;
}

rss_bpf__destroy(ctx->obj);
ctx->obj = NULL;
}
44 changes: 44 additions & 0 deletions ebpf/ebpf_rss.h
@@ -0,0 +1,44 @@
/*
* eBPF RSS header
*
* Developed by Daynix Computing LTD (http://www.daynix.com)
*
* Authors:
* Andrew Melnychenko <andrew@daynix.com>
* Yuri Benditovich <yuri.benditovich@daynix.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/

#ifndef QEMU_EBPF_RSS_H
#define QEMU_EBPF_RSS_H

struct EBPFRSSContext {
void *obj;
int program_fd;
int map_configuration;
int map_toeplitz_key;
int map_indirections_table;
};

struct EBPFRSSConfig {
uint8_t redirect;
uint8_t populate_hash;
uint32_t hash_types;
uint16_t indirections_len;
uint16_t default_queue;
} __attribute__((packed));

void ebpf_rss_init(struct EBPFRSSContext *ctx);

bool ebpf_rss_is_loaded(struct EBPFRSSContext *ctx);

bool ebpf_rss_load(struct EBPFRSSContext *ctx);

bool ebpf_rss_set_all(struct EBPFRSSContext *ctx, struct EBPFRSSConfig *config,
uint16_t *indirections_table, uint8_t *toeplitz_key);

void ebpf_rss_unload(struct EBPFRSSContext *ctx);

#endif /* QEMU_EBPF_RSS_H */
1 change: 1 addition & 0 deletions ebpf/meson.build
@@ -0,0 +1 @@
common_ss.add(when: libbpf, if_true: files('ebpf_rss.c'), if_false: files('ebpf_rss-stub.c'))

0 comments on commit 5d02a41

Please sign in to comment.