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