net/virtio: improve virtio-user errors handling
[dpdk.git] / drivers / net / virtio / virtio_user / virtio_user_dev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation
3  */
4
5 #include <stdint.h>
6 #include <stdio.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <sys/mman.h>
11 #include <unistd.h>
12 #include <sys/eventfd.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15
16 #include <rte_string_fns.h>
17 #include <rte_eal_memconfig.h>
18
19 #include "vhost.h"
20 #include "virtio_user_dev.h"
21 #include "../virtio_ethdev.h"
22
23 #define VIRTIO_USER_MEM_EVENT_CLB_NAME "virtio_user_mem_event_clb"
24
25 const char * const virtio_user_backend_strings[] = {
26         [VIRTIO_USER_BACKEND_UNKNOWN] = "VIRTIO_USER_BACKEND_UNKNOWN",
27         [VIRTIO_USER_BACKEND_VHOST_USER] = "VHOST_USER",
28         [VIRTIO_USER_BACKEND_VHOST_KERNEL] = "VHOST_NET",
29         [VIRTIO_USER_BACKEND_VHOST_VDPA] = "VHOST_VDPA",
30 };
31
32 static int
33 virtio_user_create_queue(struct virtio_user_dev *dev, uint32_t queue_sel)
34 {
35         /* Of all per virtqueue MSGs, make sure VHOST_SET_VRING_CALL come
36          * firstly because vhost depends on this msg to allocate virtqueue
37          * pair.
38          */
39         struct vhost_vring_file file;
40         int ret;
41
42         file.index = queue_sel;
43         file.fd = dev->callfds[queue_sel];
44         ret = dev->ops->set_vring_call(dev, &file);
45         if (ret < 0) {
46                 PMD_INIT_LOG(ERR, "(%s) Failed to create queue %u\n", dev->path, queue_sel);
47                 return -1;
48         }
49
50         return 0;
51 }
52
53 static int
54 virtio_user_kick_queue(struct virtio_user_dev *dev, uint32_t queue_sel)
55 {
56         int ret;
57         struct vhost_vring_file file;
58         struct vhost_vring_state state;
59         struct vring *vring = &dev->vrings[queue_sel];
60         struct vring_packed *pq_vring = &dev->packed_vrings[queue_sel];
61         struct vhost_vring_addr addr = {
62                 .index = queue_sel,
63                 .log_guest_addr = 0,
64                 .flags = 0, /* disable log */
65         };
66
67         if (dev->features & (1ULL << VIRTIO_F_RING_PACKED)) {
68                 addr.desc_user_addr =
69                         (uint64_t)(uintptr_t)pq_vring->desc;
70                 addr.avail_user_addr =
71                         (uint64_t)(uintptr_t)pq_vring->driver;
72                 addr.used_user_addr =
73                         (uint64_t)(uintptr_t)pq_vring->device;
74         } else {
75                 addr.desc_user_addr = (uint64_t)(uintptr_t)vring->desc;
76                 addr.avail_user_addr = (uint64_t)(uintptr_t)vring->avail;
77                 addr.used_user_addr = (uint64_t)(uintptr_t)vring->used;
78         }
79
80         state.index = queue_sel;
81         state.num = vring->num;
82         ret = dev->ops->set_vring_num(dev, &state);
83         if (ret < 0)
84                 goto err;
85
86         state.index = queue_sel;
87         state.num = 0; /* no reservation */
88         if (dev->features & (1ULL << VIRTIO_F_RING_PACKED))
89                 state.num |= (1 << 15);
90         ret = dev->ops->set_vring_base(dev, &state);
91         if (ret < 0)
92                 goto err;
93
94         ret = dev->ops->set_vring_addr(dev, &addr);
95         if (ret < 0)
96                 goto err;
97
98         /* Of all per virtqueue MSGs, make sure VHOST_USER_SET_VRING_KICK comes
99          * lastly because vhost depends on this msg to judge if
100          * virtio is ready.
101          */
102         file.index = queue_sel;
103         file.fd = dev->kickfds[queue_sel];
104         ret = dev->ops->set_vring_kick(dev, &file);
105         if (ret < 0)
106                 goto err;
107
108         return 0;
109 err:
110         PMD_INIT_LOG(ERR, "(%s) Failed to kick queue %u\n", dev->path, queue_sel);
111
112         return -1;
113 }
114
115 static int
116 virtio_user_queue_setup(struct virtio_user_dev *dev,
117                         int (*fn)(struct virtio_user_dev *, uint32_t))
118 {
119         uint32_t i, queue_sel;
120
121         for (i = 0; i < dev->max_queue_pairs; ++i) {
122                 queue_sel = 2 * i + VTNET_SQ_RQ_QUEUE_IDX;
123                 if (fn(dev, queue_sel) < 0) {
124                         PMD_DRV_LOG(ERR, "(%s) setup rx vq %u failed", dev->path, i);
125                         return -1;
126                 }
127         }
128         for (i = 0; i < dev->max_queue_pairs; ++i) {
129                 queue_sel = 2 * i + VTNET_SQ_TQ_QUEUE_IDX;
130                 if (fn(dev, queue_sel) < 0) {
131                         PMD_DRV_LOG(INFO, "(%s) setup tx vq %u failed", dev->path, i);
132                         return -1;
133                 }
134         }
135
136         return 0;
137 }
138
139 int
140 virtio_user_dev_set_features(struct virtio_user_dev *dev)
141 {
142         uint64_t features;
143         int ret = -1;
144
145         pthread_mutex_lock(&dev->mutex);
146
147         if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER &&
148                         dev->vhostfd < 0)
149                 goto error;
150
151         /* Step 0: tell vhost to create queues */
152         if (virtio_user_queue_setup(dev, virtio_user_create_queue) < 0)
153                 goto error;
154
155         features = dev->features;
156
157         /* Strip VIRTIO_NET_F_MAC, as MAC address is handled in vdev init */
158         features &= ~(1ull << VIRTIO_NET_F_MAC);
159         /* Strip VIRTIO_NET_F_CTRL_VQ, as devices do not really need to know */
160         features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ);
161         features &= ~(1ull << VIRTIO_NET_F_STATUS);
162         ret = dev->ops->set_features(dev, features);
163         if (ret < 0)
164                 goto error;
165         PMD_DRV_LOG(INFO, "(%s) set features: 0x%" PRIx64, dev->path, features);
166 error:
167         pthread_mutex_unlock(&dev->mutex);
168
169         return ret;
170 }
171
172 int
173 virtio_user_start_device(struct virtio_user_dev *dev)
174 {
175         int ret;
176
177         /*
178          * XXX workaround!
179          *
180          * We need to make sure that the locks will be
181          * taken in the correct order to avoid deadlocks.
182          *
183          * Before releasing this lock, this thread should
184          * not trigger any memory hotplug events.
185          *
186          * This is a temporary workaround, and should be
187          * replaced when we get proper supports from the
188          * memory subsystem in the future.
189          */
190         rte_mcfg_mem_read_lock();
191         pthread_mutex_lock(&dev->mutex);
192
193         /* Vhost-user client not connected yet, will start later */
194         if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER &&
195                         dev->vhostfd < 0)
196                 goto out;
197
198         /* Step 2: share memory regions */
199         ret = dev->ops->set_memory_table(dev);
200         if (ret < 0)
201                 goto error;
202
203         /* Step 3: kick queues */
204         ret = virtio_user_queue_setup(dev, virtio_user_kick_queue);
205         if (ret < 0)
206                 goto error;
207
208         /* Step 4: enable queues
209          * we enable the 1st queue pair by default.
210          */
211         ret = dev->ops->enable_qp(dev, 0, 1);
212         if (ret < 0)
213                 goto error;
214
215         dev->started = true;
216 out:
217         pthread_mutex_unlock(&dev->mutex);
218         rte_mcfg_mem_read_unlock();
219
220         return 0;
221 error:
222         pthread_mutex_unlock(&dev->mutex);
223         rte_mcfg_mem_read_unlock();
224
225         PMD_INIT_LOG(ERR, "(%s) Failed to start device\n", dev->path);
226
227         /* TODO: free resource here or caller to check */
228         return -1;
229 }
230
231 int virtio_user_stop_device(struct virtio_user_dev *dev)
232 {
233         struct vhost_vring_state state;
234         uint32_t i;
235         int ret;
236
237         pthread_mutex_lock(&dev->mutex);
238         if (!dev->started)
239                 goto out;
240
241         for (i = 0; i < dev->max_queue_pairs; ++i) {
242                 ret = dev->ops->enable_qp(dev, i, 0);
243                 if (ret < 0)
244                         goto err;
245         }
246
247         /* Stop the backend. */
248         for (i = 0; i < dev->max_queue_pairs * 2; ++i) {
249                 state.index = i;
250                 ret = dev->ops->get_vring_base(dev, &state);
251                 if (ret < 0) {
252                         PMD_DRV_LOG(ERR, "(%s) get_vring_base failed, index=%u", dev->path, i);
253                         goto err;
254                 }
255         }
256
257         dev->started = false;
258
259 out:
260         pthread_mutex_unlock(&dev->mutex);
261
262         return 0;
263 err:
264         pthread_mutex_unlock(&dev->mutex);
265
266         PMD_INIT_LOG(ERR, "(%s) Failed to stop device\n", dev->path);
267
268         return -1;
269 }
270
271 static inline void
272 parse_mac(struct virtio_user_dev *dev, const char *mac)
273 {
274         struct rte_ether_addr tmp;
275
276         if (!mac)
277                 return;
278
279         if (rte_ether_unformat_addr(mac, &tmp) == 0) {
280                 memcpy(dev->mac_addr, &tmp, RTE_ETHER_ADDR_LEN);
281                 dev->mac_specified = 1;
282         } else {
283                 /* ignore the wrong mac, use random mac */
284                 PMD_DRV_LOG(ERR, "wrong format of mac: %s", mac);
285         }
286 }
287
288 static int
289 virtio_user_dev_init_notify(struct virtio_user_dev *dev)
290 {
291         uint32_t i, j;
292         int callfd;
293         int kickfd;
294
295         for (i = 0; i < VIRTIO_MAX_VIRTQUEUES; ++i) {
296                 if (i >= dev->max_queue_pairs * 2) {
297                         dev->kickfds[i] = -1;
298                         dev->callfds[i] = -1;
299                         continue;
300                 }
301
302                 /* May use invalid flag, but some backend uses kickfd and
303                  * callfd as criteria to judge if dev is alive. so finally we
304                  * use real event_fd.
305                  */
306                 callfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
307                 if (callfd < 0) {
308                         PMD_DRV_LOG(ERR, "(%s) callfd error, %s", dev->path, strerror(errno));
309                         break;
310                 }
311                 kickfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
312                 if (kickfd < 0) {
313                         close(callfd);
314                         PMD_DRV_LOG(ERR, "(%s) kickfd error, %s", dev->path, strerror(errno));
315                         break;
316                 }
317                 dev->callfds[i] = callfd;
318                 dev->kickfds[i] = kickfd;
319         }
320
321         if (i < VIRTIO_MAX_VIRTQUEUES) {
322                 for (j = 0; j < i; ++j) {
323                         close(dev->callfds[j]);
324                         close(dev->kickfds[j]);
325                 }
326
327                 return -1;
328         }
329
330         return 0;
331 }
332
333 static int
334 virtio_user_fill_intr_handle(struct virtio_user_dev *dev)
335 {
336         uint32_t i;
337         struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
338
339         if (!eth_dev->intr_handle) {
340                 eth_dev->intr_handle = malloc(sizeof(*eth_dev->intr_handle));
341                 if (!eth_dev->intr_handle) {
342                         PMD_DRV_LOG(ERR, "(%s) failed to allocate intr_handle", dev->path);
343                         return -1;
344                 }
345                 memset(eth_dev->intr_handle, 0, sizeof(*eth_dev->intr_handle));
346         }
347
348         for (i = 0; i < dev->max_queue_pairs; ++i)
349                 eth_dev->intr_handle->efds[i] = dev->callfds[i];
350         eth_dev->intr_handle->nb_efd = dev->max_queue_pairs;
351         eth_dev->intr_handle->max_intr = dev->max_queue_pairs + 1;
352         eth_dev->intr_handle->type = RTE_INTR_HANDLE_VDEV;
353         /* For virtio vdev, no need to read counter for clean */
354         eth_dev->intr_handle->efd_counter_size = 0;
355         eth_dev->intr_handle->fd = -1;
356         if (dev->vhostfd >= 0)
357                 eth_dev->intr_handle->fd = dev->vhostfd;
358         else if (dev->is_server)
359                 eth_dev->intr_handle->fd = dev->listenfd;
360
361         return 0;
362 }
363
364 static void
365 virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
366                          const void *addr,
367                          size_t len __rte_unused,
368                          void *arg)
369 {
370         struct virtio_user_dev *dev = arg;
371         struct rte_memseg_list *msl;
372         uint16_t i;
373         int ret = 0;
374
375         /* ignore externally allocated memory */
376         msl = rte_mem_virt2memseg_list(addr);
377         if (msl->external)
378                 return;
379
380         pthread_mutex_lock(&dev->mutex);
381
382         if (dev->started == false)
383                 goto exit;
384
385         /* Step 1: pause the active queues */
386         for (i = 0; i < dev->queue_pairs; i++) {
387                 ret = dev->ops->enable_qp(dev, i, 0);
388                 if (ret < 0)
389                         goto exit;
390         }
391
392         /* Step 2: update memory regions */
393         ret = dev->ops->set_memory_table(dev);
394         if (ret < 0)
395                 goto exit;
396
397         /* Step 3: resume the active queues */
398         for (i = 0; i < dev->queue_pairs; i++) {
399                 ret = dev->ops->enable_qp(dev, i, 1);
400                 if (ret < 0)
401                         goto exit;
402         }
403
404 exit:
405         pthread_mutex_unlock(&dev->mutex);
406
407         if (ret < 0)
408                 PMD_DRV_LOG(ERR, "(%s) Failed to update memory table\n", dev->path);
409 }
410
411 static int
412 virtio_user_dev_setup(struct virtio_user_dev *dev)
413 {
414         uint32_t q;
415
416         dev->vhostfd = -1;
417         dev->vhostfds = NULL;
418         dev->tapfds = NULL;
419
420         if (dev->is_server) {
421                 if (dev->backend_type != VIRTIO_USER_BACKEND_VHOST_USER) {
422                         PMD_DRV_LOG(ERR, "Server mode only supports vhost-user!");
423                         return -1;
424                 }
425                 dev->ops = &virtio_ops_user;
426         } else {
427                 if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER) {
428                         dev->ops = &virtio_ops_user;
429                 } else if (dev->backend_type ==
430                                         VIRTIO_USER_BACKEND_VHOST_KERNEL) {
431                         dev->ops = &virtio_ops_kernel;
432
433                         dev->vhostfds = malloc(dev->max_queue_pairs *
434                                                sizeof(int));
435                         dev->tapfds = malloc(dev->max_queue_pairs *
436                                              sizeof(int));
437                         if (!dev->vhostfds || !dev->tapfds) {
438                                 PMD_INIT_LOG(ERR, "(%s) Failed to allocate FDs", dev->path);
439                                 return -1;
440                         }
441
442                         for (q = 0; q < dev->max_queue_pairs; ++q) {
443                                 dev->vhostfds[q] = -1;
444                                 dev->tapfds[q] = -1;
445                         }
446                 } else if (dev->backend_type ==
447                                 VIRTIO_USER_BACKEND_VHOST_VDPA) {
448                         dev->ops = &virtio_ops_vdpa;
449                 } else {
450                         PMD_DRV_LOG(ERR, "(%s) Unknown backend type", dev->path);
451                         return -1;
452                 }
453         }
454
455         if (dev->ops->setup(dev) < 0) {
456                 PMD_INIT_LOG(ERR, "(%s) Failed to setup backend\n", dev->path);
457                 return -1;
458         }
459
460         if (virtio_user_dev_init_notify(dev) < 0) {
461                 PMD_INIT_LOG(ERR, "(%s) Failed to init notifiers\n", dev->path);
462                 return -1;
463         }
464
465         if (virtio_user_fill_intr_handle(dev) < 0) {
466                 PMD_INIT_LOG(ERR, "(%s) Failed to init interrupt handler\n", dev->path);
467                 return -1;
468         }
469
470         return 0;
471 }
472
473 /* Use below macro to filter features from vhost backend */
474 #define VIRTIO_USER_SUPPORTED_FEATURES                  \
475         (1ULL << VIRTIO_NET_F_MAC               |       \
476          1ULL << VIRTIO_NET_F_STATUS            |       \
477          1ULL << VIRTIO_NET_F_MQ                |       \
478          1ULL << VIRTIO_NET_F_CTRL_MAC_ADDR     |       \
479          1ULL << VIRTIO_NET_F_CTRL_VQ           |       \
480          1ULL << VIRTIO_NET_F_CTRL_RX           |       \
481          1ULL << VIRTIO_NET_F_CTRL_VLAN         |       \
482          1ULL << VIRTIO_NET_F_CSUM              |       \
483          1ULL << VIRTIO_NET_F_HOST_TSO4         |       \
484          1ULL << VIRTIO_NET_F_HOST_TSO6         |       \
485          1ULL << VIRTIO_NET_F_MRG_RXBUF         |       \
486          1ULL << VIRTIO_RING_F_INDIRECT_DESC    |       \
487          1ULL << VIRTIO_NET_F_GUEST_CSUM        |       \
488          1ULL << VIRTIO_NET_F_GUEST_TSO4        |       \
489          1ULL << VIRTIO_NET_F_GUEST_TSO6        |       \
490          1ULL << VIRTIO_F_IN_ORDER              |       \
491          1ULL << VIRTIO_F_VERSION_1             |       \
492          1ULL << VIRTIO_F_RING_PACKED           |       \
493          1ULL << VHOST_USER_F_PROTOCOL_FEATURES)
494
495 #define VHOST_USER_SUPPORTED_PROTOCOL_FEATURES          \
496         (1ULL << VHOST_USER_PROTOCOL_F_MQ |             \
497          1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK |      \
498          1ULL << VHOST_USER_PROTOCOL_F_STATUS)
499
500 #define VHOST_VDPA_SUPPORTED_PROTOCOL_FEATURES          \
501         (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2   |       \
502         1ULL << VHOST_BACKEND_F_IOTLB_BATCH)
503 int
504 virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
505                      int cq, int queue_size, const char *mac, char **ifname,
506                      int server, int mrg_rxbuf, int in_order, int packed_vq,
507                      enum virtio_user_backend_type backend_type)
508 {
509         uint64_t protocol_features = 0;
510
511         pthread_mutex_init(&dev->mutex, NULL);
512         strlcpy(dev->path, path, PATH_MAX);
513         dev->started = 0;
514         dev->max_queue_pairs = queues;
515         dev->queue_pairs = 1; /* mq disabled by default */
516         dev->queue_size = queue_size;
517         dev->is_server = server;
518         dev->mac_specified = 0;
519         dev->frontend_features = 0;
520         dev->unsupported_features = ~VIRTIO_USER_SUPPORTED_FEATURES;
521         dev->backend_type = backend_type;
522
523         if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER)
524                 dev->protocol_features = VHOST_USER_SUPPORTED_PROTOCOL_FEATURES;
525         else if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_VDPA)
526                 dev->protocol_features = VHOST_VDPA_SUPPORTED_PROTOCOL_FEATURES;
527
528         parse_mac(dev, mac);
529
530         if (*ifname) {
531                 dev->ifname = *ifname;
532                 *ifname = NULL;
533         }
534
535         if (virtio_user_dev_setup(dev) < 0) {
536                 PMD_INIT_LOG(ERR, "(%s) backend set up fails", dev->path);
537                 return -1;
538         }
539
540         if (dev->backend_type != VIRTIO_USER_BACKEND_VHOST_USER)
541                 dev->unsupported_features |=
542                         (1ULL << VHOST_USER_F_PROTOCOL_FEATURES);
543
544         if (!dev->is_server) {
545                 if (dev->ops->set_owner(dev) < 0) {
546                         PMD_INIT_LOG(ERR, "(%s) Failed to set backend owner", dev->path);
547                         return -1;
548                 }
549
550                 if (dev->ops->get_features(dev, &dev->device_features) < 0) {
551                         PMD_INIT_LOG(ERR, "(%s) Failed to get backend features", dev->path);
552                         return -1;
553                 }
554
555
556                 if ((dev->device_features & (1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) ||
557                                 (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_VDPA)) {
558                         if (dev->ops->get_protocol_features(dev, &protocol_features)) {
559                                 PMD_INIT_LOG(ERR, "(%s) Failed to get backend protocol features",
560                                                 dev->path);
561                                 return -1;
562                         }
563
564                         dev->protocol_features &= protocol_features;
565
566                         if (dev->ops->set_protocol_features(dev, dev->protocol_features)) {
567                                 PMD_INIT_LOG(ERR, "(%s) Failed to set backend protocol features",
568                                                 dev->path);
569                                 return -1;
570                         }
571
572                         if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ)))
573                                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
574                 }
575         } else {
576                 /* We just pretend vhost-user can support all these features.
577                  * Note that this could be problematic that if some feature is
578                  * negotiated but not supported by the vhost-user which comes
579                  * later.
580                  */
581                 dev->device_features = VIRTIO_USER_SUPPORTED_FEATURES;
582
583                 /* We cannot assume VHOST_USER_PROTOCOL_F_STATUS is supported
584                  * until it's negotiated
585                  */
586                 dev->protocol_features &=
587                         ~(1ULL << VHOST_USER_PROTOCOL_F_STATUS);
588         }
589
590
591
592         if (!mrg_rxbuf)
593                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MRG_RXBUF);
594
595         if (!in_order)
596                 dev->unsupported_features |= (1ull << VIRTIO_F_IN_ORDER);
597
598         if (!packed_vq)
599                 dev->unsupported_features |= (1ull << VIRTIO_F_RING_PACKED);
600
601         if (dev->mac_specified)
602                 dev->frontend_features |= (1ull << VIRTIO_NET_F_MAC);
603         else
604                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MAC);
605
606         if (cq) {
607                 /* device does not really need to know anything about CQ,
608                  * so if necessary, we just claim to support CQ
609                  */
610                 dev->frontend_features |= (1ull << VIRTIO_NET_F_CTRL_VQ);
611         } else {
612                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_VQ);
613                 /* Also disable features that depend on VIRTIO_NET_F_CTRL_VQ */
614                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_RX);
615                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_CTRL_VLAN);
616                 dev->unsupported_features |=
617                         (1ull << VIRTIO_NET_F_GUEST_ANNOUNCE);
618                 dev->unsupported_features |= (1ull << VIRTIO_NET_F_MQ);
619                 dev->unsupported_features |=
620                         (1ull << VIRTIO_NET_F_CTRL_MAC_ADDR);
621         }
622
623         /* The backend will not report this feature, we add it explicitly */
624         if (dev->backend_type == VIRTIO_USER_BACKEND_VHOST_USER)
625                 dev->frontend_features |= (1ull << VIRTIO_NET_F_STATUS);
626
627         /*
628          * Device features =
629          *     (frontend_features | backend_features) & ~unsupported_features;
630          */
631         dev->device_features |= dev->frontend_features;
632         dev->device_features &= ~dev->unsupported_features;
633
634         if (rte_mem_event_callback_register(VIRTIO_USER_MEM_EVENT_CLB_NAME,
635                                 virtio_user_mem_event_cb, dev)) {
636                 if (rte_errno != ENOTSUP) {
637                         PMD_INIT_LOG(ERR, "(%s) Failed to register mem event callback\n",
638                                         dev->path);
639                         return -1;
640                 }
641         }
642
643         return 0;
644 }
645
646 void
647 virtio_user_dev_uninit(struct virtio_user_dev *dev)
648 {
649         uint32_t i;
650
651         virtio_user_stop_device(dev);
652
653         rte_mem_event_callback_unregister(VIRTIO_USER_MEM_EVENT_CLB_NAME, dev);
654
655         for (i = 0; i < dev->max_queue_pairs * 2; ++i) {
656                 close(dev->callfds[i]);
657                 close(dev->kickfds[i]);
658         }
659
660         if (dev->vhostfd >= 0)
661                 close(dev->vhostfd);
662
663         if (dev->is_server && dev->listenfd >= 0) {
664                 close(dev->listenfd);
665                 dev->listenfd = -1;
666         }
667
668         if (dev->vhostfds) {
669                 for (i = 0; i < dev->max_queue_pairs; ++i) {
670                         close(dev->vhostfds[i]);
671                         if (dev->tapfds[i] >= 0)
672                                 close(dev->tapfds[i]);
673                 }
674                 free(dev->vhostfds);
675                 free(dev->tapfds);
676         }
677
678         free(dev->ifname);
679
680         if (dev->is_server)
681                 unlink(dev->path);
682 }
683
684 uint8_t
685 virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs)
686 {
687         uint16_t i;
688         uint8_t ret = 0;
689
690         if (q_pairs > dev->max_queue_pairs) {
691                 PMD_INIT_LOG(ERR, "(%s) multi-q config %u, but only %u supported",
692                              dev->path, q_pairs, dev->max_queue_pairs);
693                 return -1;
694         }
695
696         /* Server mode can't enable queue pairs if vhostfd is invalid,
697          * always return 0 in this case.
698          */
699         if (!dev->is_server || dev->vhostfd >= 0) {
700                 for (i = 0; i < q_pairs; ++i)
701                         ret |= dev->ops->enable_qp(dev, i, 1);
702                 for (i = q_pairs; i < dev->max_queue_pairs; ++i)
703                         ret |= dev->ops->enable_qp(dev, i, 0);
704         }
705         dev->queue_pairs = q_pairs;
706
707         return ret;
708 }
709
710 static uint32_t
711 virtio_user_handle_ctrl_msg(struct virtio_user_dev *dev, struct vring *vring,
712                             uint16_t idx_hdr)
713 {
714         struct virtio_net_ctrl_hdr *hdr;
715         virtio_net_ctrl_ack status = ~0;
716         uint16_t i, idx_data, idx_status;
717         uint32_t n_descs = 0;
718
719         /* locate desc for header, data, and status */
720         idx_data = vring->desc[idx_hdr].next;
721         n_descs++;
722
723         i = idx_data;
724         while (vring->desc[i].flags == VRING_DESC_F_NEXT) {
725                 i = vring->desc[i].next;
726                 n_descs++;
727         }
728
729         /* locate desc for status */
730         idx_status = i;
731         n_descs++;
732
733         hdr = (void *)(uintptr_t)vring->desc[idx_hdr].addr;
734         if (hdr->class == VIRTIO_NET_CTRL_MQ &&
735             hdr->cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
736                 uint16_t queues;
737
738                 queues = *(uint16_t *)(uintptr_t)vring->desc[idx_data].addr;
739                 status = virtio_user_handle_mq(dev, queues);
740         } else if (hdr->class == VIRTIO_NET_CTRL_RX  ||
741                    hdr->class == VIRTIO_NET_CTRL_MAC ||
742                    hdr->class == VIRTIO_NET_CTRL_VLAN) {
743                 status = 0;
744         }
745
746         /* Update status */
747         *(virtio_net_ctrl_ack *)(uintptr_t)vring->desc[idx_status].addr = status;
748
749         return n_descs;
750 }
751
752 static inline int
753 desc_is_avail(struct vring_packed_desc *desc, bool wrap_counter)
754 {
755         uint16_t flags = __atomic_load_n(&desc->flags, __ATOMIC_ACQUIRE);
756
757         return wrap_counter == !!(flags & VRING_PACKED_DESC_F_AVAIL) &&
758                 wrap_counter != !!(flags & VRING_PACKED_DESC_F_USED);
759 }
760
761 static uint32_t
762 virtio_user_handle_ctrl_msg_packed(struct virtio_user_dev *dev,
763                                    struct vring_packed *vring,
764                                    uint16_t idx_hdr)
765 {
766         struct virtio_net_ctrl_hdr *hdr;
767         virtio_net_ctrl_ack status = ~0;
768         uint16_t idx_data, idx_status;
769         /* initialize to one, header is first */
770         uint32_t n_descs = 1;
771
772         /* locate desc for header, data, and status */
773         idx_data = idx_hdr + 1;
774         if (idx_data >= dev->queue_size)
775                 idx_data -= dev->queue_size;
776
777         n_descs++;
778
779         idx_status = idx_data;
780         while (vring->desc[idx_status].flags & VRING_DESC_F_NEXT) {
781                 idx_status++;
782                 if (idx_status >= dev->queue_size)
783                         idx_status -= dev->queue_size;
784                 n_descs++;
785         }
786
787         hdr = (void *)(uintptr_t)vring->desc[idx_hdr].addr;
788         if (hdr->class == VIRTIO_NET_CTRL_MQ &&
789             hdr->cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) {
790                 uint16_t queues;
791
792                 queues = *(uint16_t *)(uintptr_t)
793                                 vring->desc[idx_data].addr;
794                 status = virtio_user_handle_mq(dev, queues);
795         } else if (hdr->class == VIRTIO_NET_CTRL_RX  ||
796                    hdr->class == VIRTIO_NET_CTRL_MAC ||
797                    hdr->class == VIRTIO_NET_CTRL_VLAN) {
798                 status = 0;
799         }
800
801         /* Update status */
802         *(virtio_net_ctrl_ack *)(uintptr_t)
803                 vring->desc[idx_status].addr = status;
804
805         /* Update used descriptor */
806         vring->desc[idx_hdr].id = vring->desc[idx_status].id;
807         vring->desc[idx_hdr].len = sizeof(status);
808
809         return n_descs;
810 }
811
812 void
813 virtio_user_handle_cq_packed(struct virtio_user_dev *dev, uint16_t queue_idx)
814 {
815         struct virtio_user_queue *vq = &dev->packed_queues[queue_idx];
816         struct vring_packed *vring = &dev->packed_vrings[queue_idx];
817         uint16_t n_descs, flags;
818
819         /* Perform a load-acquire barrier in desc_is_avail to
820          * enforce the ordering between desc flags and desc
821          * content.
822          */
823         while (desc_is_avail(&vring->desc[vq->used_idx],
824                              vq->used_wrap_counter)) {
825
826                 n_descs = virtio_user_handle_ctrl_msg_packed(dev, vring,
827                                 vq->used_idx);
828
829                 flags = VRING_DESC_F_WRITE;
830                 if (vq->used_wrap_counter)
831                         flags |= VRING_PACKED_DESC_F_AVAIL_USED;
832
833                 __atomic_store_n(&vring->desc[vq->used_idx].flags, flags,
834                                  __ATOMIC_RELEASE);
835
836                 vq->used_idx += n_descs;
837                 if (vq->used_idx >= dev->queue_size) {
838                         vq->used_idx -= dev->queue_size;
839                         vq->used_wrap_counter ^= 1;
840                 }
841         }
842 }
843
844 void
845 virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx)
846 {
847         uint16_t avail_idx, desc_idx;
848         struct vring_used_elem *uep;
849         uint32_t n_descs;
850         struct vring *vring = &dev->vrings[queue_idx];
851
852         /* Consume avail ring, using used ring idx as first one */
853         while (__atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)
854                != vring->avail->idx) {
855                 avail_idx = __atomic_load_n(&vring->used->idx, __ATOMIC_RELAXED)
856                             & (vring->num - 1);
857                 desc_idx = vring->avail->ring[avail_idx];
858
859                 n_descs = virtio_user_handle_ctrl_msg(dev, vring, desc_idx);
860
861                 /* Update used ring */
862                 uep = &vring->used->ring[avail_idx];
863                 uep->id = desc_idx;
864                 uep->len = n_descs;
865
866                 __atomic_add_fetch(&vring->used->idx, 1, __ATOMIC_RELAXED);
867         }
868 }
869
870 int
871 virtio_user_dev_set_status(struct virtio_user_dev *dev, uint8_t status)
872 {
873         int ret;
874
875         pthread_mutex_lock(&dev->mutex);
876         dev->status = status;
877         ret = dev->ops->set_status(dev, status);
878         if (ret && ret != -ENOTSUP)
879                 PMD_INIT_LOG(ERR, "(%s) Failed to set backend status\n", dev->path);
880
881         pthread_mutex_unlock(&dev->mutex);
882         return ret;
883 }
884
885 int
886 virtio_user_dev_update_status(struct virtio_user_dev *dev)
887 {
888         int ret;
889         uint8_t status;
890
891         pthread_mutex_lock(&dev->mutex);
892
893         ret = dev->ops->get_status(dev, &status);
894         if (!ret) {
895                 dev->status = status;
896                 PMD_INIT_LOG(DEBUG, "Updated Device Status(0x%08x):\n"
897                         "\t-RESET: %u\n"
898                         "\t-ACKNOWLEDGE: %u\n"
899                         "\t-DRIVER: %u\n"
900                         "\t-DRIVER_OK: %u\n"
901                         "\t-FEATURES_OK: %u\n"
902                         "\t-DEVICE_NEED_RESET: %u\n"
903                         "\t-FAILED: %u\n",
904                         dev->status,
905                         (dev->status == VIRTIO_CONFIG_STATUS_RESET),
906                         !!(dev->status & VIRTIO_CONFIG_STATUS_ACK),
907                         !!(dev->status & VIRTIO_CONFIG_STATUS_DRIVER),
908                         !!(dev->status & VIRTIO_CONFIG_STATUS_DRIVER_OK),
909                         !!(dev->status & VIRTIO_CONFIG_STATUS_FEATURES_OK),
910                         !!(dev->status & VIRTIO_CONFIG_STATUS_DEV_NEED_RESET),
911                         !!(dev->status & VIRTIO_CONFIG_STATUS_FAILED));
912         } else if (ret != -ENOTSUP) {
913                 PMD_INIT_LOG(ERR, "(%s) Failed to get backend status\n", dev->path);
914         }
915
916         pthread_mutex_unlock(&dev->mutex);
917         return ret;
918 }