dpdk/drivers/net/virtio/virtio_user_ethdev.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2016 Intel Corporation
   3 */
   4
   5#include <stdint.h>
   6#include <sys/types.h>
   7#include <unistd.h>
   8#include <fcntl.h>
   9#include <linux/major.h>
  10#include <sys/stat.h>
  11#include <sys/sysmacros.h>
  12#include <sys/socket.h>
  13
  14#include <rte_malloc.h>
  15#include <rte_kvargs.h>
  16#include <ethdev_vdev.h>
  17#include <rte_bus_vdev.h>
  18#include <rte_alarm.h>
  19#include <rte_cycles.h>
  20
  21#include "virtio_ethdev.h"
  22#include "virtio_logs.h"
  23#include "virtio.h"
  24#include "virtqueue.h"
  25#include "virtio_rxtx.h"
  26#include "virtio_user/virtio_user_dev.h"
  27#include "virtio_user/vhost.h"
  28
  29#define virtio_user_get_dev(hwp) container_of(hwp, struct virtio_user_dev, hw)
  30
  31static void
  32virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
  33                     void *dst, int length)
  34{
  35        int i;
  36        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
  37
  38        if (offset == offsetof(struct virtio_net_config, mac) &&
  39            length == RTE_ETHER_ADDR_LEN) {
  40                for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i)
  41                        ((uint8_t *)dst)[i] = dev->mac_addr[i];
  42                return;
  43        }
  44
  45        if (offset == offsetof(struct virtio_net_config, status)) {
  46                virtio_user_dev_update_link_state(dev);
  47
  48                *(uint16_t *)dst = dev->net_status;
  49        }
  50
  51        if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs))
  52                *(uint16_t *)dst = dev->max_queue_pairs;
  53}
  54
  55static void
  56virtio_user_write_dev_config(struct virtio_hw *hw, size_t offset,
  57                      const void *src, int length)
  58{
  59        int i;
  60        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
  61
  62        if ((offset == offsetof(struct virtio_net_config, mac)) &&
  63            (length == RTE_ETHER_ADDR_LEN))
  64                for (i = 0; i < RTE_ETHER_ADDR_LEN; ++i)
  65                        dev->mac_addr[i] = ((const uint8_t *)src)[i];
  66        else
  67                PMD_DRV_LOG(ERR, "not supported offset=%zu, len=%d",
  68                            offset, length);
  69}
  70
  71static void
  72virtio_user_reset(struct virtio_hw *hw)
  73{
  74        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
  75
  76        if (dev->status & VIRTIO_CONFIG_STATUS_DRIVER_OK)
  77                virtio_user_stop_device(dev);
  78}
  79
  80static void
  81virtio_user_set_status(struct virtio_hw *hw, uint8_t status)
  82{
  83        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
  84        uint8_t old_status = dev->status;
  85
  86        if (status & VIRTIO_CONFIG_STATUS_FEATURES_OK &&
  87                        ~old_status & VIRTIO_CONFIG_STATUS_FEATURES_OK)
  88                virtio_user_dev_set_features(dev);
  89        if (status & VIRTIO_CONFIG_STATUS_DRIVER_OK)
  90                virtio_user_start_device(dev);
  91        else if (status == VIRTIO_CONFIG_STATUS_RESET)
  92                virtio_user_reset(hw);
  93
  94        virtio_user_dev_set_status(dev, status);
  95}
  96
  97static uint8_t
  98virtio_user_get_status(struct virtio_hw *hw)
  99{
 100        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 101
 102        virtio_user_dev_update_status(dev);
 103
 104        return dev->status;
 105}
 106
 107static uint64_t
 108virtio_user_get_features(struct virtio_hw *hw)
 109{
 110        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 111
 112        /* unmask feature bits defined in vhost user protocol */
 113        return dev->device_features & VIRTIO_PMD_SUPPORTED_GUEST_FEATURES;
 114}
 115
 116static void
 117virtio_user_set_features(struct virtio_hw *hw, uint64_t features)
 118{
 119        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 120
 121        dev->features = features & dev->device_features;
 122}
 123
 124static int
 125virtio_user_features_ok(struct virtio_hw *hw __rte_unused)
 126{
 127        return 0;
 128}
 129
 130static uint8_t
 131virtio_user_get_isr(struct virtio_hw *hw __rte_unused)
 132{
 133        /* rxq interrupts and config interrupt are separated in virtio-user,
 134         * here we only report config change.
 135         */
 136        return VIRTIO_ISR_CONFIG;
 137}
 138
 139static uint16_t
 140virtio_user_set_config_irq(struct virtio_hw *hw __rte_unused,
 141                    uint16_t vec __rte_unused)
 142{
 143        return 0;
 144}
 145
 146static uint16_t
 147virtio_user_set_queue_irq(struct virtio_hw *hw __rte_unused,
 148                          struct virtqueue *vq __rte_unused,
 149                          uint16_t vec)
 150{
 151        /* pretend we have done that */
 152        return vec;
 153}
 154
 155/* This function is to get the queue size, aka, number of descs, of a specified
 156 * queue. Different with the VHOST_USER_GET_QUEUE_NUM, which is used to get the
 157 * max supported queues.
 158 */
 159static uint16_t
 160virtio_user_get_queue_num(struct virtio_hw *hw, uint16_t queue_id __rte_unused)
 161{
 162        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 163
 164        /* Currently, each queue has same queue size */
 165        return dev->queue_size;
 166}
 167
 168static void
 169virtio_user_setup_queue_packed(struct virtqueue *vq,
 170                               struct virtio_user_dev *dev)
 171{
 172        uint16_t queue_idx = vq->vq_queue_index;
 173        struct vring_packed *vring;
 174        uint64_t desc_addr;
 175        uint64_t avail_addr;
 176        uint64_t used_addr;
 177        uint16_t i;
 178
 179        vring  = &dev->packed_vrings[queue_idx];
 180        desc_addr = (uintptr_t)vq->vq_ring_virt_mem;
 181        avail_addr = desc_addr + vq->vq_nentries *
 182                sizeof(struct vring_packed_desc);
 183        used_addr = RTE_ALIGN_CEIL(avail_addr +
 184                           sizeof(struct vring_packed_desc_event),
 185                           VIRTIO_VRING_ALIGN);
 186        vring->num = vq->vq_nentries;
 187        vring->desc = (void *)(uintptr_t)desc_addr;
 188        vring->driver = (void *)(uintptr_t)avail_addr;
 189        vring->device = (void *)(uintptr_t)used_addr;
 190        dev->packed_queues[queue_idx].avail_wrap_counter = true;
 191        dev->packed_queues[queue_idx].used_wrap_counter = true;
 192
 193        for (i = 0; i < vring->num; i++)
 194                vring->desc[i].flags = 0;
 195}
 196
 197static void
 198virtio_user_setup_queue_split(struct virtqueue *vq, struct virtio_user_dev *dev)
 199{
 200        uint16_t queue_idx = vq->vq_queue_index;
 201        uint64_t desc_addr, avail_addr, used_addr;
 202
 203        desc_addr = (uintptr_t)vq->vq_ring_virt_mem;
 204        avail_addr = desc_addr + vq->vq_nentries * sizeof(struct vring_desc);
 205        used_addr = RTE_ALIGN_CEIL(avail_addr + offsetof(struct vring_avail,
 206                                                         ring[vq->vq_nentries]),
 207                                   VIRTIO_VRING_ALIGN);
 208
 209        dev->vrings[queue_idx].num = vq->vq_nentries;
 210        dev->vrings[queue_idx].desc = (void *)(uintptr_t)desc_addr;
 211        dev->vrings[queue_idx].avail = (void *)(uintptr_t)avail_addr;
 212        dev->vrings[queue_idx].used = (void *)(uintptr_t)used_addr;
 213}
 214
 215static int
 216virtio_user_setup_queue(struct virtio_hw *hw, struct virtqueue *vq)
 217{
 218        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 219
 220        if (virtio_with_packed_queue(hw))
 221                virtio_user_setup_queue_packed(vq, dev);
 222        else
 223                virtio_user_setup_queue_split(vq, dev);
 224
 225        return 0;
 226}
 227
 228static void
 229virtio_user_del_queue(struct virtio_hw *hw, struct virtqueue *vq)
 230{
 231        /* For legacy devices, write 0 to VIRTIO_PCI_QUEUE_PFN port, QEMU
 232         * correspondingly stops the ioeventfds, and reset the status of
 233         * the device.
 234         * For modern devices, set queue desc, avail, used in PCI bar to 0,
 235         * not see any more behavior in QEMU.
 236         *
 237         * Here we just care about what information to deliver to vhost-user
 238         * or vhost-kernel. So we just close ioeventfd for now.
 239         */
 240        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 241
 242        close(dev->callfds[vq->vq_queue_index]);
 243        close(dev->kickfds[vq->vq_queue_index]);
 244}
 245
 246static void
 247virtio_user_notify_queue(struct virtio_hw *hw, struct virtqueue *vq)
 248{
 249        uint64_t buf = 1;
 250        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 251
 252        if (hw->cvq && (hw->cvq->vq == vq)) {
 253                if (virtio_with_packed_queue(vq->hw))
 254                        virtio_user_handle_cq_packed(dev, vq->vq_queue_index);
 255                else
 256                        virtio_user_handle_cq(dev, vq->vq_queue_index);
 257                return;
 258        }
 259
 260        if (write(dev->kickfds[vq->vq_queue_index], &buf, sizeof(buf)) < 0)
 261                PMD_DRV_LOG(ERR, "failed to kick backend: %s",
 262                            strerror(errno));
 263}
 264
 265static int
 266virtio_user_dev_close(struct virtio_hw *hw)
 267{
 268        struct virtio_user_dev *dev = virtio_user_get_dev(hw);
 269
 270        virtio_user_dev_uninit(dev);
 271
 272        return 0;
 273}
 274
 275const struct virtio_ops virtio_user_ops = {
 276        .read_dev_cfg   = virtio_user_read_dev_config,
 277        .write_dev_cfg  = virtio_user_write_dev_config,
 278        .get_status     = virtio_user_get_status,
 279        .set_status     = virtio_user_set_status,
 280        .get_features   = virtio_user_get_features,
 281        .set_features   = virtio_user_set_features,
 282        .features_ok    = virtio_user_features_ok,
 283        .get_isr        = virtio_user_get_isr,
 284        .set_config_irq = virtio_user_set_config_irq,
 285        .set_queue_irq  = virtio_user_set_queue_irq,
 286        .get_queue_num  = virtio_user_get_queue_num,
 287        .setup_queue    = virtio_user_setup_queue,
 288        .del_queue      = virtio_user_del_queue,
 289        .notify_queue   = virtio_user_notify_queue,
 290        .dev_close      = virtio_user_dev_close,
 291};
 292
 293static const char *valid_args[] = {
 294#define VIRTIO_USER_ARG_QUEUES_NUM     "queues"
 295        VIRTIO_USER_ARG_QUEUES_NUM,
 296#define VIRTIO_USER_ARG_CQ_NUM         "cq"
 297        VIRTIO_USER_ARG_CQ_NUM,
 298#define VIRTIO_USER_ARG_MAC            "mac"
 299        VIRTIO_USER_ARG_MAC,
 300#define VIRTIO_USER_ARG_PATH           "path"
 301        VIRTIO_USER_ARG_PATH,
 302#define VIRTIO_USER_ARG_QUEUE_SIZE     "queue_size"
 303        VIRTIO_USER_ARG_QUEUE_SIZE,
 304#define VIRTIO_USER_ARG_INTERFACE_NAME "iface"
 305        VIRTIO_USER_ARG_INTERFACE_NAME,
 306#define VIRTIO_USER_ARG_SERVER_MODE    "server"
 307        VIRTIO_USER_ARG_SERVER_MODE,
 308#define VIRTIO_USER_ARG_MRG_RXBUF      "mrg_rxbuf"
 309        VIRTIO_USER_ARG_MRG_RXBUF,
 310#define VIRTIO_USER_ARG_IN_ORDER       "in_order"
 311        VIRTIO_USER_ARG_IN_ORDER,
 312#define VIRTIO_USER_ARG_PACKED_VQ      "packed_vq"
 313        VIRTIO_USER_ARG_PACKED_VQ,
 314#define VIRTIO_USER_ARG_SPEED          "speed"
 315        VIRTIO_USER_ARG_SPEED,
 316#define VIRTIO_USER_ARG_VECTORIZED     "vectorized"
 317        VIRTIO_USER_ARG_VECTORIZED,
 318        NULL
 319};
 320
 321#define VIRTIO_USER_DEF_CQ_EN   0
 322#define VIRTIO_USER_DEF_Q_NUM   1
 323#define VIRTIO_USER_DEF_Q_SZ    256
 324#define VIRTIO_USER_DEF_SERVER_MODE     0
 325
 326static int
 327get_string_arg(const char *key __rte_unused,
 328               const char *value, void *extra_args)
 329{
 330        if (!value || !extra_args)
 331                return -EINVAL;
 332
 333        *(char **)extra_args = strdup(value);
 334
 335        if (!*(char **)extra_args)
 336                return -ENOMEM;
 337
 338        return 0;
 339}
 340
 341static int
 342get_integer_arg(const char *key __rte_unused,
 343                const char *value, void *extra_args)
 344{
 345        uint64_t integer = 0;
 346        if (!value || !extra_args)
 347                return -EINVAL;
 348        errno = 0;
 349        integer = strtoull(value, NULL, 0);
 350        /* extra_args keeps default value, it should be replaced
 351         * only in case of successful parsing of the 'value' arg
 352         */
 353        if (errno == 0)
 354                *(uint64_t *)extra_args = integer;
 355        return -errno;
 356}
 357
 358static uint32_t
 359vdpa_dynamic_major_num(void)
 360{
 361        FILE *fp;
 362        char *line = NULL;
 363        size_t size;
 364        char name[11];
 365        bool found = false;
 366        uint32_t num;
 367
 368        fp = fopen("/proc/devices", "r");
 369        if (fp == NULL) {
 370                PMD_INIT_LOG(ERR, "Cannot open /proc/devices: %s",
 371                             strerror(errno));
 372                return UNNAMED_MAJOR;
 373        }
 374
 375        while (getline(&line, &size, fp) > 0) {
 376                char *stripped = line + strspn(line, " ");
 377                if ((sscanf(stripped, "%u %10s", &num, name) == 2) &&
 378                    (strncmp(name, "vhost-vdpa", 10) == 0)) {
 379                        found = true;
 380                        break;
 381                }
 382        }
 383        fclose(fp);
 384        return found ? num : UNNAMED_MAJOR;
 385}
 386
 387static enum virtio_user_backend_type
 388virtio_user_backend_type(const char *path)
 389{
 390        struct stat sb;
 391
 392        if (stat(path, &sb) == -1) {
 393                if (errno == ENOENT)
 394                        return VIRTIO_USER_BACKEND_VHOST_USER;
 395
 396                PMD_INIT_LOG(ERR, "Stat fails: %s (%s)\n", path,
 397                             strerror(errno));
 398                return VIRTIO_USER_BACKEND_UNKNOWN;
 399        }
 400
 401        if (S_ISSOCK(sb.st_mode)) {
 402                return VIRTIO_USER_BACKEND_VHOST_USER;
 403        } else if (S_ISCHR(sb.st_mode)) {
 404                if (major(sb.st_rdev) == MISC_MAJOR)
 405                        return VIRTIO_USER_BACKEND_VHOST_KERNEL;
 406                if (major(sb.st_rdev) == vdpa_dynamic_major_num())
 407                        return VIRTIO_USER_BACKEND_VHOST_VDPA;
 408        }
 409        return VIRTIO_USER_BACKEND_UNKNOWN;
 410}
 411
 412static struct rte_eth_dev *
 413virtio_user_eth_dev_alloc(struct rte_vdev_device *vdev)
 414{
 415        struct rte_eth_dev *eth_dev;
 416        struct rte_eth_dev_data *data;
 417        struct virtio_hw *hw;
 418        struct virtio_user_dev *dev;
 419
 420        eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*dev));
 421        if (!eth_dev) {
 422                PMD_INIT_LOG(ERR, "cannot alloc rte_eth_dev");
 423                return NULL;
 424        }
 425
 426        data = eth_dev->data;
 427        dev = eth_dev->data->dev_private;
 428        hw = &dev->hw;
 429
 430        hw->port_id = data->port_id;
 431        dev->port_id = data->port_id;
 432        VIRTIO_OPS(hw) = &virtio_user_ops;
 433
 434        hw->intr_lsc = 1;
 435        hw->use_vec_rx = 0;
 436        hw->use_vec_tx = 0;
 437        hw->use_inorder_rx = 0;
 438        hw->use_inorder_tx = 0;
 439
 440        return eth_dev;
 441}
 442
 443static void
 444virtio_user_eth_dev_free(struct rte_eth_dev *eth_dev)
 445{
 446        rte_eth_dev_release_port(eth_dev);
 447}
 448
 449/* Dev initialization routine. Invoked once for each virtio vdev at
 450 * EAL init time, see rte_bus_probe().
 451 * Returns 0 on success.
 452 */
 453static int
 454virtio_user_pmd_probe(struct rte_vdev_device *vdev)
 455{
 456        struct rte_kvargs *kvlist = NULL;
 457        struct rte_eth_dev *eth_dev;
 458        struct virtio_hw *hw;
 459        struct virtio_user_dev *dev;
 460        enum virtio_user_backend_type backend_type = VIRTIO_USER_BACKEND_UNKNOWN;
 461        uint64_t queues = VIRTIO_USER_DEF_Q_NUM;
 462        uint64_t cq = VIRTIO_USER_DEF_CQ_EN;
 463        uint64_t queue_size = VIRTIO_USER_DEF_Q_SZ;
 464        uint64_t server_mode = VIRTIO_USER_DEF_SERVER_MODE;
 465        uint64_t mrg_rxbuf = 1;
 466        uint64_t in_order = 1;
 467        uint64_t packed_vq = 0;
 468        uint64_t vectorized = 0;
 469        char *path = NULL;
 470        char *ifname = NULL;
 471        char *mac_addr = NULL;
 472        int ret = -1;
 473
 474        RTE_BUILD_BUG_ON(offsetof(struct virtio_user_dev, hw) != 0);
 475
 476        if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
 477                const char *name = rte_vdev_device_name(vdev);
 478                eth_dev = rte_eth_dev_attach_secondary(name);
 479                if (!eth_dev) {
 480                        PMD_INIT_LOG(ERR, "Failed to probe %s", name);
 481                        return -1;
 482                }
 483
 484                dev = eth_dev->data->dev_private;
 485                hw = &dev->hw;
 486                VIRTIO_OPS(hw) = &virtio_user_ops;
 487
 488                if (eth_virtio_dev_init(eth_dev) < 0) {
 489                        PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails");
 490                        rte_eth_dev_release_port(eth_dev);
 491                        return -1;
 492                }
 493
 494                eth_dev->dev_ops = &virtio_user_secondary_eth_dev_ops;
 495                eth_dev->device = &vdev->device;
 496                rte_eth_dev_probing_finish(eth_dev);
 497                return 0;
 498        }
 499
 500        kvlist = rte_kvargs_parse(rte_vdev_device_args(vdev), valid_args);
 501        if (!kvlist) {
 502                PMD_INIT_LOG(ERR, "error when parsing param");
 503                goto end;
 504        }
 505
 506        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_PATH) == 1) {
 507                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_PATH,
 508                                       &get_string_arg, &path) < 0) {
 509                        PMD_INIT_LOG(ERR, "error to parse %s",
 510                                     VIRTIO_USER_ARG_PATH);
 511                        goto end;
 512                }
 513        } else {
 514                PMD_INIT_LOG(ERR, "arg %s is mandatory for virtio_user",
 515                             VIRTIO_USER_ARG_PATH);
 516                goto end;
 517        }
 518
 519        backend_type = virtio_user_backend_type(path);
 520        if (backend_type == VIRTIO_USER_BACKEND_UNKNOWN) {
 521                PMD_INIT_LOG(ERR,
 522                             "unable to determine backend type for path %s",
 523                        path);
 524                goto end;
 525        }
 526        PMD_INIT_LOG(INFO, "Backend type detected: %s",
 527                     virtio_user_backend_strings[backend_type]);
 528
 529        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_INTERFACE_NAME) == 1) {
 530                if (backend_type != VIRTIO_USER_BACKEND_VHOST_KERNEL) {
 531                        PMD_INIT_LOG(ERR,
 532                                "arg %s applies only to vhost-kernel backend",
 533                                VIRTIO_USER_ARG_INTERFACE_NAME);
 534                        goto end;
 535                }
 536
 537                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_INTERFACE_NAME,
 538                                       &get_string_arg, &ifname) < 0) {
 539                        PMD_INIT_LOG(ERR, "error to parse %s",
 540                                     VIRTIO_USER_ARG_INTERFACE_NAME);
 541                        goto end;
 542                }
 543        }
 544
 545        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_MAC) == 1) {
 546                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_MAC,
 547                                       &get_string_arg, &mac_addr) < 0) {
 548                        PMD_INIT_LOG(ERR, "error to parse %s",
 549                                     VIRTIO_USER_ARG_MAC);
 550                        goto end;
 551                }
 552        }
 553
 554        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_QUEUE_SIZE) == 1) {
 555                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_QUEUE_SIZE,
 556                                       &get_integer_arg, &queue_size) < 0) {
 557                        PMD_INIT_LOG(ERR, "error to parse %s",
 558                                     VIRTIO_USER_ARG_QUEUE_SIZE);
 559                        goto end;
 560                }
 561        }
 562
 563        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_QUEUES_NUM) == 1) {
 564                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_QUEUES_NUM,
 565                                       &get_integer_arg, &queues) < 0) {
 566                        PMD_INIT_LOG(ERR, "error to parse %s",
 567                                     VIRTIO_USER_ARG_QUEUES_NUM);
 568                        goto end;
 569                }
 570        }
 571
 572        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_SERVER_MODE) == 1) {
 573                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_SERVER_MODE,
 574                                       &get_integer_arg, &server_mode) < 0) {
 575                        PMD_INIT_LOG(ERR, "error to parse %s",
 576                                     VIRTIO_USER_ARG_SERVER_MODE);
 577                        goto end;
 578                }
 579        }
 580
 581        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_CQ_NUM) == 1) {
 582                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_CQ_NUM,
 583                                       &get_integer_arg, &cq) < 0) {
 584                        PMD_INIT_LOG(ERR, "error to parse %s",
 585                                     VIRTIO_USER_ARG_CQ_NUM);
 586                        goto end;
 587                }
 588        } else if (queues > 1) {
 589                cq = 1;
 590        }
 591
 592        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_PACKED_VQ) == 1) {
 593                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_PACKED_VQ,
 594                                       &get_integer_arg, &packed_vq) < 0) {
 595                        PMD_INIT_LOG(ERR, "error to parse %s",
 596                                     VIRTIO_USER_ARG_PACKED_VQ);
 597                        goto end;
 598                }
 599        }
 600
 601        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_VECTORIZED) == 1) {
 602                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_VECTORIZED,
 603                                       &get_integer_arg, &vectorized) < 0) {
 604                        PMD_INIT_LOG(ERR, "error to parse %s",
 605                                     VIRTIO_USER_ARG_VECTORIZED);
 606                        goto end;
 607                }
 608        }
 609
 610        if (queues > 1 && cq == 0) {
 611                PMD_INIT_LOG(ERR, "multi-q requires ctrl-q");
 612                goto end;
 613        }
 614
 615        if (queues > VIRTIO_MAX_VIRTQUEUE_PAIRS) {
 616                PMD_INIT_LOG(ERR, "arg %s %" PRIu64 " exceeds the limit %u",
 617                        VIRTIO_USER_ARG_QUEUES_NUM, queues,
 618                        VIRTIO_MAX_VIRTQUEUE_PAIRS);
 619                goto end;
 620        }
 621
 622        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_MRG_RXBUF) == 1) {
 623                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_MRG_RXBUF,
 624                                       &get_integer_arg, &mrg_rxbuf) < 0) {
 625                        PMD_INIT_LOG(ERR, "error to parse %s",
 626                                     VIRTIO_USER_ARG_MRG_RXBUF);
 627                        goto end;
 628                }
 629        }
 630
 631        if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_IN_ORDER) == 1) {
 632                if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_IN_ORDER,
 633                                       &get_integer_arg, &in_order) < 0) {
 634                        PMD_INIT_LOG(ERR, "error to parse %s",
 635                                     VIRTIO_USER_ARG_IN_ORDER);
 636                        goto end;
 637                }
 638        }
 639
 640        eth_dev = virtio_user_eth_dev_alloc(vdev);
 641        if (!eth_dev) {
 642                PMD_INIT_LOG(ERR, "virtio_user fails to alloc device");
 643                goto end;
 644        }
 645
 646        dev = eth_dev->data->dev_private;
 647        hw = &dev->hw;
 648        if (virtio_user_dev_init(dev, path, queues, cq,
 649                         queue_size, mac_addr, &ifname, server_mode,
 650                         mrg_rxbuf, in_order, packed_vq, backend_type) < 0) {
 651                PMD_INIT_LOG(ERR, "virtio_user_dev_init fails");
 652                virtio_user_eth_dev_free(eth_dev);
 653                goto end;
 654        }
 655
 656        /* previously called by pci probing for physical dev */
 657        if (eth_virtio_dev_init(eth_dev) < 0) {
 658                PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails");
 659                virtio_user_eth_dev_free(eth_dev);
 660                goto end;
 661        }
 662
 663        if (vectorized) {
 664                if (packed_vq) {
 665#if defined(CC_AVX512_SUPPORT) || defined(RTE_ARCH_ARM)
 666                        hw->use_vec_rx = 1;
 667                        hw->use_vec_tx = 1;
 668#else
 669                        PMD_INIT_LOG(INFO,
 670                                "building environment do not support packed ring vectorized");
 671#endif
 672                } else {
 673                        hw->use_vec_rx = 1;
 674                }
 675        }
 676
 677        rte_eth_dev_probing_finish(eth_dev);
 678        ret = 0;
 679
 680end:
 681        if (kvlist)
 682                rte_kvargs_free(kvlist);
 683        if (path)
 684                free(path);
 685        if (mac_addr)
 686                free(mac_addr);
 687        if (ifname)
 688                free(ifname);
 689        return ret;
 690}
 691
 692static int
 693virtio_user_pmd_remove(struct rte_vdev_device *vdev)
 694{
 695        const char *name;
 696        struct rte_eth_dev *eth_dev;
 697
 698        if (!vdev)
 699                return -EINVAL;
 700
 701        name = rte_vdev_device_name(vdev);
 702        PMD_DRV_LOG(INFO, "Un-Initializing %s", name);
 703        eth_dev = rte_eth_dev_allocated(name);
 704        /* Port has already been released by close. */
 705        if (!eth_dev)
 706                return 0;
 707
 708        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 709                return rte_eth_dev_release_port(eth_dev);
 710
 711        /* make sure the device is stopped, queues freed */
 712        return rte_eth_dev_close(eth_dev->data->port_id);
 713}
 714
 715static int virtio_user_pmd_dma_map(struct rte_vdev_device *vdev, void *addr,
 716                uint64_t iova, size_t len)
 717{
 718        const char *name;
 719        struct rte_eth_dev *eth_dev;
 720        struct virtio_user_dev *dev;
 721
 722        if (!vdev)
 723                return -EINVAL;
 724
 725        name = rte_vdev_device_name(vdev);
 726        eth_dev = rte_eth_dev_allocated(name);
 727        /* Port has already been released by close. */
 728        if (!eth_dev)
 729                return 0;
 730
 731        dev = eth_dev->data->dev_private;
 732
 733        if (dev->ops->dma_map)
 734                return dev->ops->dma_map(dev, addr, iova, len);
 735
 736        return 0;
 737}
 738
 739static int virtio_user_pmd_dma_unmap(struct rte_vdev_device *vdev, void *addr,
 740                uint64_t iova, size_t len)
 741{
 742        const char *name;
 743        struct rte_eth_dev *eth_dev;
 744        struct virtio_user_dev *dev;
 745
 746        if (!vdev)
 747                return -EINVAL;
 748
 749        name = rte_vdev_device_name(vdev);
 750        eth_dev = rte_eth_dev_allocated(name);
 751        /* Port has already been released by close. */
 752        if (!eth_dev)
 753                return 0;
 754
 755        dev = eth_dev->data->dev_private;
 756
 757        if (dev->ops->dma_unmap)
 758                return dev->ops->dma_unmap(dev, addr, iova, len);
 759
 760        return 0;
 761}
 762
 763static struct rte_vdev_driver virtio_user_driver = {
 764        .probe = virtio_user_pmd_probe,
 765        .remove = virtio_user_pmd_remove,
 766        .dma_map = virtio_user_pmd_dma_map,
 767        .dma_unmap = virtio_user_pmd_dma_unmap,
 768        .drv_flags = RTE_VDEV_DRV_NEED_IOVA_AS_VA,
 769};
 770
 771RTE_PMD_REGISTER_VDEV(net_virtio_user, virtio_user_driver);
 772RTE_PMD_REGISTER_ALIAS(net_virtio_user, virtio_user);
 773RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user,
 774        "path=<path> "
 775        "mac=<mac addr> "
 776        "cq=<int> "
 777        "queue_size=<int> "
 778        "queues=<int> "
 779        "iface=<string> "
 780        "server=<0|1> "
 781        "mrg_rxbuf=<0|1> "
 782        "in_order=<0|1> "
 783        "packed_vq=<0|1> "
 784        "speed=<int> "
 785        "vectorized=<0|1>");
 786