dpdk/drivers/net/softnic/rte_eth_softnic.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2017 Intel Corporation
   3 */
   4
   5#include <stdint.h>
   6#include <stdlib.h>
   7#include <string.h>
   8
   9#include <ethdev_driver.h>
  10#include <ethdev_vdev.h>
  11#include <rte_malloc.h>
  12#include <rte_bus_vdev.h>
  13#include <rte_kvargs.h>
  14#include <rte_errno.h>
  15#include <rte_ring.h>
  16#include <rte_tm_driver.h>
  17#include <rte_mtr_driver.h>
  18
  19#include "rte_eth_softnic.h"
  20#include "rte_eth_softnic_internals.h"
  21
  22#define PMD_PARAM_FIRMWARE                                 "firmware"
  23#define PMD_PARAM_CONN_PORT                                "conn_port"
  24#define PMD_PARAM_CPU_ID                                   "cpu_id"
  25#define PMD_PARAM_SC                                       "sc"
  26#define PMD_PARAM_TM_N_QUEUES                              "tm_n_queues"
  27#define PMD_PARAM_TM_QSIZE0                                "tm_qsize0"
  28#define PMD_PARAM_TM_QSIZE1                                "tm_qsize1"
  29#define PMD_PARAM_TM_QSIZE2                                "tm_qsize2"
  30#define PMD_PARAM_TM_QSIZE3                                "tm_qsize3"
  31#define PMD_PARAM_TM_QSIZE4                                "tm_qsize4"
  32#define PMD_PARAM_TM_QSIZE5                                "tm_qsize5"
  33#define PMD_PARAM_TM_QSIZE6                                "tm_qsize6"
  34#define PMD_PARAM_TM_QSIZE7                                "tm_qsize7"
  35#define PMD_PARAM_TM_QSIZE8                                "tm_qsize8"
  36#define PMD_PARAM_TM_QSIZE9                                "tm_qsize9"
  37#define PMD_PARAM_TM_QSIZE10                               "tm_qsize10"
  38#define PMD_PARAM_TM_QSIZE11                               "tm_qsize11"
  39#define PMD_PARAM_TM_QSIZE12                               "tm_qsize12"
  40
  41
  42static const char * const pmd_valid_args[] = {
  43        PMD_PARAM_FIRMWARE,
  44        PMD_PARAM_CONN_PORT,
  45        PMD_PARAM_CPU_ID,
  46        PMD_PARAM_SC,
  47        PMD_PARAM_TM_N_QUEUES,
  48        PMD_PARAM_TM_QSIZE0,
  49        PMD_PARAM_TM_QSIZE1,
  50        PMD_PARAM_TM_QSIZE2,
  51        PMD_PARAM_TM_QSIZE3,
  52        PMD_PARAM_TM_QSIZE4,
  53        PMD_PARAM_TM_QSIZE5,
  54        PMD_PARAM_TM_QSIZE6,
  55        PMD_PARAM_TM_QSIZE7,
  56        PMD_PARAM_TM_QSIZE8,
  57        PMD_PARAM_TM_QSIZE9,
  58        PMD_PARAM_TM_QSIZE10,
  59        PMD_PARAM_TM_QSIZE11,
  60        PMD_PARAM_TM_QSIZE12,
  61        NULL
  62};
  63
  64static const char welcome[] =
  65        "\n"
  66        "Welcome to Soft NIC!\n"
  67        "\n";
  68
  69static const char prompt[] = "softnic> ";
  70
  71static const struct softnic_conn_params conn_params_default = {
  72        .welcome = welcome,
  73        .prompt = prompt,
  74        .addr = "0.0.0.0",
  75        .port = 0,
  76        .buf_size = 1024 * 1024,
  77        .msg_in_len_max = 1024,
  78        .msg_out_len_max = 1024 * 1024,
  79        .msg_handle = softnic_cli_process,
  80        .msg_handle_arg = NULL,
  81};
  82
  83RTE_LOG_REGISTER_DEFAULT(pmd_softnic_logtype, NOTICE);
  84
  85#define PMD_LOG(level, fmt, args...) \
  86        rte_log(RTE_LOG_ ## level, pmd_softnic_logtype, \
  87                "%s(): " fmt "\n", __func__, ##args)
  88
  89static int
  90pmd_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
  91        struct rte_eth_dev_info *dev_info)
  92{
  93        dev_info->max_rx_pktlen = UINT32_MAX;
  94        dev_info->max_rx_queues = UINT16_MAX;
  95        dev_info->max_tx_queues = UINT16_MAX;
  96
  97        return 0;
  98}
  99
 100static int
 101pmd_dev_configure(struct rte_eth_dev *dev __rte_unused)
 102{
 103        return 0;
 104}
 105
 106static int
 107pmd_rx_queue_setup(struct rte_eth_dev *dev,
 108        uint16_t rx_queue_id,
 109        uint16_t nb_rx_desc,
 110        unsigned int socket_id __rte_unused,
 111        const struct rte_eth_rxconf *rx_conf __rte_unused,
 112        struct rte_mempool *mb_pool __rte_unused)
 113{
 114        char name[NAME_SIZE];
 115        struct pmd_internals *p = dev->data->dev_private;
 116        struct softnic_swq *swq;
 117
 118        struct softnic_swq_params params = {
 119                .size = nb_rx_desc,
 120        };
 121
 122        snprintf(name, sizeof(name), "RXQ%u", rx_queue_id);
 123
 124        swq = softnic_swq_create(p,
 125                name,
 126                &params);
 127        if (swq == NULL)
 128                return -1;
 129
 130        dev->data->rx_queues[rx_queue_id] = swq->r;
 131        return 0;
 132}
 133
 134static int
 135pmd_tx_queue_setup(struct rte_eth_dev *dev,
 136        uint16_t tx_queue_id,
 137        uint16_t nb_tx_desc,
 138        unsigned int socket_id __rte_unused,
 139        const struct rte_eth_txconf *tx_conf __rte_unused)
 140{
 141        char name[NAME_SIZE];
 142        struct pmd_internals *p = dev->data->dev_private;
 143        struct softnic_swq *swq;
 144
 145        struct softnic_swq_params params = {
 146                .size = nb_tx_desc,
 147        };
 148
 149        snprintf(name, sizeof(name), "TXQ%u", tx_queue_id);
 150
 151        swq = softnic_swq_create(p,
 152                name,
 153                &params);
 154        if (swq == NULL)
 155                return -1;
 156
 157        dev->data->tx_queues[tx_queue_id] = swq->r;
 158        return 0;
 159}
 160
 161static int
 162pmd_dev_start(struct rte_eth_dev *dev)
 163{
 164        struct pmd_internals *p = dev->data->dev_private;
 165        int status;
 166
 167        /* Firmware */
 168        status = softnic_cli_script_process(p,
 169                p->params.firmware,
 170                conn_params_default.msg_in_len_max,
 171                conn_params_default.msg_out_len_max);
 172        if (status)
 173                return status;
 174
 175        /* Link UP */
 176        dev->data->dev_link.link_status = ETH_LINK_UP;
 177
 178        return 0;
 179}
 180
 181static int
 182pmd_dev_stop(struct rte_eth_dev *dev)
 183{
 184        struct pmd_internals *p = dev->data->dev_private;
 185
 186        /* Link DOWN */
 187        dev->data->dev_link.link_status = ETH_LINK_DOWN;
 188
 189        /* Firmware */
 190        softnic_pipeline_disable_all(p);
 191        softnic_pipeline_free(p);
 192        softnic_table_action_profile_free(p);
 193        softnic_port_in_action_profile_free(p);
 194        softnic_tap_free(p);
 195        softnic_tmgr_free(p);
 196        softnic_link_free(p);
 197        softnic_softnic_swq_free_keep_rxq_txq(p);
 198        softnic_mempool_free(p);
 199
 200        tm_hierarchy_free(p);
 201        softnic_mtr_free(p);
 202
 203        return 0;
 204}
 205
 206static void
 207pmd_free(struct pmd_internals *p)
 208{
 209        if (p == NULL)
 210                return;
 211
 212        if (p->params.conn_port)
 213                softnic_conn_free(p->conn);
 214
 215        softnic_thread_free(p);
 216        softnic_pipeline_free(p);
 217        softnic_table_action_profile_free(p);
 218        softnic_port_in_action_profile_free(p);
 219        softnic_tap_free(p);
 220        softnic_tmgr_free(p);
 221        softnic_link_free(p);
 222        softnic_swq_free(p);
 223        softnic_mempool_free(p);
 224
 225        tm_hierarchy_free(p);
 226        softnic_mtr_free(p);
 227
 228        rte_free(p);
 229}
 230
 231static int
 232pmd_dev_close(struct rte_eth_dev *dev)
 233{
 234        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 235                return 0;
 236
 237        pmd_free(dev->data->dev_private);
 238        dev->data->dev_private = NULL; /* already freed */
 239        dev->data->mac_addrs = NULL; /* statically allocated */
 240        return 0;
 241}
 242
 243static int
 244pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 245        int wait_to_complete __rte_unused)
 246{
 247        return 0;
 248}
 249
 250static int
 251pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
 252                 const struct rte_flow_ops **ops)
 253{
 254        *ops = &pmd_flow_ops;
 255        return 0;
 256}
 257
 258static int
 259pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 260{
 261        *(const struct rte_tm_ops **)arg = &pmd_tm_ops;
 262
 263        return 0;
 264}
 265
 266static int
 267pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 268{
 269        *(const struct rte_mtr_ops **)arg = &pmd_mtr_ops;
 270
 271        return 0;
 272}
 273
 274static const struct eth_dev_ops pmd_ops = {
 275        .dev_configure = pmd_dev_configure,
 276        .dev_start = pmd_dev_start,
 277        .dev_stop = pmd_dev_stop,
 278        .dev_close = pmd_dev_close,
 279        .link_update = pmd_link_update,
 280        .dev_infos_get = pmd_dev_infos_get,
 281        .rx_queue_setup = pmd_rx_queue_setup,
 282        .tx_queue_setup = pmd_tx_queue_setup,
 283        .flow_ops_get = pmd_flow_ops_get,
 284        .tm_ops_get = pmd_tm_ops_get,
 285        .mtr_ops_get = pmd_mtr_ops_get,
 286};
 287
 288static uint16_t
 289pmd_rx_pkt_burst(void *rxq,
 290        struct rte_mbuf **rx_pkts,
 291        uint16_t nb_pkts)
 292{
 293        return (uint16_t)rte_ring_sc_dequeue_burst(rxq,
 294                (void **)rx_pkts,
 295                nb_pkts,
 296                NULL);
 297}
 298
 299static uint16_t
 300pmd_tx_pkt_burst(void *txq,
 301        struct rte_mbuf **tx_pkts,
 302        uint16_t nb_pkts)
 303{
 304        return (uint16_t)rte_ring_sp_enqueue_burst(txq,
 305                (void **)tx_pkts,
 306                nb_pkts,
 307                NULL);
 308}
 309
 310static void *
 311pmd_init(struct pmd_params *params)
 312{
 313        struct pmd_internals *p;
 314        int status;
 315
 316        p = rte_zmalloc_socket(params->name,
 317                sizeof(struct pmd_internals),
 318                0,
 319                params->cpu_id);
 320        if (p == NULL)
 321                return NULL;
 322
 323        /* Params */
 324        memcpy(&p->params, params, sizeof(p->params));
 325
 326        /* Resources */
 327        tm_hierarchy_init(p);
 328        softnic_mtr_init(p);
 329
 330        softnic_mempool_init(p);
 331        softnic_swq_init(p);
 332        softnic_link_init(p);
 333        softnic_tmgr_init(p);
 334        softnic_tap_init(p);
 335        softnic_cryptodev_init(p);
 336        softnic_port_in_action_profile_init(p);
 337        softnic_table_action_profile_init(p);
 338        softnic_pipeline_init(p);
 339
 340        status = softnic_thread_init(p);
 341        if (status) {
 342                rte_free(p);
 343                return NULL;
 344        }
 345
 346        if (params->conn_port) {
 347                struct softnic_conn_params conn_params;
 348
 349                memcpy(&conn_params, &conn_params_default, sizeof(conn_params));
 350                conn_params.port = p->params.conn_port;
 351                conn_params.msg_handle_arg = p;
 352
 353                p->conn = softnic_conn_init(&conn_params);
 354                if (p->conn == NULL) {
 355                        softnic_thread_free(p);
 356                        rte_free(p);
 357                        return NULL;
 358                }
 359        }
 360
 361        return p;
 362}
 363
 364static struct rte_ether_addr eth_addr = {
 365        .addr_bytes = {0},
 366};
 367
 368static int
 369pmd_ethdev_register(struct rte_vdev_device *vdev,
 370        struct pmd_params *params,
 371        void *dev_private)
 372{
 373        struct rte_eth_dev *dev;
 374
 375        /* Ethdev entry allocation */
 376        dev = rte_eth_dev_allocate(params->name);
 377        if (!dev)
 378                return -ENOMEM;
 379
 380        /* dev */
 381        dev->rx_pkt_burst = pmd_rx_pkt_burst;
 382        dev->tx_pkt_burst = pmd_tx_pkt_burst;
 383        dev->tx_pkt_prepare = NULL;
 384        dev->dev_ops = &pmd_ops;
 385        dev->device = &vdev->device;
 386
 387        /* dev->data */
 388        dev->data->dev_private = dev_private;
 389        dev->data->dev_link.link_speed = ETH_SPEED_NUM_100G;
 390        dev->data->dev_link.link_duplex = ETH_LINK_FULL_DUPLEX;
 391        dev->data->dev_link.link_autoneg = ETH_LINK_FIXED;
 392        dev->data->dev_link.link_status = ETH_LINK_DOWN;
 393        dev->data->mac_addrs = &eth_addr;
 394        dev->data->promiscuous = 1;
 395        dev->data->numa_node = params->cpu_id;
 396
 397        rte_eth_dev_probing_finish(dev);
 398
 399        return 0;
 400}
 401
 402static int
 403get_string(const char *key __rte_unused, const char *value, void *extra_args)
 404{
 405        if (!value || !extra_args)
 406                return -EINVAL;
 407
 408        *(char **)extra_args = strdup(value);
 409
 410        if (!*(char **)extra_args)
 411                return -ENOMEM;
 412
 413        return 0;
 414}
 415
 416static int
 417get_uint32(const char *key __rte_unused, const char *value, void *extra_args)
 418{
 419        if (!value || !extra_args)
 420                return -EINVAL;
 421
 422        *(uint32_t *)extra_args = strtoull(value, NULL, 0);
 423
 424        return 0;
 425}
 426
 427static int
 428get_uint16(const char *key __rte_unused, const char *value, void *extra_args)
 429{
 430        if (!value || !extra_args)
 431                return -EINVAL;
 432
 433        *(uint16_t *)extra_args = strtoull(value, NULL, 0);
 434
 435        return 0;
 436}
 437
 438static int
 439pmd_parse_args(struct pmd_params *p, const char *params)
 440{
 441        struct rte_kvargs *kvlist;
 442        int ret = 0;
 443
 444        kvlist = rte_kvargs_parse(params, pmd_valid_args);
 445        if (kvlist == NULL)
 446                return -EINVAL;
 447
 448        /* Set default values */
 449        memset(p, 0, sizeof(*p));
 450        p->firmware = SOFTNIC_FIRMWARE;
 451        p->cpu_id = SOFTNIC_CPU_ID;
 452        p->sc = SOFTNIC_SC;
 453        p->tm.n_queues = SOFTNIC_TM_N_QUEUES;
 454        p->tm.qsize[0] = SOFTNIC_TM_QUEUE_SIZE;
 455        p->tm.qsize[1] = SOFTNIC_TM_QUEUE_SIZE;
 456        p->tm.qsize[2] = SOFTNIC_TM_QUEUE_SIZE;
 457        p->tm.qsize[3] = SOFTNIC_TM_QUEUE_SIZE;
 458        p->tm.qsize[4] = SOFTNIC_TM_QUEUE_SIZE;
 459        p->tm.qsize[5] = SOFTNIC_TM_QUEUE_SIZE;
 460        p->tm.qsize[6] = SOFTNIC_TM_QUEUE_SIZE;
 461        p->tm.qsize[7] = SOFTNIC_TM_QUEUE_SIZE;
 462        p->tm.qsize[8] = SOFTNIC_TM_QUEUE_SIZE;
 463        p->tm.qsize[9] = SOFTNIC_TM_QUEUE_SIZE;
 464        p->tm.qsize[10] = SOFTNIC_TM_QUEUE_SIZE;
 465        p->tm.qsize[11] = SOFTNIC_TM_QUEUE_SIZE;
 466        p->tm.qsize[12] = SOFTNIC_TM_QUEUE_SIZE;
 467
 468        /* Firmware script (optional) */
 469        if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) {
 470                ret = rte_kvargs_process(kvlist, PMD_PARAM_FIRMWARE,
 471                        &get_string, &p->firmware);
 472                if (ret < 0)
 473                        goto out_free;
 474        }
 475
 476        /* Connection listening port (optional) */
 477        if (rte_kvargs_count(kvlist, PMD_PARAM_CONN_PORT) == 1) {
 478                ret = rte_kvargs_process(kvlist, PMD_PARAM_CONN_PORT,
 479                        &get_uint16, &p->conn_port);
 480                if (ret < 0)
 481                        goto out_free;
 482        }
 483
 484        /* CPU ID (optional) */
 485        if (rte_kvargs_count(kvlist, PMD_PARAM_CPU_ID) == 1) {
 486                ret = rte_kvargs_process(kvlist, PMD_PARAM_CPU_ID,
 487                        &get_uint32, &p->cpu_id);
 488                if (ret < 0)
 489                        goto out_free;
 490        }
 491
 492        /* Service cores (optional) */
 493        if (rte_kvargs_count(kvlist, PMD_PARAM_SC) == 1) {
 494                ret = rte_kvargs_process(kvlist, PMD_PARAM_SC,
 495                        &get_uint32, &p->sc);
 496                if (ret < 0)
 497                        goto out_free;
 498        }
 499
 500        /* TM number of queues (optional) */
 501        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_N_QUEUES) == 1) {
 502                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_N_QUEUES,
 503                        &get_uint32, &p->tm.n_queues);
 504                if (ret < 0)
 505                        goto out_free;
 506        }
 507
 508        /* TM queue size 0 .. 3 (optional) */
 509        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE0) == 1) {
 510                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE0,
 511                        &get_uint32, &p->tm.qsize[0]);
 512                if (ret < 0)
 513                        goto out_free;
 514        }
 515
 516        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE1) == 1) {
 517                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE1,
 518                        &get_uint32, &p->tm.qsize[1]);
 519                if (ret < 0)
 520                        goto out_free;
 521        }
 522
 523        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE2) == 1) {
 524                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE2,
 525                        &get_uint32, &p->tm.qsize[2]);
 526                if (ret < 0)
 527                        goto out_free;
 528        }
 529
 530        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE3) == 1) {
 531                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE3,
 532                        &get_uint32, &p->tm.qsize[3]);
 533                if (ret < 0)
 534                        goto out_free;
 535        }
 536
 537        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE4) == 1) {
 538                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE4,
 539                        &get_uint32, &p->tm.qsize[4]);
 540                if (ret < 0)
 541                        goto out_free;
 542        }
 543
 544        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE5) == 1) {
 545                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE5,
 546                        &get_uint32, &p->tm.qsize[5]);
 547                if (ret < 0)
 548                        goto out_free;
 549        }
 550
 551        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE6) == 1) {
 552                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE6,
 553                        &get_uint32, &p->tm.qsize[6]);
 554                if (ret < 0)
 555                        goto out_free;
 556        }
 557
 558        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE7) == 1) {
 559                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE7,
 560                        &get_uint32, &p->tm.qsize[7]);
 561                if (ret < 0)
 562                        goto out_free;
 563        }
 564        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE8) == 1) {
 565                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE8,
 566                        &get_uint32, &p->tm.qsize[8]);
 567                if (ret < 0)
 568                        goto out_free;
 569        }
 570        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE9) == 1) {
 571                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE9,
 572                        &get_uint32, &p->tm.qsize[9]);
 573                if (ret < 0)
 574                        goto out_free;
 575        }
 576
 577        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE10) == 1) {
 578                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE10,
 579                        &get_uint32, &p->tm.qsize[10]);
 580                if (ret < 0)
 581                        goto out_free;
 582        }
 583
 584        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE11) == 1) {
 585                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE11,
 586                        &get_uint32, &p->tm.qsize[11]);
 587                if (ret < 0)
 588                        goto out_free;
 589        }
 590
 591        if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE12) == 1) {
 592                ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE12,
 593                        &get_uint32, &p->tm.qsize[12]);
 594                if (ret < 0)
 595                        goto out_free;
 596        }
 597
 598out_free:
 599        rte_kvargs_free(kvlist);
 600        return ret;
 601}
 602
 603static int
 604pmd_probe(struct rte_vdev_device *vdev)
 605{
 606        struct pmd_params p;
 607        const char *params;
 608        int status = 0;
 609
 610        void *dev_private;
 611        const char *name = rte_vdev_device_name(vdev);
 612
 613        PMD_LOG(INFO, "Probing device \"%s\"", name);
 614
 615        /* Parse input arguments */
 616        params = rte_vdev_device_args(vdev);
 617        if (!params)
 618                return -EINVAL;
 619
 620        status = pmd_parse_args(&p, params);
 621        if (status)
 622                return status;
 623
 624        p.name = name;
 625
 626        /* Allocate and initialize soft ethdev private data */
 627        dev_private = pmd_init(&p);
 628        if (dev_private == NULL)
 629                return -ENOMEM;
 630
 631        /* Register soft ethdev */
 632        PMD_LOG(INFO, "Creating soft ethdev \"%s\"", p.name);
 633
 634        status = pmd_ethdev_register(vdev, &p, dev_private);
 635        if (status) {
 636                pmd_free(dev_private);
 637                return status;
 638        }
 639
 640        return 0;
 641}
 642
 643static int
 644pmd_remove(struct rte_vdev_device *vdev)
 645{
 646        struct rte_eth_dev *dev = NULL;
 647
 648        if (!vdev)
 649                return -EINVAL;
 650
 651        PMD_LOG(INFO, "Removing device \"%s\"", rte_vdev_device_name(vdev));
 652
 653        /* Find the ethdev entry */
 654        dev = rte_eth_dev_allocated(rte_vdev_device_name(vdev));
 655        if (dev == NULL)
 656                return 0; /* port already released */
 657
 658        pmd_dev_close(dev);
 659        rte_eth_dev_release_port(dev);
 660
 661        return 0;
 662}
 663
 664static struct rte_vdev_driver pmd_softnic_drv = {
 665        .probe = pmd_probe,
 666        .remove = pmd_remove,
 667};
 668
 669RTE_PMD_REGISTER_VDEV(net_softnic, pmd_softnic_drv);
 670RTE_PMD_REGISTER_PARAM_STRING(net_softnic,
 671        PMD_PARAM_FIRMWARE "=<string> "
 672        PMD_PARAM_CONN_PORT "=<uint16> "
 673        PMD_PARAM_CPU_ID "=<uint32> "
 674        PMD_PARAM_TM_N_QUEUES "=<uint32> "
 675        PMD_PARAM_TM_QSIZE0 "=<uint32> "
 676        PMD_PARAM_TM_QSIZE1 "=<uint32> "
 677        PMD_PARAM_TM_QSIZE2 "=<uint32> "
 678        PMD_PARAM_TM_QSIZE3 "=<uint32>"
 679        PMD_PARAM_TM_QSIZE4 "=<uint32> "
 680        PMD_PARAM_TM_QSIZE5 "=<uint32> "
 681        PMD_PARAM_TM_QSIZE6 "=<uint32> "
 682        PMD_PARAM_TM_QSIZE7 "=<uint32> "
 683        PMD_PARAM_TM_QSIZE8 "=<uint32> "
 684        PMD_PARAM_TM_QSIZE9 "=<uint32> "
 685        PMD_PARAM_TM_QSIZE10 "=<uint32> "
 686        PMD_PARAM_TM_QSIZE11 "=<uint32>"
 687        PMD_PARAM_TM_QSIZE12 "=<uint32>"
 688);
 689
 690int
 691rte_pmd_softnic_manage(uint16_t port_id)
 692{
 693        struct rte_eth_dev *dev = &rte_eth_devices[port_id];
 694        struct pmd_internals *softnic;
 695
 696#ifdef RTE_LIBRTE_ETHDEV_DEBUG
 697        RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
 698#endif
 699
 700        softnic = dev->data->dev_private;
 701
 702        softnic_conn_poll_for_conn(softnic->conn);
 703
 704        softnic_conn_poll_for_msg(softnic->conn);
 705
 706        return 0;
 707}
 708