Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2016 Intel Corporation
3 : : */
4 : :
5 : : #include <sys/types.h>
6 : : #include <sys/stat.h>
7 : : #include <fcntl.h>
8 : : #include <unistd.h>
9 : : #include <errno.h>
10 : : #include <stdlib.h>
11 : :
12 : : #include <rte_memory.h>
13 : :
14 : : #include "vhost.h"
15 : : #include "virtio_user_dev.h"
16 : : #include "vhost_kernel_tap.h"
17 : :
18 : : struct vhost_kernel_data {
19 : : int *vhostfds;
20 : : int *tapfds;
21 : : };
22 : :
23 : : struct vhost_memory_kernel {
24 : : uint32_t nregions;
25 : : uint32_t padding;
26 : : struct vhost_memory_region regions[];
27 : : };
28 : :
29 : : /* vhost kernel ioctls */
30 : : #define VHOST_VIRTIO 0xAF
31 : : #define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
32 : : #define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
33 : : #define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
34 : : #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
35 : : #define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory_kernel)
36 : : #define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
37 : : #define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
38 : : #define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
39 : : #define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
40 : : #define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
41 : : #define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
42 : : #define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
43 : : #define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
44 : : #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
45 : : #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
46 : :
47 : : /* with below features, vhost kernel does not need to do the checksum and TSO,
48 : : * these info will be passed to virtio_user through virtio net header.
49 : : */
50 : : #define VHOST_KERNEL_GUEST_OFFLOADS_MASK \
51 : : ((1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
52 : : (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
53 : : (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
54 : : (1ULL << VIRTIO_NET_F_GUEST_ECN) | \
55 : : (1ULL << VIRTIO_NET_F_GUEST_UFO))
56 : :
57 : : /* with below features, when flows from virtio_user to vhost kernel
58 : : * (1) if flows goes up through the kernel networking stack, it does not need
59 : : * to verify checksum, which can save CPU cycles;
60 : : * (2) if flows goes through a Linux bridge and outside from an interface
61 : : * (kernel driver), checksum and TSO will be done by GSO in kernel or even
62 : : * offloaded into real physical device.
63 : : */
64 : : #define VHOST_KERNEL_HOST_OFFLOADS_MASK \
65 : : ((1ULL << VIRTIO_NET_F_HOST_TSO4) | \
66 : : (1ULL << VIRTIO_NET_F_HOST_TSO6) | \
67 : : (1ULL << VIRTIO_NET_F_CSUM))
68 : :
69 : : static uint64_t max_regions = 64;
70 : :
71 : : static void
72 : 0 : get_vhost_kernel_max_regions(void)
73 : : {
74 : : int fd;
75 : 0 : char buf[20] = {'\0'};
76 : :
77 : : fd = open("/sys/module/vhost/parameters/max_mem_regions", O_RDONLY);
78 [ # # ]: 0 : if (fd < 0)
79 : 0 : return;
80 : :
81 [ # # ]: 0 : if (read(fd, buf, sizeof(buf) - 1) > 0)
82 : 0 : max_regions = strtoull(buf, NULL, 10);
83 : :
84 : 0 : close(fd);
85 : : }
86 : :
87 : : static int
88 : 0 : vhost_kernel_ioctl(int fd, uint64_t request, void *arg)
89 : : {
90 : : int ret;
91 : :
92 : 0 : ret = ioctl(fd, request, arg);
93 [ # # ]: 0 : if (ret) {
94 : 0 : PMD_DRV_LOG(ERR, "Vhost-kernel ioctl %"PRIu64" failed (%s)",
95 : : request, strerror(errno));
96 : 0 : return -1;
97 : : }
98 : :
99 : : return 0;
100 : : }
101 : :
102 : : static int
103 : 0 : vhost_kernel_set_owner(struct virtio_user_dev *dev)
104 : : {
105 : : int ret;
106 : : uint32_t i;
107 : 0 : struct vhost_kernel_data *data = dev->backend_data;
108 : :
109 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; ++i) {
110 [ # # ]: 0 : if (data->vhostfds[i] < 0)
111 : 0 : continue;
112 : :
113 : 0 : ret = vhost_kernel_ioctl(data->vhostfds[i], VHOST_SET_OWNER, NULL);
114 [ # # ]: 0 : if (ret < 0)
115 : 0 : return ret;
116 : : }
117 : :
118 : : return 0;
119 : : }
120 : :
121 : : static int
122 : 0 : vhost_kernel_get_features(struct virtio_user_dev *dev, uint64_t *features)
123 : : {
124 : 0 : struct vhost_kernel_data *data = dev->backend_data;
125 : : unsigned int tap_flags;
126 : : int ret;
127 : :
128 : 0 : ret = vhost_kernel_ioctl(data->vhostfds[0], VHOST_GET_FEATURES, features);
129 [ # # ]: 0 : if (ret < 0) {
130 : 0 : PMD_DRV_LOG(ERR, "Failed to get features");
131 : 0 : return -1;
132 : : }
133 : :
134 : 0 : ret = tap_get_flags(data->tapfds[0], &tap_flags);
135 [ # # ]: 0 : if (ret < 0) {
136 : 0 : PMD_DRV_LOG(ERR, "Failed to get TAP features");
137 : 0 : return -1;
138 : : }
139 : :
140 : : /* with tap as the backend, all these features are supported
141 : : * but not claimed by vhost-net, so we add them back when
142 : : * reporting to upper layer.
143 : : */
144 [ # # ]: 0 : if (tap_flags & IFF_VNET_HDR) {
145 : 0 : *features |= VHOST_KERNEL_GUEST_OFFLOADS_MASK;
146 : 0 : *features |= VHOST_KERNEL_HOST_OFFLOADS_MASK;
147 : : }
148 : :
149 : : /* vhost_kernel will not declare this feature, but it does
150 : : * support multi-queue.
151 : : */
152 [ # # ]: 0 : if (tap_flags & IFF_MULTI_QUEUE)
153 : 0 : *features |= (1ull << VIRTIO_NET_F_MQ);
154 : :
155 : : return 0;
156 : : }
157 : :
158 : : static int
159 : 0 : vhost_kernel_set_features(struct virtio_user_dev *dev, uint64_t features)
160 : : {
161 : 0 : struct vhost_kernel_data *data = dev->backend_data;
162 : : uint32_t i;
163 : : int ret;
164 : :
165 : : /* We don't need memory protection here */
166 : 0 : features &= ~(1ULL << VIRTIO_F_IOMMU_PLATFORM);
167 : : /* VHOST kernel does not know about below flags */
168 : 0 : features &= ~VHOST_KERNEL_GUEST_OFFLOADS_MASK;
169 : 0 : features &= ~VHOST_KERNEL_HOST_OFFLOADS_MASK;
170 : 0 : features &= ~(1ULL << VIRTIO_NET_F_MQ);
171 : :
172 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; ++i) {
173 [ # # ]: 0 : if (data->vhostfds[i] < 0)
174 : 0 : continue;
175 : :
176 : 0 : ret = vhost_kernel_ioctl(data->vhostfds[i], VHOST_SET_FEATURES, &features);
177 [ # # ]: 0 : if (ret < 0)
178 : 0 : return ret;
179 : : }
180 : :
181 : : return 0;
182 : : }
183 : :
184 : : static int
185 : 0 : add_memseg_list(const struct rte_memseg_list *msl, void *arg)
186 : : {
187 : : struct vhost_memory_kernel *vm = arg;
188 : : struct vhost_memory_region *mr;
189 : : void *start_addr;
190 : : uint64_t len;
191 : :
192 [ # # ]: 0 : if (msl->external)
193 : : return 0;
194 : :
195 [ # # ]: 0 : if (vm->nregions >= max_regions)
196 : : return -1;
197 : :
198 : 0 : start_addr = msl->base_va;
199 : 0 : len = msl->page_sz * msl->memseg_arr.len;
200 : :
201 : 0 : mr = &vm->regions[vm->nregions++];
202 : :
203 : 0 : mr->guest_phys_addr = (uint64_t)(uintptr_t)start_addr;
204 : 0 : mr->userspace_addr = (uint64_t)(uintptr_t)start_addr;
205 : 0 : mr->memory_size = len;
206 : 0 : mr->mmap_offset = 0; /* flags_padding */
207 : :
208 : 0 : PMD_DRV_LOG(DEBUG, "index=%u addr=%p len=%" PRIu64,
209 : : vm->nregions - 1, start_addr, len);
210 : :
211 : 0 : return 0;
212 : : }
213 : :
214 : : /* By default, vhost kernel module allows 64 regions, but DPDK may
215 : : * have much more memory regions. Below function will treat each
216 : : * contiguous memory space reserved by DPDK as one region.
217 : : */
218 : : static int
219 : 0 : vhost_kernel_set_memory_table(struct virtio_user_dev *dev)
220 : : {
221 : : uint32_t i;
222 : 0 : struct vhost_kernel_data *data = dev->backend_data;
223 : : struct vhost_memory_kernel *vm;
224 : : int ret;
225 : :
226 : 0 : vm = malloc(sizeof(struct vhost_memory_kernel) +
227 : 0 : max_regions *
228 : : sizeof(struct vhost_memory_region));
229 [ # # ]: 0 : if (!vm)
230 : 0 : goto err;
231 : :
232 : 0 : vm->nregions = 0;
233 : 0 : vm->padding = 0;
234 : :
235 : : /*
236 : : * The memory lock has already been taken by memory subsystem
237 : : * or virtio_user_start_device().
238 : : */
239 : 0 : ret = rte_memseg_list_walk_thread_unsafe(add_memseg_list, vm);
240 [ # # ]: 0 : if (ret < 0)
241 : 0 : goto err_free;
242 : :
243 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; ++i) {
244 [ # # ]: 0 : if (data->vhostfds[i] < 0)
245 : 0 : continue;
246 : :
247 : 0 : ret = vhost_kernel_ioctl(data->vhostfds[i], VHOST_SET_MEM_TABLE, vm);
248 [ # # ]: 0 : if (ret < 0)
249 : 0 : goto err_free;
250 : : }
251 : :
252 : 0 : free(vm);
253 : :
254 : 0 : return 0;
255 : 0 : err_free:
256 : 0 : free(vm);
257 : 0 : err:
258 : 0 : PMD_DRV_LOG(ERR, "Failed to set memory table");
259 : 0 : return -1;
260 : : }
261 : :
262 : : static int
263 : 0 : vhost_kernel_set_vring(struct virtio_user_dev *dev, uint64_t req, struct vhost_vring_state *state)
264 : : {
265 : : int ret, fd;
266 : 0 : unsigned int index = state->index;
267 : 0 : struct vhost_kernel_data *data = dev->backend_data;
268 : :
269 : : /* Convert from queue index to queue-pair & offset */
270 : 0 : fd = data->vhostfds[state->index / 2];
271 : 0 : state->index %= 2;
272 : :
273 : 0 : ret = vhost_kernel_ioctl(fd, req, state);
274 [ # # ]: 0 : if (ret < 0) {
275 : 0 : PMD_DRV_LOG(ERR, "Failed to set vring (request %" PRIu64 ")", req);
276 : 0 : return -1;
277 : : }
278 : :
279 : : /* restore index back to queue index */
280 : 0 : state->index = index;
281 : :
282 : 0 : return 0;
283 : : }
284 : :
285 : : static int
286 : 0 : vhost_kernel_set_vring_num(struct virtio_user_dev *dev, struct vhost_vring_state *state)
287 : : {
288 : 0 : return vhost_kernel_set_vring(dev, VHOST_SET_VRING_NUM, state);
289 : : }
290 : :
291 : : static int
292 : 0 : vhost_kernel_set_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state)
293 : : {
294 : 0 : return vhost_kernel_set_vring(dev, VHOST_SET_VRING_BASE, state);
295 : : }
296 : :
297 : : static int
298 : 0 : vhost_kernel_get_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state)
299 : : {
300 : 0 : return vhost_kernel_set_vring(dev, VHOST_GET_VRING_BASE, state);
301 : : }
302 : :
303 : : static int
304 : 0 : vhost_kernel_set_vring_file(struct virtio_user_dev *dev, uint64_t req,
305 : : struct vhost_vring_file *file)
306 : : {
307 : : int ret, fd;
308 : 0 : unsigned int index = file->index;
309 : 0 : struct vhost_kernel_data *data = dev->backend_data;
310 : :
311 : : /* Convert from queue index to queue-pair & offset */
312 : 0 : fd = data->vhostfds[file->index / 2];
313 : 0 : file->index %= 2;
314 : :
315 : 0 : ret = vhost_kernel_ioctl(fd, req, file);
316 [ # # ]: 0 : if (ret < 0) {
317 : 0 : PMD_DRV_LOG(ERR, "Failed to set vring file (request %" PRIu64 ")", req);
318 : 0 : return -1;
319 : : }
320 : :
321 : : /* restore index back to queue index */
322 : 0 : file->index = index;
323 : :
324 : 0 : return 0;
325 : : }
326 : :
327 : : static int
328 : 0 : vhost_kernel_set_vring_kick(struct virtio_user_dev *dev, struct vhost_vring_file *file)
329 : : {
330 : 0 : return vhost_kernel_set_vring_file(dev, VHOST_SET_VRING_KICK, file);
331 : : }
332 : :
333 : : static int
334 : 0 : vhost_kernel_set_vring_call(struct virtio_user_dev *dev, struct vhost_vring_file *file)
335 : : {
336 : 0 : return vhost_kernel_set_vring_file(dev, VHOST_SET_VRING_CALL, file);
337 : : }
338 : :
339 : : static int
340 : 0 : vhost_kernel_set_vring_addr(struct virtio_user_dev *dev, struct vhost_vring_addr *addr)
341 : : {
342 : : int ret, fd;
343 : 0 : unsigned int index = addr->index;
344 : 0 : struct vhost_kernel_data *data = dev->backend_data;
345 : :
346 : : /* Convert from queue index to queue-pair & offset */
347 : 0 : fd = data->vhostfds[addr->index / 2];
348 : 0 : addr->index %= 2;
349 : :
350 : 0 : ret = vhost_kernel_ioctl(fd, VHOST_SET_VRING_ADDR, addr);
351 [ # # ]: 0 : if (ret < 0) {
352 : 0 : PMD_DRV_LOG(ERR, "Failed to set vring address");
353 : 0 : return -1;
354 : : }
355 : :
356 : : /* restore index back to queue index */
357 : 0 : addr->index = index;
358 : :
359 : 0 : return 0;
360 : : }
361 : :
362 : : static int
363 : 0 : vhost_kernel_get_status(struct virtio_user_dev *dev __rte_unused, uint8_t *status __rte_unused)
364 : : {
365 : 0 : return -ENOTSUP;
366 : : }
367 : :
368 : : static int
369 : 0 : vhost_kernel_set_status(struct virtio_user_dev *dev __rte_unused, uint8_t status __rte_unused)
370 : : {
371 : 0 : return -ENOTSUP;
372 : : }
373 : :
374 : : /**
375 : : * Set up environment to talk with a vhost kernel backend.
376 : : *
377 : : * @return
378 : : * - (-1) if fail to set up;
379 : : * - (>=0) if successful.
380 : : */
381 : : static int
382 : 0 : vhost_kernel_setup(struct virtio_user_dev *dev)
383 : : {
384 : : struct vhost_kernel_data *data;
385 : : unsigned int tap_features;
386 : : unsigned int tap_flags;
387 : : unsigned int r_flags;
388 : : const char *ifname;
389 : : uint32_t q, i;
390 : : int vhostfd;
391 : :
392 [ # # ]: 0 : if (tap_support_features(&tap_features) < 0)
393 : : return -1;
394 : :
395 [ # # ]: 0 : if ((tap_features & IFF_VNET_HDR) == 0) {
396 : 0 : PMD_INIT_LOG(ERR, "TAP does not support IFF_VNET_HDR");
397 : 0 : return -1;
398 : : }
399 : : r_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
400 : :
401 [ # # ]: 0 : if (tap_features & IFF_NAPI)
402 : : r_flags |= IFF_NAPI;
403 : :
404 : 0 : data = malloc(sizeof(*data));
405 [ # # ]: 0 : if (!data) {
406 : 0 : PMD_INIT_LOG(ERR, "(%s) Failed to allocate Vhost-kernel data", dev->path);
407 : 0 : return -1;
408 : : }
409 : :
410 : 0 : data->vhostfds = malloc(dev->max_queue_pairs * sizeof(int));
411 [ # # ]: 0 : if (!data->vhostfds) {
412 : 0 : PMD_INIT_LOG(ERR, "(%s) Failed to allocate Vhost FDs", dev->path);
413 : 0 : goto err_data;
414 : : }
415 : 0 : data->tapfds = malloc(dev->max_queue_pairs * sizeof(int));
416 [ # # ]: 0 : if (!data->tapfds) {
417 : 0 : PMD_INIT_LOG(ERR, "(%s) Failed to allocate TAP FDs", dev->path);
418 : 0 : goto err_vhostfds;
419 : : }
420 : :
421 [ # # ]: 0 : for (q = 0; q < dev->max_queue_pairs; ++q) {
422 : 0 : data->vhostfds[q] = -1;
423 : 0 : data->tapfds[q] = -1;
424 : : }
425 : :
426 : 0 : get_vhost_kernel_max_regions();
427 : :
428 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; ++i) {
429 : 0 : vhostfd = open(dev->path, O_RDWR);
430 [ # # ]: 0 : if (vhostfd < 0) {
431 : 0 : PMD_DRV_LOG(ERR, "fail to open %s, %s", dev->path, strerror(errno));
432 : 0 : goto err_tapfds;
433 : : }
434 : 0 : data->vhostfds[i] = vhostfd;
435 : : }
436 : :
437 [ # # ]: 0 : ifname = dev->ifname != NULL ? dev->ifname : "tap%d";
438 : 0 : data->tapfds[0] = tap_open(ifname, r_flags, (tap_features & IFF_MULTI_QUEUE) != 0);
439 [ # # ]: 0 : if (data->tapfds[0] < 0)
440 : 0 : goto err_tapfds;
441 [ # # # # ]: 0 : if (dev->ifname == NULL && tap_get_name(data->tapfds[0], &dev->ifname) < 0) {
442 : 0 : PMD_DRV_LOG(ERR, "fail to get tap name (%d)", data->tapfds[0]);
443 : 0 : goto err_tapfds;
444 : : }
445 [ # # ]: 0 : if (tap_get_flags(data->tapfds[0], &tap_flags) < 0) {
446 : 0 : PMD_DRV_LOG(ERR, "fail to get tap flags for tap %s", dev->ifname);
447 : 0 : goto err_tapfds;
448 : : }
449 [ # # # # ]: 0 : if ((tap_flags & IFF_MULTI_QUEUE) == 0 && dev->max_queue_pairs > 1) {
450 : 0 : PMD_DRV_LOG(ERR, "tap %s does not support multi queue", dev->ifname);
451 : 0 : goto err_tapfds;
452 : : }
453 : :
454 [ # # ]: 0 : for (i = 1; i < dev->max_queue_pairs; i++) {
455 : 0 : data->tapfds[i] = tap_open(dev->ifname, r_flags, true);
456 [ # # ]: 0 : if (data->tapfds[i] < 0)
457 : 0 : goto err_tapfds;
458 : : }
459 : :
460 : 0 : dev->backend_data = data;
461 : :
462 : 0 : return 0;
463 : :
464 : : err_tapfds:
465 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; i++) {
466 [ # # ]: 0 : if (data->vhostfds[i] >= 0)
467 : 0 : close(data->vhostfds[i]);
468 [ # # ]: 0 : if (data->tapfds[i] >= 0)
469 : 0 : close(data->tapfds[i]);
470 : : }
471 : :
472 : 0 : free(data->tapfds);
473 : 0 : err_vhostfds:
474 : 0 : free(data->vhostfds);
475 : 0 : err_data:
476 : 0 : free(data);
477 : :
478 : 0 : return -1;
479 : : }
480 : :
481 : : static int
482 : 0 : vhost_kernel_destroy(struct virtio_user_dev *dev)
483 : : {
484 : 0 : struct vhost_kernel_data *data = dev->backend_data;
485 : : uint32_t i;
486 : :
487 [ # # ]: 0 : if (!data)
488 : : return 0;
489 : :
490 [ # # ]: 0 : for (i = 0; i < dev->max_queue_pairs; ++i) {
491 [ # # ]: 0 : if (data->vhostfds[i] >= 0)
492 : 0 : close(data->vhostfds[i]);
493 [ # # ]: 0 : if (data->tapfds[i] >= 0)
494 : 0 : close(data->tapfds[i]);
495 : : }
496 : :
497 : 0 : free(data->vhostfds);
498 : 0 : free(data->tapfds);
499 : 0 : free(data);
500 : 0 : dev->backend_data = NULL;
501 : :
502 : 0 : return 0;
503 : : }
504 : :
505 : : static int
506 : 0 : vhost_kernel_set_backend(int vhostfd, int tapfd)
507 : : {
508 : : struct vhost_vring_file f;
509 : :
510 : 0 : f.fd = tapfd;
511 : 0 : f.index = 0;
512 [ # # ]: 0 : if (ioctl(vhostfd, VHOST_NET_SET_BACKEND, &f) < 0) {
513 : 0 : PMD_DRV_LOG(ERR, "VHOST_NET_SET_BACKEND fails, %s",
514 : : strerror(errno));
515 : 0 : return -1;
516 : : }
517 : :
518 : 0 : f.index = 1;
519 [ # # ]: 0 : if (ioctl(vhostfd, VHOST_NET_SET_BACKEND, &f) < 0) {
520 : 0 : PMD_DRV_LOG(ERR, "VHOST_NET_SET_BACKEND fails, %s",
521 : : strerror(errno));
522 : 0 : return -1;
523 : : }
524 : :
525 : : return 0;
526 : : }
527 : :
528 : : static int
529 : 0 : vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
530 : : uint16_t pair_idx,
531 : : int enable)
532 : : {
533 : 0 : struct vhost_kernel_data *data = dev->backend_data;
534 : : int hdr_size;
535 : : int vhostfd;
536 : : int tapfd;
537 : :
538 [ # # ]: 0 : if (dev->qp_enabled[pair_idx] == enable)
539 : : return 0;
540 : :
541 : 0 : vhostfd = data->vhostfds[pair_idx];
542 : 0 : tapfd = data->tapfds[pair_idx];
543 : :
544 [ # # ]: 0 : if (!enable) {
545 [ # # ]: 0 : if (vhost_kernel_set_backend(vhostfd, -1) < 0) {
546 : 0 : PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel");
547 : 0 : return -1;
548 : : }
549 : 0 : dev->qp_enabled[pair_idx] = false;
550 : 0 : return 0;
551 : : }
552 : :
553 [ # # ]: 0 : if ((dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) ||
554 : : (dev->features & (1ULL << VIRTIO_F_VERSION_1)))
555 : : hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf);
556 : : else
557 : : hdr_size = sizeof(struct virtio_net_hdr);
558 : :
559 : : /* Set mac on tap only once when starting */
560 [ # # # # : 0 : if (!dev->started && pair_idx == 0 &&
# # ]
561 : 0 : tap_set_mac(data->tapfds[pair_idx], dev->mac_addr) < 0)
562 : : return -1;
563 : :
564 [ # # ]: 0 : if (vhost_kernel_tap_setup(tapfd, hdr_size, dev->features) < 0) {
565 : 0 : PMD_DRV_LOG(ERR, "fail to setup tap for vhost kernel");
566 : 0 : return -1;
567 : : }
568 : :
569 [ # # ]: 0 : if (vhost_kernel_set_backend(vhostfd, tapfd) < 0) {
570 : 0 : PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel");
571 : 0 : return -1;
572 : : }
573 : :
574 : 0 : dev->qp_enabled[pair_idx] = true;
575 : 0 : return 0;
576 : : }
577 : :
578 : : static int
579 : 0 : vhost_kernel_get_backend_features(uint64_t *features)
580 : : {
581 : 0 : *features = 0;
582 : :
583 : 0 : return 0;
584 : : }
585 : :
586 : : static int
587 : 0 : vhost_kernel_update_link_state(struct virtio_user_dev *dev __rte_unused)
588 : : {
589 : : /* Nothing to update (Maybe get TAP interface link state?) */
590 : 0 : return 0;
591 : : }
592 : :
593 : : static int
594 : 0 : vhost_kernel_get_intr_fd(struct virtio_user_dev *dev __rte_unused)
595 : : {
596 : : /* No link state interrupt with Vhost-kernel */
597 : 0 : return -1;
598 : : }
599 : :
600 : : struct virtio_user_backend_ops virtio_ops_kernel = {
601 : : .setup = vhost_kernel_setup,
602 : : .destroy = vhost_kernel_destroy,
603 : : .get_backend_features = vhost_kernel_get_backend_features,
604 : : .set_owner = vhost_kernel_set_owner,
605 : : .get_features = vhost_kernel_get_features,
606 : : .set_features = vhost_kernel_set_features,
607 : : .set_memory_table = vhost_kernel_set_memory_table,
608 : : .set_vring_num = vhost_kernel_set_vring_num,
609 : : .set_vring_base = vhost_kernel_set_vring_base,
610 : : .get_vring_base = vhost_kernel_get_vring_base,
611 : : .set_vring_call = vhost_kernel_set_vring_call,
612 : : .set_vring_kick = vhost_kernel_set_vring_kick,
613 : : .set_vring_addr = vhost_kernel_set_vring_addr,
614 : : .get_status = vhost_kernel_get_status,
615 : : .set_status = vhost_kernel_set_status,
616 : : .enable_qp = vhost_kernel_enable_queue_pair,
617 : : .update_link_state = vhost_kernel_update_link_state,
618 : : .get_intr_fd = vhost_kernel_get_intr_fd,
619 : : };
|