1a4975cd2SXueming Li /* SPDX-License-Identifier: BSD-3-Clause
2a4975cd2SXueming Li * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3a4975cd2SXueming Li */
4a4975cd2SXueming Li
5a4975cd2SXueming Li #include <stdlib.h>
6a4975cd2SXueming Li #include <stdio.h>
7a4975cd2SXueming Li #include <string.h>
8a4975cd2SXueming Li
9a4975cd2SXueming Li #include <rte_common.h>
10a4975cd2SXueming Li #include <rte_devargs.h>
11a4975cd2SXueming Li #include <rte_kvargs.h>
12a4975cd2SXueming Li #include <rte_bus.h>
13a4975cd2SXueming Li #include <rte_class.h>
14a4975cd2SXueming Li
15a4975cd2SXueming Li #include "test.h"
16a4975cd2SXueming Li
17a4975cd2SXueming Li /* Check layer arguments. */
18a4975cd2SXueming Li static int
test_args(const char * devargs,const char * layer,const char * args,const int n)19a4975cd2SXueming Li test_args(const char *devargs, const char *layer, const char *args, const int n)
20a4975cd2SXueming Li {
21a4975cd2SXueming Li struct rte_kvargs *kvlist;
22a4975cd2SXueming Li
23a4975cd2SXueming Li if (n == 0) {
24a4975cd2SXueming Li if (args != NULL && strlen(args) > 0) {
25a4975cd2SXueming Li printf("rte_devargs_parse(%s) %s args parsed (not expected)\n",
26a4975cd2SXueming Li devargs, layer);
27a4975cd2SXueming Li return -1;
28a4975cd2SXueming Li } else {
29a4975cd2SXueming Li return 0;
30a4975cd2SXueming Li }
31a4975cd2SXueming Li }
32a4975cd2SXueming Li if (args == NULL) {
33a4975cd2SXueming Li printf("rte_devargs_parse(%s) %s args not parsed\n",
34a4975cd2SXueming Li devargs, layer);
35a4975cd2SXueming Li return -1;
36a4975cd2SXueming Li }
37a4975cd2SXueming Li kvlist = rte_kvargs_parse(args, NULL);
38a4975cd2SXueming Li if (kvlist == NULL) {
39a4975cd2SXueming Li printf("rte_devargs_parse(%s) %s_str: %s not parsed\n",
40a4975cd2SXueming Li devargs, layer, args);
41a4975cd2SXueming Li return -1;
42a4975cd2SXueming Li }
43a4975cd2SXueming Li if ((int)kvlist->count != n) {
44a4975cd2SXueming Li printf("rte_devargs_parse(%s) %s_str: %s kv number %u, not %d\n",
45a4975cd2SXueming Li devargs, layer, args, kvlist->count, n);
46*d05c2dccSXueming Li rte_kvargs_free(kvlist);
47a4975cd2SXueming Li return -1;
48a4975cd2SXueming Li }
49*d05c2dccSXueming Li rte_kvargs_free(kvlist);
50a4975cd2SXueming Li return 0;
51a4975cd2SXueming Li }
52a4975cd2SXueming Li
53a4975cd2SXueming Li struct devargs_case {
54a4975cd2SXueming Li const char *devargs;
55a4975cd2SXueming Li int bus_kv;
56a4975cd2SXueming Li int class_kv;
57a4975cd2SXueming Li int driver_kv;
58a4975cd2SXueming Li const char *bus;
59a4975cd2SXueming Li const char *name;
60a4975cd2SXueming Li const char *class;
61a4975cd2SXueming Li };
62a4975cd2SXueming Li
63a4975cd2SXueming Li static int
test_valid_devargs_cases(const struct devargs_case * list,size_t n)64a4975cd2SXueming Li test_valid_devargs_cases(const struct devargs_case *list, size_t n)
65a4975cd2SXueming Li {
66a4975cd2SXueming Li struct rte_devargs da;
67a4975cd2SXueming Li uint32_t i;
68a4975cd2SXueming Li int ret;
69a4975cd2SXueming Li int fail = TEST_SUCCESS;
70a4975cd2SXueming Li struct rte_bus *pci_bus = rte_bus_find_by_name("pci");
71a4975cd2SXueming Li struct rte_bus *vdev_bus = rte_bus_find_by_name("vdev");
72a4975cd2SXueming Li struct rte_class *eth_class = rte_class_find_by_name("eth");
73a4975cd2SXueming Li
74a4975cd2SXueming Li for (i = 0; i < n; i++) {
75a4975cd2SXueming Li if (pci_bus == NULL && list[i].bus != NULL &&
76a4975cd2SXueming Li strcmp(list[i].bus, "pci") == 0)
77a4975cd2SXueming Li continue;
78a4975cd2SXueming Li if (vdev_bus == NULL && list[i].bus != NULL &&
79a4975cd2SXueming Li strcmp(list[i].bus, "vdev") == 0)
80a4975cd2SXueming Li continue;
81a4975cd2SXueming Li if (eth_class == NULL && list[i].class != NULL &&
82a4975cd2SXueming Li strcmp(list[i].class, "eth") == 0)
83a4975cd2SXueming Li continue;
84a4975cd2SXueming Li memset(&da, 0, sizeof(da));
85a4975cd2SXueming Li ret = rte_devargs_parse(&da, list[i].devargs);
86a4975cd2SXueming Li if (ret < 0) {
87a4975cd2SXueming Li printf("rte_devargs_parse(%s) returned %d (but should not)\n",
88a4975cd2SXueming Li list[i].devargs, ret);
89a4975cd2SXueming Li goto fail;
90a4975cd2SXueming Li }
91a4975cd2SXueming Li if ((list[i].bus_kv > 0 || list[i].bus != NULL) &&
92a4975cd2SXueming Li da.bus == NULL) {
93a4975cd2SXueming Li printf("rte_devargs_parse(%s) bus not parsed\n",
94a4975cd2SXueming Li list[i].devargs);
95a4975cd2SXueming Li goto fail;
96a4975cd2SXueming Li }
97a4975cd2SXueming Li if (test_args(list[i].devargs, "bus", da.bus_str,
98a4975cd2SXueming Li list[i].bus_kv) != 0)
99a4975cd2SXueming Li goto fail;
100a4975cd2SXueming Li if (list[i].bus != NULL &&
101a4975cd2SXueming Li strcmp(da.bus->name, list[i].bus) != 0) {
102a4975cd2SXueming Li printf("rte_devargs_parse(%s) bus name (%s) not expected (%s)\n",
103a4975cd2SXueming Li list[i].devargs, da.bus->name, list[i].bus);
104a4975cd2SXueming Li goto fail;
105a4975cd2SXueming Li }
106a4975cd2SXueming Li if ((list[i].class_kv > 0 || list[i].class != NULL) &&
107a4975cd2SXueming Li da.cls == NULL) {
108a4975cd2SXueming Li printf("rte_devargs_parse(%s) class not parsed\n",
109a4975cd2SXueming Li list[i].devargs);
110a4975cd2SXueming Li goto fail;
111a4975cd2SXueming Li }
112a4975cd2SXueming Li if (test_args(list[i].devargs, "class", da.cls_str,
113a4975cd2SXueming Li list[i].class_kv) != 0)
114a4975cd2SXueming Li goto fail;
115a4975cd2SXueming Li if (list[i].class != NULL &&
116a4975cd2SXueming Li strcmp(da.cls->name, list[i].class) != 0) {
117a4975cd2SXueming Li printf("rte_devargs_parse(%s) class name (%s) not expected (%s)\n",
118a4975cd2SXueming Li list[i].devargs, da.cls->name, list[i].class);
119a4975cd2SXueming Li goto fail;
120a4975cd2SXueming Li }
121a4975cd2SXueming Li if (test_args(list[i].devargs, "driver", da.drv_str,
122a4975cd2SXueming Li list[i].driver_kv) != 0)
123a4975cd2SXueming Li goto fail;
124a4975cd2SXueming Li if (list[i].name != NULL &&
125a4975cd2SXueming Li strcmp(da.name, list[i].name) != 0) {
126a4975cd2SXueming Li printf("rte_devargs_parse(%s) device name (%s) not expected (%s)\n",
127a4975cd2SXueming Li list[i].devargs, da.name, list[i].name);
128a4975cd2SXueming Li goto fail;
129a4975cd2SXueming Li }
130a4975cd2SXueming Li goto cleanup;
131a4975cd2SXueming Li fail:
132a4975cd2SXueming Li fail = TEST_FAILED;
133a4975cd2SXueming Li cleanup:
134a4975cd2SXueming Li rte_devargs_reset(&da);
135a4975cd2SXueming Li }
136a4975cd2SXueming Li return fail;
137a4975cd2SXueming Li }
138a4975cd2SXueming Li
139a4975cd2SXueming Li /* Test several valid cases */
140a4975cd2SXueming Li static int
test_valid_devargs(void)141a4975cd2SXueming Li test_valid_devargs(void)
142a4975cd2SXueming Li {
143a4975cd2SXueming Li static const struct devargs_case list[] = {
144a4975cd2SXueming Li /* Global devargs syntax: */
145a4975cd2SXueming Li { "bus=pci",
146a4975cd2SXueming Li 1, 0, 0, "pci", NULL, NULL},
147a4975cd2SXueming Li { "class=eth",
148a4975cd2SXueming Li 0, 1, 0, NULL, NULL, "eth" },
149a4975cd2SXueming Li { "bus=pci,addr=1:2.3/class=eth/driver=abc,k0=v0",
150a4975cd2SXueming Li 2, 1, 2, "pci", "0000:01:02.3", "eth" },
151a4975cd2SXueming Li { "bus=vdev,name=/dev/file/name/class=eth",
152a4975cd2SXueming Li 2, 1, 0, "vdev", "/dev/file/name", "eth" },
153a4975cd2SXueming Li { "bus=vdev,name=/class/bus/path/class=eth",
154a4975cd2SXueming Li 2, 1, 0, "vdev", "/class/bus/path", "eth" },
155a4975cd2SXueming Li { "bus=vdev,name=///dblslsh/class=eth",
156a4975cd2SXueming Li 2, 1, 0, "vdev", "///dblslsh", "eth" },
157a4975cd2SXueming Li /* Legacy devargs syntax: */
158a4975cd2SXueming Li { "1:2.3", 0, 0, 0,
159a4975cd2SXueming Li "pci", "1:2.3", NULL },
160a4975cd2SXueming Li { "pci:1:2.3,k0=v0",
161a4975cd2SXueming Li 0, 0, 1, "pci", "1:2.3", NULL },
162a4975cd2SXueming Li };
163a4975cd2SXueming Li static const struct devargs_case legacy_ring_list[] = {
164a4975cd2SXueming Li { "net_ring0",
165a4975cd2SXueming Li 0, 0, 0, "vdev", "net_ring0", NULL },
166a4975cd2SXueming Li { "net_ring0,iface=test,path=/class/bus/,queues=1",
167a4975cd2SXueming Li 0, 0, 3, "vdev", "net_ring0", NULL },
168a4975cd2SXueming Li };
169a4975cd2SXueming Li struct rte_bus *vdev_bus = rte_bus_find_by_name("vdev");
170a4975cd2SXueming Li int ret;
171a4975cd2SXueming Li
172a4975cd2SXueming Li ret = test_valid_devargs_cases(list, RTE_DIM(list));
173a4975cd2SXueming Li if (vdev_bus != NULL && vdev_bus->parse("net_ring0", NULL) == 0)
174a4975cd2SXueming Li /* Ring vdev driver enabled. */
175a4975cd2SXueming Li ret |= test_valid_devargs_cases(legacy_ring_list,
176a4975cd2SXueming Li RTE_DIM(legacy_ring_list));
177a4975cd2SXueming Li return ret;
178a4975cd2SXueming Li }
179a4975cd2SXueming Li
180a4975cd2SXueming Li /* Test several invalid cases */
181a4975cd2SXueming Li static int
test_invalid_devargs(void)182a4975cd2SXueming Li test_invalid_devargs(void)
183a4975cd2SXueming Li {
184a4975cd2SXueming Li static const char * const list[] = {
185a4975cd2SXueming Li "bus=wrong-bus",
186a4975cd2SXueming Li "class=wrong-class"};
187a4975cd2SXueming Li struct rte_devargs da;
188a4975cd2SXueming Li uint32_t i;
189a4975cd2SXueming Li int ret;
190a4975cd2SXueming Li int fail = 0;
191a4975cd2SXueming Li
192a4975cd2SXueming Li for (i = 0; i < RTE_DIM(list); i++) {
193a4975cd2SXueming Li ret = rte_devargs_parse(&da, list[i]);
194a4975cd2SXueming Li if (ret >= 0) {
195a4975cd2SXueming Li printf("rte_devargs_parse(%s) returned %d (but should not)\n",
196a4975cd2SXueming Li list[i], ret);
197a4975cd2SXueming Li fail = ret;
198a4975cd2SXueming Li }
199a4975cd2SXueming Li rte_devargs_reset(&da);
200a4975cd2SXueming Li }
201a4975cd2SXueming Li return fail;
202a4975cd2SXueming Li }
203a4975cd2SXueming Li
204a4975cd2SXueming Li static int
test_devargs(void)205a4975cd2SXueming Li test_devargs(void)
206a4975cd2SXueming Li {
207a4975cd2SXueming Li printf("== test valid case ==\n");
208a4975cd2SXueming Li if (test_valid_devargs() < 0)
209a4975cd2SXueming Li return -1;
210a4975cd2SXueming Li printf("== test invalid case ==\n");
211a4975cd2SXueming Li if (test_invalid_devargs() < 0)
212a4975cd2SXueming Li return -1;
213a4975cd2SXueming Li return 0;
214a4975cd2SXueming Li }
215a4975cd2SXueming Li
216a4975cd2SXueming Li REGISTER_TEST_COMMAND(devargs_autotest, test_devargs);
217