]>
Commit | Line | Data |
---|---|---|
46627f41 AM |
1 | /* |
2 | * eBPF RSS loader | |
3 | * | |
4 | * Developed by Daynix Computing LTD (http://www.daynix.com) | |
5 | * | |
6 | * Authors: | |
7 | * Andrew Melnychenko <andrew@daynix.com> | |
8 | * Yuri Benditovich <yuri.benditovich@daynix.com> | |
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 | ||
a495eba0 | 52 | bpf_program__set_type(rss_bpf_ctx->progs.tun_rss_steering_prog, BPF_PROG_TYPE_SOCKET_FILTER); |
46627f41 AM |
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 | } |