xref: /dpdk/app/test/test_devargs.c (revision 148c51a3deff2ea4be3bc3fd0cb045a96f28ec64)
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
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);
46d05c2dccSXueming Li 		rte_kvargs_free(kvlist);
47a4975cd2SXueming Li 		return -1;
48a4975cd2SXueming Li 	}
49d05c2dccSXueming 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
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 &&
101*148c51a3SDavid Marchand 		    strcmp(rte_bus_name(da.bus), list[i].bus) != 0) {
102a4975cd2SXueming Li 			printf("rte_devargs_parse(%s) bus name (%s) not expected (%s)\n",
103*148c51a3SDavid Marchand 			       list[i].devargs, rte_bus_name(da.bus), 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
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
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
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