bd7e55ed62994d67849d81e3d1a91302c82fd923
[dpdk.git] / lib / librte_vhost / virtio-net.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <linux/vhost.h>
35 #include <linux/virtio_net.h>
36 #include <stddef.h>
37 #include <stdint.h>
38 #include <stdlib.h>
39 #include <assert.h>
40 #include <sys/mman.h>
41 #include <unistd.h>
42 #ifdef RTE_LIBRTE_VHOST_NUMA
43 #include <numaif.h>
44 #endif
45
46 #include <sys/socket.h>
47
48 #include <rte_ethdev.h>
49 #include <rte_log.h>
50 #include <rte_string_fns.h>
51 #include <rte_memory.h>
52 #include <rte_malloc.h>
53 #include <rte_virtio_net.h>
54
55 #include "vhost-net.h"
56
57 #define MAX_VHOST_DEVICE        1024
58 static struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
59
60 /* device ops to add/remove device to/from data core. */
61 struct virtio_net_device_ops const *notify_ops;
62
63 #define VHOST_USER_F_PROTOCOL_FEATURES  30
64
65 /* Features supported by this lib. */
66 #define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
67                                 (1ULL << VIRTIO_NET_F_CTRL_VQ) | \
68                                 (1ULL << VIRTIO_NET_F_CTRL_RX) | \
69                                 (1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
70                                 (VHOST_SUPPORTS_MQ)            | \
71                                 (1ULL << VIRTIO_F_VERSION_1)   | \
72                                 (1ULL << VHOST_F_LOG_ALL)      | \
73                                 (1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
74                                 (1ULL << VIRTIO_NET_F_HOST_TSO4) | \
75                                 (1ULL << VIRTIO_NET_F_HOST_TSO6) | \
76                                 (1ULL << VIRTIO_NET_F_CSUM)    | \
77                                 (1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
78                                 (1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
79                                 (1ULL << VIRTIO_NET_F_GUEST_TSO6))
80
81 static uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
82
83
84 /*
85  * Converts QEMU virtual address to Vhost virtual address. This function is
86  * used to convert the ring addresses to our address space.
87  */
88 static uint64_t
89 qva_to_vva(struct virtio_net *dev, uint64_t qemu_va)
90 {
91         struct virtio_memory_regions *region;
92         uint64_t vhost_va = 0;
93         uint32_t regionidx = 0;
94
95         /* Find the region where the address lives. */
96         for (regionidx = 0; regionidx < dev->mem->nregions; regionidx++) {
97                 region = &dev->mem->regions[regionidx];
98                 if ((qemu_va >= region->userspace_address) &&
99                         (qemu_va <= region->userspace_address +
100                         region->memory_size)) {
101                         vhost_va = qemu_va + region->guest_phys_address +
102                                 region->address_offset -
103                                 region->userspace_address;
104                         break;
105                 }
106         }
107         return vhost_va;
108 }
109
110 struct virtio_net *
111 get_device(int vid)
112 {
113         struct virtio_net *dev = vhost_devices[vid];
114
115         if (unlikely(!dev)) {
116                 RTE_LOG(ERR, VHOST_CONFIG,
117                         "(%d) device not found.\n", vid);
118         }
119
120         return dev;
121 }
122
123 static void
124 cleanup_vq(struct vhost_virtqueue *vq, int destroy)
125 {
126         if ((vq->callfd >= 0) && (destroy != 0))
127                 close(vq->callfd);
128         if (vq->kickfd >= 0)
129                 close(vq->kickfd);
130 }
131
132 /*
133  * Unmap any memory, close any file descriptors and
134  * free any memory owned by a device.
135  */
136 static void
137 cleanup_device(struct virtio_net *dev, int destroy)
138 {
139         uint32_t i;
140
141         vhost_backend_cleanup(dev);
142
143         for (i = 0; i < dev->virt_qp_nb; i++) {
144                 cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ], destroy);
145                 cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ], destroy);
146         }
147 }
148
149 /*
150  * Release virtqueues and device memory.
151  */
152 static void
153 free_device(struct virtio_net *dev)
154 {
155         uint32_t i;
156
157         for (i = 0; i < dev->virt_qp_nb; i++)
158                 rte_free(dev->virtqueue[i * VIRTIO_QNUM]);
159
160         rte_free(dev);
161 }
162
163 static void
164 init_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
165 {
166         memset(vq, 0, sizeof(struct vhost_virtqueue));
167
168         vq->kickfd = VIRTIO_UNINITIALIZED_EVENTFD;
169         vq->callfd = VIRTIO_UNINITIALIZED_EVENTFD;
170
171         /* Backends are set to -1 indicating an inactive device. */
172         vq->backend = -1;
173
174         /* always set the default vq pair to enabled */
175         if (qp_idx == 0)
176                 vq->enabled = 1;
177 }
178
179 static void
180 init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
181 {
182         uint32_t base_idx = qp_idx * VIRTIO_QNUM;
183
184         init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
185         init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
186 }
187
188 static void
189 reset_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
190 {
191         int callfd;
192
193         callfd = vq->callfd;
194         init_vring_queue(vq, qp_idx);
195         vq->callfd = callfd;
196 }
197
198 static void
199 reset_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
200 {
201         uint32_t base_idx = qp_idx * VIRTIO_QNUM;
202
203         reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
204         reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
205 }
206
207 static int
208 alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
209 {
210         struct vhost_virtqueue *virtqueue = NULL;
211         uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
212         uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
213
214         virtqueue = rte_malloc(NULL,
215                                sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);
216         if (virtqueue == NULL) {
217                 RTE_LOG(ERR, VHOST_CONFIG,
218                         "Failed to allocate memory for virt qp:%d.\n", qp_idx);
219                 return -1;
220         }
221
222         dev->virtqueue[virt_rx_q_idx] = virtqueue;
223         dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
224
225         init_vring_queue_pair(dev, qp_idx);
226
227         dev->virt_qp_nb += 1;
228
229         return 0;
230 }
231
232 /*
233  * Reset some variables in device structure, while keeping few
234  * others untouched, such as vid, ifname, virt_qp_nb: they
235  * should be same unless the device is removed.
236  */
237 static void
238 reset_device(struct virtio_net *dev)
239 {
240         uint32_t i;
241
242         dev->features = 0;
243         dev->protocol_features = 0;
244         dev->flags = 0;
245
246         for (i = 0; i < dev->virt_qp_nb; i++)
247                 reset_vring_queue_pair(dev, i);
248 }
249
250 /*
251  * Function is called from the CUSE open function. The device structure is
252  * initialised and a new entry is added to the device configuration linked
253  * list.
254  */
255 int
256 vhost_new_device(void)
257 {
258         struct virtio_net *dev;
259         int i;
260
261         dev = rte_zmalloc(NULL, sizeof(struct virtio_net), 0);
262         if (dev == NULL) {
263                 RTE_LOG(ERR, VHOST_CONFIG,
264                         "Failed to allocate memory for new dev.\n");
265                 return -1;
266         }
267
268         for (i = 0; i < MAX_VHOST_DEVICE; i++) {
269                 if (vhost_devices[i] == NULL)
270                         break;
271         }
272         if (i == MAX_VHOST_DEVICE) {
273                 RTE_LOG(ERR, VHOST_CONFIG,
274                         "Failed to find a free slot for new device.\n");
275                 return -1;
276         }
277
278         vhost_devices[i] = dev;
279         dev->vid = i;
280
281         return i;
282 }
283
284 /*
285  * Function is called from the CUSE release function. This function will
286  * cleanup the device and remove it from device configuration linked list.
287  */
288 void
289 vhost_destroy_device(int vid)
290 {
291         struct virtio_net *dev = get_device(vid);
292
293         if (dev == NULL)
294                 return;
295
296         if (dev->flags & VIRTIO_DEV_RUNNING) {
297                 dev->flags &= ~VIRTIO_DEV_RUNNING;
298                 notify_ops->destroy_device(vid);
299         }
300
301         cleanup_device(dev, 1);
302         free_device(dev);
303
304         vhost_devices[vid] = NULL;
305 }
306
307 void
308 vhost_set_ifname(int vid, const char *if_name, unsigned int if_len)
309 {
310         struct virtio_net *dev;
311         unsigned int len;
312
313         dev = get_device(vid);
314         if (dev == NULL)
315                 return;
316
317         len = if_len > sizeof(dev->ifname) ?
318                 sizeof(dev->ifname) : if_len;
319
320         strncpy(dev->ifname, if_name, len);
321         dev->ifname[sizeof(dev->ifname) - 1] = '\0';
322 }
323
324
325 /*
326  * Called from CUSE IOCTL: VHOST_SET_OWNER
327  * This function just returns success at the moment unless
328  * the device hasn't been initialised.
329  */
330 int
331 vhost_set_owner(int vid)
332 {
333         struct virtio_net *dev;
334
335         dev = get_device(vid);
336         if (dev == NULL)
337                 return -1;
338
339         return 0;
340 }
341
342 /*
343  * Called from CUSE IOCTL: VHOST_RESET_OWNER
344  */
345 int
346 vhost_reset_owner(int vid)
347 {
348         struct virtio_net *dev;
349
350         dev = get_device(vid);
351         if (dev == NULL)
352                 return -1;
353
354         if (dev->flags & VIRTIO_DEV_RUNNING) {
355                 dev->flags &= ~VIRTIO_DEV_RUNNING;
356                 notify_ops->destroy_device(vid);
357         }
358
359         cleanup_device(dev, 0);
360         reset_device(dev);
361         return 0;
362 }
363
364 /*
365  * Called from CUSE IOCTL: VHOST_GET_FEATURES
366  * The features that we support are requested.
367  */
368 int
369 vhost_get_features(int vid, uint64_t *pu)
370 {
371         struct virtio_net *dev;
372
373         dev = get_device(vid);
374         if (dev == NULL)
375                 return -1;
376
377         /* Send our supported features. */
378         *pu = VHOST_FEATURES;
379         return 0;
380 }
381
382 /*
383  * Called from CUSE IOCTL: VHOST_SET_FEATURES
384  * We receive the negotiated features supported by us and the virtio device.
385  */
386 int
387 vhost_set_features(int vid, uint64_t *pu)
388 {
389         struct virtio_net *dev;
390
391         dev = get_device(vid);
392         if (dev == NULL)
393                 return -1;
394         if (*pu & ~VHOST_FEATURES)
395                 return -1;
396
397         dev->features = *pu;
398         if (dev->features &
399                 ((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
400                 dev->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
401         } else {
402                 dev->vhost_hlen = sizeof(struct virtio_net_hdr);
403         }
404         LOG_DEBUG(VHOST_CONFIG,
405                 "(%d) mergeable RX buffers %s, virtio 1 %s\n",
406                 dev->vid,
407                 (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) ? "on" : "off",
408                 (dev->features & (1ULL << VIRTIO_F_VERSION_1)) ? "on" : "off");
409
410         return 0;
411 }
412
413 /*
414  * Called from CUSE IOCTL: VHOST_SET_VRING_NUM
415  * The virtio device sends us the size of the descriptor ring.
416  */
417 int
418 vhost_set_vring_num(int vid, struct vhost_vring_state *state)
419 {
420         struct virtio_net *dev;
421
422         dev = get_device(vid);
423         if (dev == NULL)
424                 return -1;
425
426         /* State->index refers to the queue index. The txq is 1, rxq is 0. */
427         dev->virtqueue[state->index]->size = state->num;
428
429         return 0;
430 }
431
432 /*
433  * Reallocate virtio_dev and vhost_virtqueue data structure to make them on the
434  * same numa node as the memory of vring descriptor.
435  */
436 #ifdef RTE_LIBRTE_VHOST_NUMA
437 static struct virtio_net*
438 numa_realloc(struct virtio_net *dev, int index)
439 {
440         int oldnode, newnode;
441         struct virtio_net *old_dev;
442         struct vhost_virtqueue *old_vq, *vq;
443         int ret;
444
445         /*
446          * vq is allocated on pairs, we should try to do realloc
447          * on first queue of one queue pair only.
448          */
449         if (index % VIRTIO_QNUM != 0)
450                 return dev;
451
452         old_dev = dev;
453         vq = old_vq = dev->virtqueue[index];
454
455         ret = get_mempolicy(&newnode, NULL, 0, old_vq->desc,
456                             MPOL_F_NODE | MPOL_F_ADDR);
457
458         /* check if we need to reallocate vq */
459         ret |= get_mempolicy(&oldnode, NULL, 0, old_vq,
460                              MPOL_F_NODE | MPOL_F_ADDR);
461         if (ret) {
462                 RTE_LOG(ERR, VHOST_CONFIG,
463                         "Unable to get vq numa information.\n");
464                 return dev;
465         }
466         if (oldnode != newnode) {
467                 RTE_LOG(INFO, VHOST_CONFIG,
468                         "reallocate vq from %d to %d node\n", oldnode, newnode);
469                 vq = rte_malloc_socket(NULL, sizeof(*vq) * VIRTIO_QNUM, 0,
470                                        newnode);
471                 if (!vq)
472                         return dev;
473
474                 memcpy(vq, old_vq, sizeof(*vq) * VIRTIO_QNUM);
475                 rte_free(old_vq);
476         }
477
478         /* check if we need to reallocate dev */
479         ret = get_mempolicy(&oldnode, NULL, 0, old_dev,
480                             MPOL_F_NODE | MPOL_F_ADDR);
481         if (ret) {
482                 RTE_LOG(ERR, VHOST_CONFIG,
483                         "Unable to get dev numa information.\n");
484                 goto out;
485         }
486         if (oldnode != newnode) {
487                 RTE_LOG(INFO, VHOST_CONFIG,
488                         "reallocate dev from %d to %d node\n",
489                         oldnode, newnode);
490                 dev = rte_malloc_socket(NULL, sizeof(*dev), 0, newnode);
491                 if (!dev) {
492                         dev = old_dev;
493                         goto out;
494                 }
495
496                 memcpy(dev, old_dev, sizeof(*dev));
497                 rte_free(old_dev);
498         }
499
500 out:
501         dev->virtqueue[index] = vq;
502         dev->virtqueue[index + 1] = vq + 1;
503         vhost_devices[dev->vid] = dev;
504
505         return dev;
506 }
507 #else
508 static struct virtio_net*
509 numa_realloc(struct virtio_net *dev, int index __rte_unused)
510 {
511         return dev;
512 }
513 #endif
514
515 /*
516  * Called from CUSE IOCTL: VHOST_SET_VRING_ADDR
517  * The virtio device sends us the desc, used and avail ring addresses.
518  * This function then converts these to our address space.
519  */
520 int
521 vhost_set_vring_addr(int vid, struct vhost_vring_addr *addr)
522 {
523         struct virtio_net *dev;
524         struct vhost_virtqueue *vq;
525
526         dev = get_device(vid);
527         if ((dev == NULL) || (dev->mem == NULL))
528                 return -1;
529
530         /* addr->index refers to the queue index. The txq 1, rxq is 0. */
531         vq = dev->virtqueue[addr->index];
532
533         /* The addresses are converted from QEMU virtual to Vhost virtual. */
534         vq->desc = (struct vring_desc *)(uintptr_t)qva_to_vva(dev,
535                         addr->desc_user_addr);
536         if (vq->desc == 0) {
537                 RTE_LOG(ERR, VHOST_CONFIG,
538                         "(%d) failed to find desc ring address.\n",
539                         dev->vid);
540                 return -1;
541         }
542
543         dev = numa_realloc(dev, addr->index);
544         vq = dev->virtqueue[addr->index];
545
546         vq->avail = (struct vring_avail *)(uintptr_t)qva_to_vva(dev,
547                         addr->avail_user_addr);
548         if (vq->avail == 0) {
549                 RTE_LOG(ERR, VHOST_CONFIG,
550                         "(%d) failed to find avail ring address.\n",
551                         dev->vid);
552                 return -1;
553         }
554
555         vq->used = (struct vring_used *)(uintptr_t)qva_to_vva(dev,
556                         addr->used_user_addr);
557         if (vq->used == 0) {
558                 RTE_LOG(ERR, VHOST_CONFIG,
559                         "(%d) failed to find used ring address.\n",
560                         dev->vid);
561                 return -1;
562         }
563
564         if (vq->last_used_idx != vq->used->idx) {
565                 RTE_LOG(WARNING, VHOST_CONFIG,
566                         "last_used_idx (%u) and vq->used->idx (%u) mismatches; "
567                         "some packets maybe resent for Tx and dropped for Rx\n",
568                         vq->last_used_idx, vq->used->idx);
569                 vq->last_used_idx     = vq->used->idx;
570                 vq->last_used_idx_res = vq->used->idx;
571         }
572
573         vq->log_guest_addr = addr->log_guest_addr;
574
575         LOG_DEBUG(VHOST_CONFIG, "(%d) mapped address desc: %p\n",
576                         dev->vid, vq->desc);
577         LOG_DEBUG(VHOST_CONFIG, "(%d) mapped address avail: %p\n",
578                         dev->vid, vq->avail);
579         LOG_DEBUG(VHOST_CONFIG, "(%d) mapped address used: %p\n",
580                         dev->vid, vq->used);
581         LOG_DEBUG(VHOST_CONFIG, "(%d) log_guest_addr: %" PRIx64 "\n",
582                         dev->vid, vq->log_guest_addr);
583
584         return 0;
585 }
586
587 /*
588  * Called from CUSE IOCTL: VHOST_SET_VRING_BASE
589  * The virtio device sends us the available ring last used index.
590  */
591 int
592 vhost_set_vring_base(int vid, struct vhost_vring_state *state)
593 {
594         struct virtio_net *dev;
595
596         dev = get_device(vid);
597         if (dev == NULL)
598                 return -1;
599
600         /* State->index refers to the queue index. The txq is 1, rxq is 0. */
601         dev->virtqueue[state->index]->last_used_idx = state->num;
602         dev->virtqueue[state->index]->last_used_idx_res = state->num;
603
604         return 0;
605 }
606
607 /*
608  * Called from CUSE IOCTL: VHOST_GET_VRING_BASE
609  * We send the virtio device our available ring last used index.
610  */
611 int
612 vhost_get_vring_base(int vid, uint32_t index,
613         struct vhost_vring_state *state)
614 {
615         struct virtio_net *dev;
616
617         dev = get_device(vid);
618         if (dev == NULL)
619                 return -1;
620
621         state->index = index;
622         /* State->index refers to the queue index. The txq is 1, rxq is 0. */
623         state->num = dev->virtqueue[state->index]->last_used_idx;
624
625         return 0;
626 }
627
628
629 /*
630  * Called from CUSE IOCTL: VHOST_SET_VRING_CALL
631  * The virtio device sends an eventfd to interrupt the guest. This fd gets
632  * copied into our process space.
633  */
634 int
635 vhost_set_vring_call(int vid, struct vhost_vring_file *file)
636 {
637         struct virtio_net *dev;
638         struct vhost_virtqueue *vq;
639         uint32_t cur_qp_idx = file->index / VIRTIO_QNUM;
640
641         dev = get_device(vid);
642         if (dev == NULL)
643                 return -1;
644
645         /*
646          * FIXME: VHOST_SET_VRING_CALL is the first per-vring message
647          * we get, so we do vring queue pair allocation here.
648          */
649         if (cur_qp_idx + 1 > dev->virt_qp_nb) {
650                 if (alloc_vring_queue_pair(dev, cur_qp_idx) < 0)
651                         return -1;
652         }
653
654         /* file->index refers to the queue index. The txq is 1, rxq is 0. */
655         vq = dev->virtqueue[file->index];
656         assert(vq != NULL);
657
658         if (vq->callfd >= 0)
659                 close(vq->callfd);
660
661         vq->callfd = file->fd;
662
663         return 0;
664 }
665
666 /*
667  * Called from CUSE IOCTL: VHOST_SET_VRING_KICK
668  * The virtio device sends an eventfd that it can use to notify us.
669  * This fd gets copied into our process space.
670  */
671 int
672 vhost_set_vring_kick(int vid, struct vhost_vring_file *file)
673 {
674         struct virtio_net *dev;
675         struct vhost_virtqueue *vq;
676
677         dev = get_device(vid);
678         if (dev == NULL)
679                 return -1;
680
681         /* file->index refers to the queue index. The txq is 1, rxq is 0. */
682         vq = dev->virtqueue[file->index];
683
684         if (vq->kickfd >= 0)
685                 close(vq->kickfd);
686
687         vq->kickfd = file->fd;
688
689         return 0;
690 }
691
692 /*
693  * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND
694  * To complete device initialisation when the virtio driver is loaded,
695  * we are provided with a valid fd for a tap device (not used by us).
696  * If this happens then we can add the device to a data core.
697  * When the virtio driver is removed we get fd=-1.
698  * At that point we remove the device from the data core.
699  * The device will still exist in the device configuration linked list.
700  */
701 int
702 vhost_set_backend(int vid, struct vhost_vring_file *file)
703 {
704         struct virtio_net *dev;
705
706         dev = get_device(vid);
707         if (dev == NULL)
708                 return -1;
709
710         /* file->index refers to the queue index. The txq is 1, rxq is 0. */
711         dev->virtqueue[file->index]->backend = file->fd;
712
713         /*
714          * If the device isn't already running and both backend fds are set,
715          * we add the device.
716          */
717         if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
718                 if (dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED &&
719                     dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED) {
720                         if (notify_ops->new_device(vid) < 0)
721                                 return -1;
722                         dev->flags |= VIRTIO_DEV_RUNNING;
723                 }
724         } else if (file->fd == VIRTIO_DEV_STOPPED) {
725                 dev->flags &= ~VIRTIO_DEV_RUNNING;
726                 notify_ops->destroy_device(vid);
727         }
728
729         return 0;
730 }
731
732 int
733 rte_vhost_get_numa_node(int vid)
734 {
735 #ifdef RTE_LIBRTE_VHOST_NUMA
736         struct virtio_net *dev = get_device(vid);
737         int numa_node;
738         int ret;
739
740         if (dev == NULL)
741                 return -1;
742
743         ret = get_mempolicy(&numa_node, NULL, 0, dev,
744                             MPOL_F_NODE | MPOL_F_ADDR);
745         if (ret < 0) {
746                 RTE_LOG(ERR, VHOST_CONFIG,
747                         "(%d) failed to query numa node: %d\n", vid, ret);
748                 return -1;
749         }
750
751         return numa_node;
752 #else
753         RTE_SET_USED(vid);
754         return -1;
755 #endif
756 }
757
758 uint32_t
759 rte_vhost_get_queue_num(int vid)
760 {
761         struct virtio_net *dev = get_device(vid);
762
763         if (dev == NULL)
764                 return 0;
765
766         return dev->virt_qp_nb;
767 }
768
769 int
770 rte_vhost_get_ifname(int vid, char *buf, size_t len)
771 {
772         struct virtio_net *dev = get_device(vid);
773
774         if (dev == NULL)
775                 return -1;
776
777         len = RTE_MIN(len, sizeof(dev->ifname));
778
779         strncpy(buf, dev->ifname, len);
780         buf[len - 1] = '\0';
781
782         return 0;
783 }
784
785 uint16_t
786 rte_vhost_avail_entries(int vid, uint16_t queue_id)
787 {
788         struct virtio_net *dev;
789         struct vhost_virtqueue *vq;
790
791         dev = get_device(vid);
792         if (!dev)
793                 return 0;
794
795         vq = dev->virtqueue[queue_id];
796         if (!vq->enabled)
797                 return 0;
798
799         return *(volatile uint16_t *)&vq->avail->idx - vq->last_used_idx_res;
800 }
801
802 int
803 rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)
804 {
805         struct virtio_net *dev = get_device(vid);
806
807         if (dev == NULL)
808                 return -1;
809
810         if (enable) {
811                 RTE_LOG(ERR, VHOST_CONFIG,
812                         "guest notification isn't supported.\n");
813                 return -1;
814         }
815
816         dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
817         return 0;
818 }
819
820 uint64_t rte_vhost_feature_get(void)
821 {
822         return VHOST_FEATURES;
823 }
824
825 int rte_vhost_feature_disable(uint64_t feature_mask)
826 {
827         VHOST_FEATURES = VHOST_FEATURES & ~feature_mask;
828         return 0;
829 }
830
831 int rte_vhost_feature_enable(uint64_t feature_mask)
832 {
833         if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) {
834                 VHOST_FEATURES = VHOST_FEATURES | feature_mask;
835                 return 0;
836         }
837         return -1;
838 }
839
840 /*
841  * Register ops so that we can add/remove device to data core.
842  */
843 int
844 rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
845 {
846         notify_ops = ops;
847
848         return 0;
849 }