4 * Developed by Daynix Computing LTD (http://www.daynix.com)
7 * Andrew Melnychenko <andrew@daynix.com>
8 * Yuri Benditovich <yuri.benditovich@daynix.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See
11 * the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "qemu/error-report.h"
17 #include <bpf/libbpf.h>
20 #include "hw/virtio/virtio-net.h" /* VIRTIO_NET_RSS_MAX_TABLE_LEN */
22 #include "ebpf/ebpf_rss.h"
23 #include "ebpf/rss.bpf.skeleton.h"
26 void ebpf_rss_init(struct EBPFRSSContext
*ctx
)
33 bool ebpf_rss_is_loaded(struct EBPFRSSContext
*ctx
)
35 return ctx
!= NULL
&& ctx
->obj
!= NULL
;
38 bool ebpf_rss_load(struct EBPFRSSContext
*ctx
)
40 struct rss_bpf
*rss_bpf_ctx
;
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");
52 bpf_program__set_socket_filter(rss_bpf_ctx
->progs
.tun_rss_steering_prog
);
54 if (rss_bpf__load(rss_bpf_ctx
)) {
55 trace_ebpf_error("eBPF RSS", "can not load RSS program");
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
);
71 rss_bpf__destroy(rss_bpf_ctx
);
77 static bool ebpf_rss_set_config(struct EBPFRSSContext
*ctx
,
78 struct EBPFRSSConfig
*config
)
82 if (!ebpf_rss_is_loaded(ctx
)) {
85 if (bpf_map_update_elem(ctx
->map_configuration
,
86 &map_key
, config
, 0) < 0) {
92 static bool ebpf_rss_set_indirections_table(struct EBPFRSSContext
*ctx
,
93 uint16_t *indirections_table
,
98 if (!ebpf_rss_is_loaded(ctx
) || indirections_table
== NULL
||
99 len
> VIRTIO_NET_RSS_MAX_TABLE_LEN
) {
103 for (; i
< len
; ++i
) {
104 if (bpf_map_update_elem(ctx
->map_indirections_table
, &i
,
105 indirections_table
+ i
, 0) < 0) {
112 static bool ebpf_rss_set_toepliz_key(struct EBPFRSSContext
*ctx
,
113 uint8_t *toeplitz_key
)
115 uint32_t map_key
= 0;
117 /* prepare toeplitz key */
118 uint8_t toe
[VIRTIO_NET_RSS_MAX_KEY_SIZE
] = {};
120 if (!ebpf_rss_is_loaded(ctx
) || toeplitz_key
== NULL
) {
123 memcpy(toe
, toeplitz_key
, VIRTIO_NET_RSS_MAX_KEY_SIZE
);
124 *(uint32_t *)toe
= ntohl(*(uint32_t *)toe
);
126 if (bpf_map_update_elem(ctx
->map_toeplitz_key
, &map_key
, toe
,
133 bool ebpf_rss_set_all(struct EBPFRSSContext
*ctx
, struct EBPFRSSConfig
*config
,
134 uint16_t *indirections_table
, uint8_t *toeplitz_key
)
136 if (!ebpf_rss_is_loaded(ctx
) || config
== NULL
||
137 indirections_table
== NULL
|| toeplitz_key
== NULL
) {
141 if (!ebpf_rss_set_config(ctx
, config
)) {
145 if (!ebpf_rss_set_indirections_table(ctx
, indirections_table
,
146 config
->indirections_len
)) {
150 if (!ebpf_rss_set_toepliz_key(ctx
, toeplitz_key
)) {
157 void ebpf_rss_unload(struct EBPFRSSContext
*ctx
)
159 if (!ebpf_rss_is_loaded(ctx
)) {
163 rss_bpf__destroy(ctx
->obj
);