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