xref: /illumos-gate/usr/src/test/nvme-tests/tests/unit/identify.c (revision 34bbc83afbf22a6f8e504cb99d76c97c017cb5f4)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2024 Oxide Computer Company
14  */
15 
16 /*
17  * NVMe Identify unit tests. This validates both fields and also whether certain
18  * cases are supported.
19  */
20 
21 #include <stdlib.h>
22 #include <sys/sysmacros.h>
23 #include <err.h>
24 
25 #include "nvme_unit.h"
26 
27 static const nvme_unit_field_test_t identify_field_tests[] = { {
28 	.nu_desc = "valid CNS (1.0) (1)",
29 	.nu_fields = nvme_identify_fields,
30 	.nu_index = NVME_ID_REQ_F_CNS,
31 	.nu_data = &nvme_ctrl_base_1v0,
32 	.nu_value = 0x0,
33 	.nu_ret = NVME_FIELD_ERR_OK
34 }, {
35 	.nu_desc = "valid CNS (1.0) (2)",
36 	.nu_fields = nvme_identify_fields,
37 	.nu_index = NVME_ID_REQ_F_CNS,
38 	.nu_data = &nvme_ctrl_base_1v0,
39 	.nu_value = 0x1,
40 	.nu_ret = NVME_FIELD_ERR_OK
41 }, {
42 	.nu_desc = "invalid CNS (1.0) (1)",
43 	.nu_fields = nvme_identify_fields,
44 	.nu_index = NVME_ID_REQ_F_CNS,
45 	.nu_data = &nvme_ctrl_base_1v0,
46 	.nu_value = 0x2,
47 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
48 }, {
49 	.nu_desc = "invalid CNS (1.0) (2)",
50 	.nu_fields = nvme_identify_fields,
51 	.nu_index = NVME_ID_REQ_F_CNS,
52 	.nu_data = &nvme_ctrl_base_1v0,
53 	.nu_value = 0x55,
54 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
55 }, {
56 	.nu_desc = "valid CNS (1.1) (1)",
57 	.nu_fields = nvme_identify_fields,
58 	.nu_index = NVME_ID_REQ_F_CNS,
59 	.nu_data = &nvme_ctrl_base_1v1,
60 	.nu_value = 0x0,
61 	.nu_ret = NVME_FIELD_ERR_OK
62 }, {
63 	.nu_desc = "valid CNS (1.1) (2)",
64 	.nu_fields = nvme_identify_fields,
65 	.nu_index = NVME_ID_REQ_F_CNS,
66 	.nu_data = &nvme_ctrl_base_1v1,
67 	.nu_value = 0x1,
68 	.nu_ret = NVME_FIELD_ERR_OK
69 }, {
70 	.nu_desc = "valid CNS (1.1) (3)",
71 	.nu_fields = nvme_identify_fields,
72 	.nu_index = NVME_ID_REQ_F_CNS,
73 	.nu_data = &nvme_ctrl_base_1v1,
74 	.nu_value = 0x2,
75 	.nu_ret = NVME_FIELD_ERR_OK
76 },  {
77 	.nu_desc = "valid CNS (1.1) (3)",
78 	.nu_fields = nvme_identify_fields,
79 	.nu_index = NVME_ID_REQ_F_CNS,
80 	.nu_data = &nvme_ctrl_base_1v1,
81 	.nu_value = 0x3,
82 	.nu_ret = NVME_FIELD_ERR_OK
83 },  {
84 	.nu_desc = "invalid CNS (1.1) (1)",
85 	.nu_fields = nvme_identify_fields,
86 	.nu_index = NVME_ID_REQ_F_CNS,
87 	.nu_data = &nvme_ctrl_base_1v1,
88 	.nu_value = 0x4,
89 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
90 }, {
91 	.nu_desc = "invalid CNS (1.1) (2)",
92 	.nu_fields = nvme_identify_fields,
93 	.nu_index = NVME_ID_REQ_F_CNS,
94 	.nu_data = &nvme_ctrl_base_1v1,
95 	.nu_value = 0x55,
96 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
97 }, {
98 	.nu_desc = "invalid CNS (1.1) (2)",
99 	.nu_fields = nvme_identify_fields,
100 	.nu_index = NVME_ID_REQ_F_CNS,
101 	.nu_data = &nvme_ctrl_base_1v1,
102 	.nu_value = 0x121,
103 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
104 }, {
105 	.nu_desc = "valid CNS (1.2) (1)",
106 	.nu_fields = nvme_identify_fields,
107 	.nu_index = NVME_ID_REQ_F_CNS,
108 	.nu_data = &nvme_ctrl_base_1v2,
109 	.nu_value = 0x0,
110 	.nu_ret = NVME_FIELD_ERR_OK
111 }, {
112 	.nu_desc = "valid CNS (1.2) (2)",
113 	.nu_fields = nvme_identify_fields,
114 	.nu_index = NVME_ID_REQ_F_CNS,
115 	.nu_data = &nvme_ctrl_base_1v2,
116 	.nu_value = 0xff,
117 	.nu_ret = NVME_FIELD_ERR_OK
118 }, {
119 	.nu_desc = "valid CNS (1.2) (3)",
120 	.nu_fields = nvme_identify_fields,
121 	.nu_index = NVME_ID_REQ_F_CNS,
122 	.nu_data = &nvme_ctrl_base_1v2,
123 	.nu_value = 0x74,
124 	.nu_ret = NVME_FIELD_ERR_OK
125 },  {
126 	.nu_desc = "valid CNS (1.2) (3)",
127 	.nu_fields = nvme_identify_fields,
128 	.nu_index = NVME_ID_REQ_F_CNS,
129 	.nu_data = &nvme_ctrl_base_1v2,
130 	.nu_value = 0x23,
131 	.nu_ret = NVME_FIELD_ERR_OK
132 },  {
133 	.nu_desc = "invalid CNS (1.2) (1)",
134 	.nu_fields = nvme_identify_fields,
135 	.nu_index = NVME_ID_REQ_F_CNS,
136 	.nu_data = &nvme_ctrl_base_1v2,
137 	.nu_value = 0x100,
138 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
139 }, {
140 	.nu_desc = "invalid CNS (1.2) (2)",
141 	.nu_fields = nvme_identify_fields,
142 	.nu_index = NVME_ID_REQ_F_CNS,
143 	.nu_data = &nvme_ctrl_base_1v2,
144 	.nu_value = 0x3223,
145 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
146 }, {
147 	.nu_desc = "invalid CNS (1.2) (2)",
148 	.nu_fields = nvme_identify_fields,
149 	.nu_index = NVME_ID_REQ_F_CNS,
150 	.nu_data = &nvme_ctrl_base_1v2,
151 	.nu_value = 0x121,
152 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
153 }, {
154 	.nu_desc = "valid nsid (1.0/1) (1)",
155 	.nu_fields = nvme_identify_fields,
156 	.nu_index = NVME_ID_REQ_F_NSID,
157 	.nu_data = &nvme_ctrl_base_1v0,
158 	.nu_value = 0x1,
159 	.nu_ret = NVME_FIELD_ERR_OK
160 }, {
161 	.nu_desc = "valid nsid (1.0/1) (2)",
162 	.nu_fields = nvme_identify_fields,
163 	.nu_index = NVME_ID_REQ_F_NSID,
164 	.nu_data = &nvme_ctrl_base_1v0,
165 	.nu_value = NVME_NSID_BCAST,
166 	.nu_ret = NVME_FIELD_ERR_OK
167 }, {
168 	/*
169 	 * The namespace ID for identify commands varies in its allowed values
170 	 * based on the particular CNS. Some commands allow for a namespace ID
171 	 * that has nothing to do with the controller's valid range.
172 	 */
173 	.nu_desc = "invalid nsid (1)",
174 	.nu_fields = nvme_identify_fields,
175 	.nu_index = NVME_ID_REQ_F_NSID,
176 	.nu_data = &nvme_ctrl_base_1v0,
177 	.nu_value = UINT64_MAX,
178 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
179 }, {
180 	.nu_desc = "invalid nsid (2)",
181 	.nu_fields = nvme_identify_fields,
182 	.nu_index = NVME_ID_REQ_F_NSID,
183 	.nu_data = &nvme_ctrl_base_1v0,
184 	.nu_value = 0x100000000,
185 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
186 }, {
187 	.nu_desc = "unsupported ctrlid (1)",
188 	.nu_fields = nvme_identify_fields,
189 	.nu_index = NVME_ID_REQ_F_CTRLID,
190 	.nu_data = &nvme_ctrl_base_1v0,
191 	.nu_value = 0x0,
192 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
193 }, {
194 	.nu_desc = "unsupported ctrlid (2)",
195 	.nu_fields = nvme_identify_fields,
196 	.nu_index = NVME_ID_REQ_F_CTRLID,
197 	.nu_data = &nvme_ctrl_base_1v1,
198 	.nu_value = 0x0,
199 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
200 }, {
201 	.nu_desc = "valid ctrlid (1)",
202 	.nu_fields = nvme_identify_fields,
203 	.nu_index = NVME_ID_REQ_F_CTRLID,
204 	.nu_data = &nvme_ctrl_base_1v2,
205 	.nu_value = 0x0,
206 	.nu_ret = NVME_FIELD_ERR_OK
207 }, {
208 	.nu_desc = "valid ctrlid (2)",
209 	.nu_fields = nvme_identify_fields,
210 	.nu_index = NVME_ID_REQ_F_CTRLID,
211 	.nu_data = &nvme_ctrl_ns_1v4,
212 	.nu_value = 0xffff,
213 	.nu_ret = NVME_FIELD_ERR_OK
214 }, {
215 	.nu_desc = "valid ctrlid (3)",
216 	.nu_fields = nvme_identify_fields,
217 	.nu_index = NVME_ID_REQ_F_CTRLID,
218 	.nu_data = &nvme_ctrl_base_1v2,
219 	.nu_value = 0x4334,
220 	.nu_ret = NVME_FIELD_ERR_OK
221 }, {
222 	.nu_desc = "invalid ctrlid (1)",
223 	.nu_fields = nvme_identify_fields,
224 	.nu_index = NVME_ID_REQ_F_CTRLID,
225 	.nu_data = &nvme_ctrl_base_1v2,
226 	.nu_value = 0x10000,
227 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
228 }, {
229 	.nu_desc = "invalid ctrlid (2)",
230 	.nu_fields = nvme_identify_fields,
231 	.nu_index = NVME_ID_REQ_F_CTRLID,
232 	.nu_data = &nvme_ctrl_base_1v2,
233 	.nu_value = 0x43210,
234 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
235 }, {
236 	.nu_desc = "valid buffer length",
237 	.nu_fields = nvme_identify_fields,
238 	.nu_index = NVME_ID_REQ_F_BUF,
239 	.nu_data = &nvme_ctrl_base_1v0,
240 	.nu_value = 0x1000,
241 	.nu_ret = NVME_FIELD_ERR_OK
242 }, {
243 	.nu_desc = "invalid buffer length (1)",
244 	.nu_fields = nvme_identify_fields,
245 	.nu_index = NVME_ID_REQ_F_BUF,
246 	.nu_data = &nvme_ctrl_base_1v0,
247 	.nu_value = 0xfff,
248 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
249 }, {
250 	.nu_desc = "invalid buffer length (2)",
251 	.nu_fields = nvme_identify_fields,
252 	.nu_index = NVME_ID_REQ_F_BUF,
253 	.nu_data = &nvme_ctrl_base_1v0,
254 	.nu_value = 0x1001,
255 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
256 } };
257 
258 typedef struct identify_impl_test {
259 	const char *iit_desc;
260 	uint32_t iit_cns;
261 	const nvme_valid_ctrl_data_t *iit_data;
262 	bool iit_impl;
263 } identify_impl_test_t;
264 
265 static const identify_impl_test_t identify_impl_tests[] = { {
266 	.iit_desc = "identify namespace supported (1.0)",
267 	.iit_cns = NVME_IDENTIFY_NSID,
268 	.iit_data = &nvme_ctrl_base_1v0,
269 	.iit_impl = true
270 }, {
271 	.iit_desc = "identify namespace supported (1.4 No NS)",
272 	.iit_cns = NVME_IDENTIFY_NSID,
273 	.iit_data = &nvme_ctrl_nons_1v4,
274 	.iit_impl = true
275 }, {
276 	.iit_desc = "identify namespace supported (2.0)",
277 	.iit_cns = NVME_IDENTIFY_NSID,
278 	.iit_data = &nvme_ctrl_ns_2v0,
279 	.iit_impl = true
280 }, {
281 	.iit_desc = "identify controller supported (1.0)",
282 	.iit_cns = NVME_IDENTIFY_CTRL,
283 	.iit_data = &nvme_ctrl_base_1v0,
284 	.iit_impl = true
285 }, {
286 	.iit_desc = "identify controller supported (1.4 No NS)",
287 	.iit_cns = NVME_IDENTIFY_CTRL,
288 	.iit_data = &nvme_ctrl_nons_1v4,
289 	.iit_impl = true
290 }, {
291 	.iit_desc = "identify controller supported (2.0)",
292 	.iit_cns = NVME_IDENTIFY_CTRL,
293 	.iit_data = &nvme_ctrl_ns_2v0,
294 	.iit_impl = true
295 }, {
296 	.iit_desc = "identify controller supported (1.2 No NS)",
297 	.iit_cns = NVME_IDENTIFY_CTRL,
298 	.iit_data = &nvme_ctrl_base_1v2,
299 	.iit_impl = true
300 }, {
301 	.iit_desc = "active namespace list unsupported (1.0)",
302 	.iit_cns = NVME_IDENTIFY_NSID_LIST,
303 	.iit_data = &nvme_ctrl_base_1v0,
304 	.iit_impl = false
305 }, {
306 	.iit_desc = "active namespace list supported (1.1)",
307 	.iit_cns = NVME_IDENTIFY_NSID_LIST,
308 	.iit_data = &nvme_ctrl_base_1v1,
309 	.iit_impl = true
310 }, {
311 	.iit_desc = "active namespace list supported (1.3 No NS)",
312 	.iit_cns = NVME_IDENTIFY_NSID_LIST,
313 	.iit_data = &nvme_ctrl_nons_1v3,
314 	.iit_impl = true
315 }, {
316 	.iit_desc = "active namespace list supported (1.4)",
317 	.iit_cns = NVME_IDENTIFY_NSID_LIST,
318 	.iit_data = &nvme_ctrl_ns_1v4,
319 	.iit_impl = true
320 }, {
321 	.iit_desc = "namespace id desc unsupported (1.0)",
322 	.iit_cns = NVME_IDENTIFY_NSID_DESC,
323 	.iit_data = &nvme_ctrl_base_1v0,
324 	.iit_impl = false
325 }, {
326 	.iit_desc = "namespace id desc unsupported (1.1)",
327 	.iit_cns = NVME_IDENTIFY_NSID_DESC,
328 	.iit_data = &nvme_ctrl_base_1v1,
329 	.iit_impl = false
330 }, {
331 	.iit_desc = "namespace id desc supported (1.3 No NS)",
332 	.iit_cns = NVME_IDENTIFY_NSID_DESC,
333 	.iit_data = &nvme_ctrl_nons_1v3,
334 	.iit_impl = true
335 }, {
336 	.iit_desc = "namespace id desc supported (1.3)",
337 	.iit_cns = NVME_IDENTIFY_NSID_DESC,
338 	.iit_data = &nvme_ctrl_ns_1v3,
339 	.iit_impl = true
340 }, {
341 	.iit_desc = "namespace id desc supported (1.4)",
342 	.iit_cns = NVME_IDENTIFY_NSID_DESC,
343 	.iit_data = &nvme_ctrl_ns_1v4,
344 	.iit_impl = true
345 }, {
346 	.iit_desc = "allocated namespace list unsupported (1.0)",
347 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC_LIST,
348 	.iit_data = &nvme_ctrl_base_1v0,
349 	.iit_impl = false
350 }, {
351 	.iit_desc = "allocated namespace list unsupported (1.2 No NS)",
352 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC_LIST,
353 	.iit_data = &nvme_ctrl_base_1v2,
354 	.iit_impl = false
355 }, {
356 	.iit_desc = "allocated namespace list unsupported (1.4 No NS)",
357 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC_LIST,
358 	.iit_data = &nvme_ctrl_nons_1v4,
359 	.iit_impl = false
360 }, {
361 	.iit_desc = "allocated namespace list supported (1.2)",
362 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC_LIST,
363 	.iit_data = &nvme_ctrl_ns_1v2,
364 	.iit_impl = true
365 }, {
366 	.iit_desc = "allocated namespace list supported (1.4)",
367 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC_LIST,
368 	.iit_data = &nvme_ctrl_ns_1v4,
369 	.iit_impl = true
370 }, {
371 	.iit_desc = "identify allocated namespace unsupported (1.0)",
372 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC,
373 	.iit_data = &nvme_ctrl_base_1v0,
374 	.iit_impl = false
375 }, {
376 	.iit_desc = "identify allocated namespace unsupported (1.2 No NS)",
377 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC,
378 	.iit_data = &nvme_ctrl_base_1v2,
379 	.iit_impl = false
380 }, {
381 	.iit_desc = "identify allocated namespace unsupported (1.4 No NS)",
382 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC,
383 	.iit_data = &nvme_ctrl_nons_1v4,
384 	.iit_impl = false
385 }, {
386 	.iit_desc = "identify allocated namespace supported (1.2)",
387 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC,
388 	.iit_data = &nvme_ctrl_ns_1v2,
389 	.iit_impl = true
390 }, {
391 	.iit_desc = "identify allocated namespace supported (1.4)",
392 	.iit_cns = NVME_IDENTIFY_NSID_ALLOC,
393 	.iit_data = &nvme_ctrl_ns_1v4,
394 	.iit_impl = true
395 }, {
396 	.iit_desc = "controller list by NS unsupported (1.0)",
397 	.iit_cns = NVME_IDENTIFY_NSID_CTRL_LIST,
398 	.iit_data = &nvme_ctrl_base_1v0,
399 	.iit_impl = false
400 }, {
401 	.iit_desc = "controller list by NS unsupported (1.2 No NS)",
402 	.iit_cns = NVME_IDENTIFY_NSID_CTRL_LIST,
403 	.iit_data = &nvme_ctrl_base_1v2,
404 	.iit_impl = false
405 }, {
406 	.iit_desc = "controller list by NS unsupported (1.4 No NS)",
407 	.iit_cns = NVME_IDENTIFY_NSID_CTRL_LIST,
408 	.iit_data = &nvme_ctrl_nons_1v4,
409 	.iit_impl = false
410 }, {
411 	.iit_desc = "controller list by NS supported (1.2)",
412 	.iit_cns = NVME_IDENTIFY_NSID_CTRL_LIST,
413 	.iit_data = &nvme_ctrl_ns_1v2,
414 	.iit_impl = true
415 }, {
416 	.iit_desc = "controller list by NS supported (1.4)",
417 	.iit_cns = NVME_IDENTIFY_NSID_CTRL_LIST,
418 	.iit_data = &nvme_ctrl_ns_1v4,
419 	.iit_impl = true
420 }, {
421 	.iit_desc = "controller list by NVM unsupported (1.0)",
422 	.iit_cns = NVME_IDENTIFY_CTRL_LIST,
423 	.iit_data = &nvme_ctrl_base_1v0,
424 	.iit_impl = false
425 }, {
426 	.iit_desc = "controller list by NVM unsupported (1.2 No NS)",
427 	.iit_cns = NVME_IDENTIFY_CTRL_LIST,
428 	.iit_data = &nvme_ctrl_base_1v2,
429 	.iit_impl = false
430 }, {
431 	.iit_desc = "controller list by NVM unsupported (1.4 No NS)",
432 	.iit_cns = NVME_IDENTIFY_CTRL_LIST,
433 	.iit_data = &nvme_ctrl_nons_1v4,
434 	.iit_impl = false
435 }, {
436 	.iit_desc = "controller list by NVM supported (1.2)",
437 	.iit_cns = NVME_IDENTIFY_CTRL_LIST,
438 	.iit_data = &nvme_ctrl_ns_1v2,
439 	.iit_impl = true
440 }, {
441 	.iit_desc = "controller list by NVM supported (1.4)",
442 	.iit_cns = NVME_IDENTIFY_CTRL_LIST,
443 	.iit_data = &nvme_ctrl_ns_1v4,
444 	.iit_impl = true
445 } };
446 
447 static bool
448 identify_impl_test_one(const identify_impl_test_t *test)
449 {
450 	const nvme_identify_info_t *info = NULL;
451 	bool impl;
452 
453 	for (size_t i = 0; i < nvme_identify_ncmds; i++) {
454 		if (nvme_identify_cmds[i].nii_csi == NVME_CSI_NVM &&
455 		    nvme_identify_cmds[i].nii_cns == test->iit_cns) {
456 			info = &nvme_identify_cmds[i];
457 			break;
458 		}
459 	}
460 
461 	if (info == NULL) {
462 		errx(EXIT_FAILURE, "malformed test %s: cannot find CNS %u",
463 		    test->iit_desc, test->iit_cns);
464 	}
465 
466 	impl = nvme_identify_info_supported(info, test->iit_data);
467 	if (impl != test->iit_impl) {
468 		warnx("TEST FAILED: %s: expected impl %u, found %u",
469 		    test->iit_desc, test->iit_impl, impl);
470 		return (false);
471 	}
472 
473 	(void) printf("TEST PASSED: %s: got correct impl\n", test->iit_desc);
474 	return (true);
475 }
476 
477 int
478 main(void)
479 {
480 	int ret = EXIT_SUCCESS;
481 
482 	if (!nvme_unit_field_test(identify_field_tests,
483 	    ARRAY_SIZE(identify_field_tests))) {
484 		ret = EXIT_FAILURE;
485 	}
486 
487 	for (size_t i = 0; i < ARRAY_SIZE(identify_impl_tests); i++) {
488 		if (!identify_impl_test_one(&identify_impl_tests[i])) {
489 			ret = EXIT_FAILURE;
490 		}
491 	}
492 
493 	if (ret == EXIT_SUCCESS) {
494 		(void) printf("All tests passed successfully!\n");
495 	}
496 
497 	return (ret);
498 }
499