dpdk/lib/rawdev/rte_rawdev.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright 2017 NXP
   3 */
   4
   5#include <ctype.h>
   6#include <stdio.h>
   7#include <stdlib.h>
   8#include <string.h>
   9#include <stdarg.h>
  10#include <errno.h>
  11#include <stdint.h>
  12#include <inttypes.h>
  13#include <sys/types.h>
  14#include <sys/queue.h>
  15
  16#include <rte_string_fns.h>
  17#include <rte_byteorder.h>
  18#include <rte_log.h>
  19#include <rte_debug.h>
  20#include <rte_dev.h>
  21#include <rte_memory.h>
  22#include <rte_memcpy.h>
  23#include <rte_memzone.h>
  24#include <rte_eal.h>
  25#include <rte_per_lcore.h>
  26#include <rte_lcore.h>
  27#include <rte_atomic.h>
  28#include <rte_branch_prediction.h>
  29#include <rte_common.h>
  30#include <rte_malloc.h>
  31#include <rte_errno.h>
  32#include <rte_telemetry.h>
  33
  34#include "rte_rawdev.h"
  35#include "rte_rawdev_pmd.h"
  36
  37static struct rte_rawdev rte_rawdevices[RTE_RAWDEV_MAX_DEVS];
  38
  39struct rte_rawdev *rte_rawdevs = rte_rawdevices;
  40
  41static struct rte_rawdev_global rawdev_globals = {
  42        .nb_devs                = 0
  43};
  44
  45/* Raw device, northbound API implementation */
  46uint8_t
  47rte_rawdev_count(void)
  48{
  49        return rawdev_globals.nb_devs;
  50}
  51
  52uint16_t
  53rte_rawdev_get_dev_id(const char *name)
  54{
  55        uint16_t i;
  56
  57        if (!name)
  58                return -EINVAL;
  59
  60        for (i = 0; i < rawdev_globals.nb_devs; i++)
  61                if ((strcmp(rte_rawdevices[i].name, name)
  62                                == 0) &&
  63                                (rte_rawdevices[i].attached ==
  64                                                RTE_RAWDEV_ATTACHED))
  65                        return i;
  66        return -ENODEV;
  67}
  68
  69int
  70rte_rawdev_socket_id(uint16_t dev_id)
  71{
  72        struct rte_rawdev *dev;
  73
  74        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
  75        dev = &rte_rawdevs[dev_id];
  76
  77        return dev->socket_id;
  78}
  79
  80int
  81rte_rawdev_info_get(uint16_t dev_id, struct rte_rawdev_info *dev_info,
  82                size_t dev_private_size)
  83{
  84        struct rte_rawdev *rawdev;
  85        int ret = 0;
  86
  87        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
  88        RTE_FUNC_PTR_OR_ERR_RET(dev_info, -EINVAL);
  89
  90        rawdev = &rte_rawdevs[dev_id];
  91
  92        if (dev_info->dev_private != NULL) {
  93                RTE_FUNC_PTR_OR_ERR_RET(*rawdev->dev_ops->dev_info_get, -ENOTSUP);
  94                ret = (*rawdev->dev_ops->dev_info_get)(rawdev,
  95                                dev_info->dev_private,
  96                                dev_private_size);
  97        }
  98
  99        dev_info->driver_name = rawdev->driver_name;
 100        dev_info->device = rawdev->device;
 101        dev_info->socket_id = rawdev->socket_id;
 102
 103        return ret;
 104}
 105
 106int
 107rte_rawdev_configure(uint16_t dev_id, struct rte_rawdev_info *dev_conf,
 108                size_t dev_private_size)
 109{
 110        struct rte_rawdev *dev;
 111        int diag;
 112
 113        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 114        RTE_FUNC_PTR_OR_ERR_RET(dev_conf, -EINVAL);
 115
 116        dev = &rte_rawdevs[dev_id];
 117
 118        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP);
 119
 120        if (dev->started) {
 121                RTE_RDEV_ERR(
 122                   "device %d must be stopped to allow configuration", dev_id);
 123                return -EBUSY;
 124        }
 125
 126        /* Configure the device */
 127        diag = (*dev->dev_ops->dev_configure)(dev, dev_conf->dev_private,
 128                        dev_private_size);
 129        if (diag != 0)
 130                RTE_RDEV_ERR("dev%d dev_configure = %d", dev_id, diag);
 131        else
 132                dev->attached = 1;
 133
 134        return diag;
 135}
 136
 137int
 138rte_rawdev_queue_conf_get(uint16_t dev_id,
 139                          uint16_t queue_id,
 140                          rte_rawdev_obj_t queue_conf,
 141                          size_t queue_conf_size)
 142{
 143        struct rte_rawdev *dev;
 144
 145        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 146        dev = &rte_rawdevs[dev_id];
 147
 148        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_def_conf, -ENOTSUP);
 149        return (*dev->dev_ops->queue_def_conf)(dev, queue_id, queue_conf,
 150                        queue_conf_size);
 151}
 152
 153int
 154rte_rawdev_queue_setup(uint16_t dev_id,
 155                       uint16_t queue_id,
 156                       rte_rawdev_obj_t queue_conf,
 157                       size_t queue_conf_size)
 158{
 159        struct rte_rawdev *dev;
 160
 161        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 162        dev = &rte_rawdevs[dev_id];
 163
 164        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_setup, -ENOTSUP);
 165        return (*dev->dev_ops->queue_setup)(dev, queue_id, queue_conf,
 166                        queue_conf_size);
 167}
 168
 169int
 170rte_rawdev_queue_release(uint16_t dev_id, uint16_t queue_id)
 171{
 172        struct rte_rawdev *dev;
 173
 174        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 175        dev = &rte_rawdevs[dev_id];
 176
 177        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_release, -ENOTSUP);
 178        return (*dev->dev_ops->queue_release)(dev, queue_id);
 179}
 180
 181uint16_t
 182rte_rawdev_queue_count(uint16_t dev_id)
 183{
 184        struct rte_rawdev *dev;
 185
 186        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 187        dev = &rte_rawdevs[dev_id];
 188
 189        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_count, -ENOTSUP);
 190        return (*dev->dev_ops->queue_count)(dev);
 191}
 192
 193int
 194rte_rawdev_get_attr(uint16_t dev_id,
 195                    const char *attr_name,
 196                    uint64_t *attr_value)
 197{
 198        struct rte_rawdev *dev;
 199
 200        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 201        dev = &rte_rawdevs[dev_id];
 202
 203        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->attr_get, -ENOTSUP);
 204        return (*dev->dev_ops->attr_get)(dev, attr_name, attr_value);
 205}
 206
 207int
 208rte_rawdev_set_attr(uint16_t dev_id,
 209                    const char *attr_name,
 210                    const uint64_t attr_value)
 211{
 212        struct rte_rawdev *dev;
 213
 214        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 215        dev = &rte_rawdevs[dev_id];
 216
 217        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->attr_set, -ENOTSUP);
 218        return (*dev->dev_ops->attr_set)(dev, attr_name, attr_value);
 219}
 220
 221int
 222rte_rawdev_enqueue_buffers(uint16_t dev_id,
 223                           struct rte_rawdev_buf **buffers,
 224                           unsigned int count,
 225                           rte_rawdev_obj_t context)
 226{
 227        struct rte_rawdev *dev;
 228
 229        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 230        dev = &rte_rawdevs[dev_id];
 231
 232        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->enqueue_bufs, -ENOTSUP);
 233        return (*dev->dev_ops->enqueue_bufs)(dev, buffers, count, context);
 234}
 235
 236int
 237rte_rawdev_dequeue_buffers(uint16_t dev_id,
 238                           struct rte_rawdev_buf **buffers,
 239                           unsigned int count,
 240                           rte_rawdev_obj_t context)
 241{
 242        struct rte_rawdev *dev;
 243
 244        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 245        dev = &rte_rawdevs[dev_id];
 246
 247        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dequeue_bufs, -ENOTSUP);
 248        return (*dev->dev_ops->dequeue_bufs)(dev, buffers, count, context);
 249}
 250
 251int
 252rte_rawdev_dump(uint16_t dev_id, FILE *f)
 253{
 254        struct rte_rawdev *dev;
 255
 256        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 257        dev = &rte_rawdevs[dev_id];
 258
 259        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dump, -ENOTSUP);
 260        return (*dev->dev_ops->dump)(dev, f);
 261}
 262
 263static int
 264xstats_get_count(uint16_t dev_id)
 265{
 266        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 267
 268        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_get_names, -ENOTSUP);
 269        return (*dev->dev_ops->xstats_get_names)(dev, NULL, 0);
 270}
 271
 272int
 273rte_rawdev_xstats_names_get(uint16_t dev_id,
 274                struct rte_rawdev_xstats_name *xstats_names,
 275                unsigned int size)
 276{
 277        const struct rte_rawdev *dev;
 278        int cnt_expected_entries;
 279
 280        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -ENODEV);
 281
 282        cnt_expected_entries = xstats_get_count(dev_id);
 283
 284        if (xstats_names == NULL || cnt_expected_entries < 0 ||
 285            (int)size < cnt_expected_entries || size <= 0)
 286                return cnt_expected_entries;
 287
 288        dev = &rte_rawdevs[dev_id];
 289
 290        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_get_names, -ENOTSUP);
 291        return (*dev->dev_ops->xstats_get_names)(dev, xstats_names, size);
 292}
 293
 294/* retrieve rawdev extended statistics */
 295int
 296rte_rawdev_xstats_get(uint16_t dev_id,
 297                      const unsigned int ids[],
 298                      uint64_t values[],
 299                      unsigned int n)
 300{
 301        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -ENODEV);
 302        const struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 303
 304        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_get, -ENOTSUP);
 305        return (*dev->dev_ops->xstats_get)(dev, ids, values, n);
 306}
 307
 308uint64_t
 309rte_rawdev_xstats_by_name_get(uint16_t dev_id,
 310                              const char *name,
 311                              unsigned int *id)
 312{
 313        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, 0);
 314        const struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 315        unsigned int temp = -1;
 316
 317        if (id != NULL)
 318                *id = (unsigned int)-1;
 319        else
 320                id = &temp; /* driver never gets a NULL value */
 321
 322        /* implemented by driver */
 323        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_get_by_name, -ENOTSUP);
 324        return (*dev->dev_ops->xstats_get_by_name)(dev, name, id);
 325}
 326
 327int
 328rte_rawdev_xstats_reset(uint16_t dev_id,
 329                        const uint32_t ids[], uint32_t nb_ids)
 330{
 331        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 332        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 333
 334        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_reset, -ENOTSUP);
 335        return (*dev->dev_ops->xstats_reset)(dev, ids, nb_ids);
 336}
 337
 338int
 339rte_rawdev_firmware_status_get(uint16_t dev_id, rte_rawdev_obj_t status_info)
 340{
 341        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 342        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 343
 344        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->firmware_status_get, -ENOTSUP);
 345        return (*dev->dev_ops->firmware_status_get)(dev, status_info);
 346}
 347
 348int
 349rte_rawdev_firmware_version_get(uint16_t dev_id, rte_rawdev_obj_t version_info)
 350{
 351        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 352        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 353
 354        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->firmware_version_get, -ENOTSUP);
 355        return (*dev->dev_ops->firmware_version_get)(dev, version_info);
 356}
 357
 358int
 359rte_rawdev_firmware_load(uint16_t dev_id, rte_rawdev_obj_t firmware_image)
 360{
 361        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 362        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 363
 364        if (!firmware_image)
 365                return -EINVAL;
 366
 367        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->firmware_load, -ENOTSUP);
 368        return (*dev->dev_ops->firmware_load)(dev, firmware_image);
 369}
 370
 371int
 372rte_rawdev_firmware_unload(uint16_t dev_id)
 373{
 374        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 375        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 376
 377        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->firmware_load, -ENOTSUP);
 378        return (*dev->dev_ops->firmware_unload)(dev);
 379}
 380
 381int
 382rte_rawdev_selftest(uint16_t dev_id)
 383{
 384        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 385        struct rte_rawdev *dev = &rte_rawdevs[dev_id];
 386
 387        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_selftest, -ENOTSUP);
 388        return (*dev->dev_ops->dev_selftest)(dev_id);
 389}
 390
 391int
 392rte_rawdev_start(uint16_t dev_id)
 393{
 394        struct rte_rawdev *dev;
 395        int diag;
 396
 397        RTE_RDEV_DEBUG("Start dev_id=%" PRIu8, dev_id);
 398
 399        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 400        dev = &rte_rawdevs[dev_id];
 401        if (dev->started != 0) {
 402                RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already started",
 403                             dev_id);
 404                return 0;
 405        }
 406
 407        if (dev->dev_ops->dev_start == NULL)
 408                goto mark_started;
 409
 410        diag = (*dev->dev_ops->dev_start)(dev);
 411        if (diag != 0)
 412                return diag;
 413
 414mark_started:
 415        dev->started = 1;
 416        return 0;
 417}
 418
 419void
 420rte_rawdev_stop(uint16_t dev_id)
 421{
 422        struct rte_rawdev *dev;
 423
 424        RTE_RDEV_DEBUG("Stop dev_id=%" PRIu8, dev_id);
 425
 426        RTE_RAWDEV_VALID_DEVID_OR_RET(dev_id);
 427        dev = &rte_rawdevs[dev_id];
 428
 429        if (dev->started == 0) {
 430                RTE_RDEV_ERR("Device with dev_id=%" PRIu8 "already stopped",
 431                        dev_id);
 432                return;
 433        }
 434
 435        if (dev->dev_ops->dev_stop == NULL)
 436                goto mark_stopped;
 437
 438        (*dev->dev_ops->dev_stop)(dev);
 439
 440mark_stopped:
 441        dev->started = 0;
 442}
 443
 444int
 445rte_rawdev_close(uint16_t dev_id)
 446{
 447        struct rte_rawdev *dev;
 448
 449        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 450        dev = &rte_rawdevs[dev_id];
 451
 452        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP);
 453        /* Device must be stopped before it can be closed */
 454        if (dev->started == 1) {
 455                RTE_RDEV_ERR("Device %u must be stopped before closing",
 456                             dev_id);
 457                return -EBUSY;
 458        }
 459
 460        return (*dev->dev_ops->dev_close)(dev);
 461}
 462
 463int
 464rte_rawdev_reset(uint16_t dev_id)
 465{
 466        struct rte_rawdev *dev;
 467
 468        RTE_RAWDEV_VALID_DEVID_OR_ERR_RET(dev_id, -EINVAL);
 469        dev = &rte_rawdevs[dev_id];
 470
 471        RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_reset, -ENOTSUP);
 472        /* Reset is not dependent on state of the device */
 473        return (*dev->dev_ops->dev_reset)(dev);
 474}
 475
 476static inline uint8_t
 477rte_rawdev_find_free_device_index(void)
 478{
 479        uint16_t dev_id;
 480
 481        for (dev_id = 0; dev_id < RTE_RAWDEV_MAX_DEVS; dev_id++) {
 482                if (rte_rawdevs[dev_id].attached ==
 483                                RTE_RAWDEV_DETACHED)
 484                        return dev_id;
 485        }
 486
 487        return RTE_RAWDEV_MAX_DEVS;
 488}
 489
 490struct rte_rawdev *
 491rte_rawdev_pmd_allocate(const char *name, size_t dev_priv_size, int socket_id)
 492{
 493        struct rte_rawdev *rawdev;
 494        uint16_t dev_id;
 495
 496        if (rte_rawdev_pmd_get_named_dev(name) != NULL) {
 497                RTE_RDEV_ERR("Event device with name %s already allocated!",
 498                             name);
 499                return NULL;
 500        }
 501
 502        dev_id = rte_rawdev_find_free_device_index();
 503        if (dev_id == RTE_RAWDEV_MAX_DEVS) {
 504                RTE_RDEV_ERR("Reached maximum number of raw devices");
 505                return NULL;
 506        }
 507
 508        rawdev = &rte_rawdevs[dev_id];
 509
 510        if (dev_priv_size > 0) {
 511                rawdev->dev_private = rte_zmalloc_socket("rawdev private",
 512                                     dev_priv_size,
 513                                     RTE_CACHE_LINE_SIZE,
 514                                     socket_id);
 515                if (!rawdev->dev_private) {
 516                        RTE_RDEV_ERR("Unable to allocate memory for rawdev");
 517                        return NULL;
 518                }
 519        }
 520
 521        rawdev->dev_id = dev_id;
 522        rawdev->socket_id = socket_id;
 523        rawdev->started = 0;
 524        strlcpy(rawdev->name, name, RTE_RAWDEV_NAME_MAX_LEN);
 525
 526        rawdev->attached = RTE_RAWDEV_ATTACHED;
 527        rawdev_globals.nb_devs++;
 528
 529        return rawdev;
 530}
 531
 532int
 533rte_rawdev_pmd_release(struct rte_rawdev *rawdev)
 534{
 535        int ret;
 536
 537        if (rawdev == NULL)
 538                return -EINVAL;
 539
 540        ret = rte_rawdev_close(rawdev->dev_id);
 541        if (ret < 0)
 542                return ret;
 543
 544        rawdev->attached = RTE_RAWDEV_DETACHED;
 545        rawdev_globals.nb_devs--;
 546
 547        rawdev->dev_id = 0;
 548        rawdev->socket_id = 0;
 549        rawdev->dev_ops = NULL;
 550        if (rawdev->dev_private) {
 551                rte_free(rawdev->dev_private);
 552                rawdev->dev_private = NULL;
 553        }
 554
 555        return 0;
 556}
 557
 558static int
 559handle_dev_list(const char *cmd __rte_unused,
 560                const char *params __rte_unused,
 561                struct rte_tel_data *d)
 562{
 563        int i;
 564
 565        rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
 566        for (i = 0; i < rawdev_globals.nb_devs; i++)
 567                if (rte_rawdevices[i].attached == RTE_RAWDEV_ATTACHED)
 568                        rte_tel_data_add_array_int(d, i);
 569        return 0;
 570}
 571
 572static int
 573handle_dev_xstats(const char *cmd __rte_unused,
 574                const char *params,
 575                struct rte_tel_data *d)
 576{
 577        uint64_t *rawdev_xstats;
 578        struct rte_rawdev_xstats_name *xstat_names;
 579        int dev_id, num_xstats, i, ret;
 580        unsigned int *ids;
 581        char *end_param;
 582
 583        if (params == NULL || strlen(params) == 0 || !isdigit(*params))
 584                return -1;
 585
 586        dev_id = strtoul(params, &end_param, 0);
 587        if (*end_param != '\0')
 588                RTE_RDEV_LOG(NOTICE,
 589                        "Extra parameters passed to rawdev telemetry command, ignoring");
 590        if (!rte_rawdev_pmd_is_valid_dev(dev_id))
 591                return -1;
 592
 593        num_xstats = xstats_get_count(dev_id);
 594        if (num_xstats < 0)
 595                return -1;
 596
 597        /* use one malloc for names, stats and ids */
 598        rawdev_xstats = malloc((sizeof(uint64_t) +
 599                        sizeof(struct rte_rawdev_xstats_name) +
 600                        sizeof(unsigned int)) * num_xstats);
 601        if (rawdev_xstats == NULL)
 602                return -1;
 603        xstat_names = (void *)&rawdev_xstats[num_xstats];
 604        ids = (void *)&xstat_names[num_xstats];
 605
 606        ret = rte_rawdev_xstats_names_get(dev_id, xstat_names, num_xstats);
 607        if (ret < 0 || ret > num_xstats) {
 608                free(rawdev_xstats);
 609                return -1;
 610        }
 611
 612        for (i = 0; i < num_xstats; i++)
 613                ids[i] = i;
 614
 615        ret = rte_rawdev_xstats_get(dev_id, ids, rawdev_xstats, num_xstats);
 616        if (ret < 0 || ret > num_xstats) {
 617                free(rawdev_xstats);
 618                return -1;
 619        }
 620
 621        rte_tel_data_start_dict(d);
 622        for (i = 0; i < num_xstats; i++)
 623                rte_tel_data_add_dict_u64(d, xstat_names[i].name,
 624                                rawdev_xstats[i]);
 625
 626        free(rawdev_xstats);
 627        return 0;
 628}
 629
 630RTE_LOG_REGISTER_DEFAULT(librawdev_logtype, INFO);
 631
 632RTE_INIT(librawdev_init_telemetry)
 633{
 634        rte_telemetry_register_cmd("/rawdev/list", handle_dev_list,
 635                        "Returns list of available rawdev ports. Takes no parameters");
 636        rte_telemetry_register_cmd("/rawdev/xstats", handle_dev_xstats,
 637                        "Returns the xstats for a rawdev port. Parameters: int port_id");
 638}
 639