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  * Various unit tests of the common NVMe log validation code. We focus on field
18  * validation, scope determination, size, and support determination.
19  */
20 
21 #include <stdlib.h>
22 #include <sys/sysmacros.h>
23 #include <stdio.h>
24 #include <strings.h>
25 #include <err.h>
26 
27 #include "nvme_unit.h"
28 
29 static const nvme_unit_field_test_t log_field_tests[] = { {
30 	.nu_desc = "invalid lid value (1)",
31 	.nu_fields = nvme_log_fields,
32 	.nu_index = NVME_LOG_REQ_FIELD_LID,
33 	.nu_data = &nvme_ctrl_base_1v0,
34 	.nu_value = 0x123456,
35 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
36 }, {
37 	.nu_desc = "invalid lid value (2)",
38 	.nu_fields = nvme_log_fields,
39 	.nu_index = NVME_LOG_REQ_FIELD_LID,
40 	.nu_data = &nvme_ctrl_base_1v0,
41 	.nu_value = 0x100,
42 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
43 }, {
44 	.nu_desc = "valid lid (1)",
45 	.nu_fields = nvme_log_fields,
46 	.nu_index = NVME_LOG_REQ_FIELD_LID,
47 	.nu_data = &nvme_ctrl_base_1v0,
48 	.nu_value = 0x00,
49 	.nu_ret = NVME_FIELD_ERR_OK
50 }, {
51 	.nu_desc = "valid lid (2)",
52 	.nu_fields = nvme_log_fields,
53 	.nu_index = NVME_LOG_REQ_FIELD_LID,
54 	.nu_data = &nvme_ctrl_base_1v0,
55 	.nu_value = 0xff,
56 	.nu_ret = NVME_FIELD_ERR_OK
57 }, {
58 	.nu_desc = "invalid lsp (vers)",
59 	.nu_fields = nvme_log_fields,
60 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
61 	.nu_data = &nvme_ctrl_base_1v0,
62 	.nu_value = 0x0,
63 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
64 }, {
65 	.nu_desc = "unsupported lsp",
66 	.nu_fields = nvme_log_fields,
67 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
68 	.nu_data = &nvme_ctrl_base_1v0,
69 	.nu_value = 0x0,
70 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
71 }, {
72 	.nu_desc = "invalid lsp (1)",
73 	.nu_fields = nvme_log_fields,
74 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
75 	.nu_data = &nvme_ctrl_ns_1v4,
76 	.nu_value = 0x7777,
77 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
78 }, {
79 	.nu_desc = "invalid lsp (2)",
80 	.nu_fields = nvme_log_fields,
81 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
82 	.nu_data = &nvme_ctrl_ns_2v0,
83 	.nu_value = 0x7777,
84 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
85 }, {
86 	.nu_desc = "invalid lsp (1.x)",
87 	.nu_fields = nvme_log_fields,
88 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
89 	.nu_data = &nvme_ctrl_ns_1v4,
90 	.nu_value = 0x10,
91 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
92 }, {
93 	.nu_desc = "invalid lsp (2.x)",
94 	.nu_fields = nvme_log_fields,
95 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
96 	.nu_data = &nvme_ctrl_ns_2v0,
97 	.nu_value = 0x100,
98 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
99 }, {
100 	.nu_desc = "invalid lsp (2.x)",
101 	.nu_fields = nvme_log_fields,
102 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
103 	.nu_data = &nvme_ctrl_ns_2v0,
104 	.nu_value = 0x80,
105 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
106 }, {
107 	.nu_desc = "valid lsp (1.x) (1)",
108 	.nu_fields = nvme_log_fields,
109 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
110 	.nu_data = &nvme_ctrl_ns_1v4,
111 	.nu_value = 0x7,
112 	.nu_ret = NVME_FIELD_ERR_OK
113 }, {
114 	.nu_desc = "valid lsp (1.x) (2)",
115 	.nu_fields = nvme_log_fields,
116 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
117 	.nu_data = &nvme_ctrl_ns_1v4,
118 	.nu_value = 0x2,
119 	.nu_ret = NVME_FIELD_ERR_OK
120 }, {
121 	.nu_desc = "valid lsp (1.x) (3)",
122 	.nu_fields = nvme_log_fields,
123 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
124 	.nu_data = &nvme_ctrl_ns_1v4,
125 	.nu_value = 0x0,
126 	.nu_ret = NVME_FIELD_ERR_OK
127 }, {
128 	.nu_desc = "valid lsp (2.x) (1)",
129 	.nu_fields = nvme_log_fields,
130 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
131 	.nu_data = &nvme_ctrl_ns_2v0,
132 	.nu_value = 0x7,
133 	.nu_ret = NVME_FIELD_ERR_OK
134 }, {
135 	.nu_desc = "valid lsp (2.x) (2)",
136 	.nu_fields = nvme_log_fields,
137 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
138 	.nu_data = &nvme_ctrl_ns_2v0,
139 	.nu_value = 0x2,
140 	.nu_ret = NVME_FIELD_ERR_OK
141 }, {
142 	.nu_desc = "valid lsp (2.x) (3)",
143 	.nu_fields = nvme_log_fields,
144 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
145 	.nu_data = &nvme_ctrl_ns_2v0,
146 	.nu_value = 0x0,
147 	.nu_ret = NVME_FIELD_ERR_OK
148 }, {
149 	.nu_desc = "valid lsp (2.x) (4)",
150 	.nu_fields = nvme_log_fields,
151 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
152 	.nu_data = &nvme_ctrl_ns_2v0,
153 	.nu_value = 0x7f,
154 	.nu_ret = NVME_FIELD_ERR_OK
155 }, {
156 	.nu_desc = "valid lsp (2.x) (4)",
157 	.nu_fields = nvme_log_fields,
158 	.nu_index = NVME_LOG_REQ_FIELD_LSP,
159 	.nu_data = &nvme_ctrl_ns_2v0,
160 	.nu_value = 0x23,
161 	.nu_ret = NVME_FIELD_ERR_OK
162 }, {
163 	.nu_desc = "unsupported lsi",
164 	.nu_fields = nvme_log_fields,
165 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
166 	.nu_data = &nvme_ctrl_base_1v0,
167 	.nu_value = 0x0,
168 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
169 }, {
170 	.nu_desc = "invalid lsi (1)",
171 	.nu_fields = nvme_log_fields,
172 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
173 	.nu_data = &nvme_ctrl_ns_1v4,
174 	.nu_value = 0x10000,
175 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
176 }, {
177 	.nu_desc = "invalid lsi (2)",
178 	.nu_fields = nvme_log_fields,
179 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
180 	.nu_data = &nvme_ctrl_ns_1v4,
181 	.nu_value = 0x123321,
182 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
183 }, {
184 	.nu_desc = "valid lsi (1)",
185 	.nu_fields = nvme_log_fields,
186 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
187 	.nu_data = &nvme_ctrl_ns_1v4,
188 	.nu_value = 0x0,
189 	.nu_ret = NVME_FIELD_ERR_OK
190 }, {
191 	.nu_desc = "valid lsi (2)",
192 	.nu_fields = nvme_log_fields,
193 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
194 	.nu_data = &nvme_ctrl_ns_1v4,
195 	.nu_value = 0xffff,
196 	.nu_ret = NVME_FIELD_ERR_OK
197 }, {
198 	.nu_desc = "valid lsi (3)",
199 	.nu_fields = nvme_log_fields,
200 	.nu_index = NVME_LOG_REQ_FIELD_LSI,
201 	.nu_data = &nvme_ctrl_ns_1v4,
202 	.nu_value = 0x5445,
203 	.nu_ret = NVME_FIELD_ERR_OK
204 }, {
205 	.nu_desc = "invalid size (1.0) (1)",
206 	.nu_fields = nvme_log_fields,
207 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
208 	.nu_data = &nvme_ctrl_base_1v0,
209 	.nu_value = 0x4004,
210 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
211 }, {
212 	.nu_desc = "invalid size (1.0) (2)",
213 	.nu_fields = nvme_log_fields,
214 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
215 	.nu_data = &nvme_ctrl_base_1v0,
216 	.nu_value = 0x76543210,
217 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
218 }, {
219 	.nu_desc = "invalid size (1.0) (3)",
220 	.nu_fields = nvme_log_fields,
221 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
222 	.nu_data = &nvme_ctrl_base_1v0,
223 	.nu_value = 0x0,
224 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
225 }, {
226 	.nu_desc = "bad alignment (1.0) (1)",
227 	.nu_fields = nvme_log_fields,
228 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
229 	.nu_data = &nvme_ctrl_base_1v0,
230 	.nu_value = 0x3,
231 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
232 }, {
233 	.nu_desc = "bad alignment (1.0) (2)",
234 	.nu_fields = nvme_log_fields,
235 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
236 	.nu_data = &nvme_ctrl_base_1v0,
237 	.nu_value = 0xf7,
238 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
239 }, {
240 	.nu_desc = "invalid size (1.4, No LPA) (1)",
241 	.nu_fields = nvme_log_fields,
242 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
243 	.nu_data = &nvme_ctrl_nolpa_1v4,
244 	.nu_value = 0x4004,
245 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
246 }, {
247 	.nu_desc = "invalid size (1.4, No LPA) (2)",
248 	.nu_fields = nvme_log_fields,
249 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
250 	.nu_data = &nvme_ctrl_nolpa_1v4,
251 	.nu_value = 0x76543210,
252 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
253 }, {
254 	.nu_desc = "invalid size (1.4, No LPA) (3)",
255 	.nu_fields = nvme_log_fields,
256 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
257 	.nu_data = &nvme_ctrl_nolpa_1v4,
258 	.nu_value = 0x0,
259 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
260 }, {
261 	.nu_desc = "invalid size (1.4, LPA) (1)",
262 	.nu_fields = nvme_log_fields,
263 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
264 	.nu_data = &nvme_ctrl_ns_1v4,
265 	.nu_value = 0x123456789a0,
266 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
267 }, {
268 	.nu_desc = "invalid size (1.4, LPA) (2)",
269 	.nu_fields = nvme_log_fields,
270 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
271 	.nu_data = &nvme_ctrl_ns_1v4,
272 	.nu_value = 0x400000004,
273 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
274 }, {
275 	.nu_desc = "invalid size (1.4, LPA) (3)",
276 	.nu_fields = nvme_log_fields,
277 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
278 	.nu_data = &nvme_ctrl_ns_1v4,
279 	.nu_value = 0x0,
280 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
281 }, {
282 	.nu_desc = "valid size (1.0) (1)",
283 	.nu_fields = nvme_log_fields,
284 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
285 	.nu_data = &nvme_ctrl_base_1v0,
286 	.nu_value = 0x4000,
287 	.nu_ret = NVME_FIELD_ERR_OK
288 }, {
289 	.nu_desc = "valid size (1.0) (2)",
290 	.nu_fields = nvme_log_fields,
291 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
292 	.nu_data = &nvme_ctrl_base_1v0,
293 	.nu_value = 0x4,
294 	.nu_ret = NVME_FIELD_ERR_OK
295 }, {
296 	.nu_desc = "valid size (1.0) (3)",
297 	.nu_fields = nvme_log_fields,
298 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
299 	.nu_data = &nvme_ctrl_base_1v0,
300 	.nu_value = 0x1234,
301 	.nu_ret = NVME_FIELD_ERR_OK
302 }, {
303 	.nu_desc = "valid size (1.4, No LPA) (1)",
304 	.nu_fields = nvme_log_fields,
305 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
306 	.nu_data = &nvme_ctrl_nolpa_1v4,
307 	.nu_value = 0x4000,
308 	.nu_ret = NVME_FIELD_ERR_OK
309 }, {
310 	.nu_desc = "valid size (1.4, No LPA) (2)",
311 	.nu_fields = nvme_log_fields,
312 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
313 	.nu_data = &nvme_ctrl_nolpa_1v4,
314 	.nu_value = 0x4,
315 	.nu_ret = NVME_FIELD_ERR_OK
316 }, {
317 	.nu_desc = "valid size (1.4, No LPA) (3)",
318 	.nu_fields = nvme_log_fields,
319 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
320 	.nu_data = &nvme_ctrl_nolpa_1v4,
321 	.nu_value = 0x1234,
322 	.nu_ret = NVME_FIELD_ERR_OK
323 }, {
324 	.nu_desc = "valid size (1.4, LPA) (1)",
325 	.nu_fields = nvme_log_fields,
326 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
327 	.nu_data = &nvme_ctrl_ns_1v4,
328 	.nu_value = 0x4000,
329 	.nu_ret = NVME_FIELD_ERR_OK
330 }, {
331 	.nu_desc = "valid size (1.4, LPA) (2)",
332 	.nu_fields = nvme_log_fields,
333 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
334 	.nu_data = &nvme_ctrl_ns_1v4,
335 	.nu_value = 0x4,
336 	.nu_ret = NVME_FIELD_ERR_OK
337 }, {
338 	.nu_desc = "valid size (1.4, LPA) (3)",
339 	.nu_fields = nvme_log_fields,
340 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
341 	.nu_data = &nvme_ctrl_ns_1v4,
342 	.nu_value = 0x1234,
343 	.nu_ret = NVME_FIELD_ERR_OK
344 }, {
345 	.nu_desc = "valid size (1.4, LPA) (4)",
346 	.nu_fields = nvme_log_fields,
347 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
348 	.nu_data = &nvme_ctrl_ns_1v4,
349 	.nu_value = 0x400000000,
350 	.nu_ret = NVME_FIELD_ERR_OK
351 }, {
352 	.nu_desc = "valid size (1.4, LPA) (5)",
353 	.nu_fields = nvme_log_fields,
354 	.nu_index = NVME_LOG_REQ_FIELD_SIZE,
355 	.nu_data = &nvme_ctrl_ns_1v4,
356 	.nu_value = 0x7777777c,
357 	.nu_ret = NVME_FIELD_ERR_OK
358 }, {
359 	.nu_desc = "unsupported CSI (1.0)",
360 	.nu_fields = nvme_log_fields,
361 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
362 	.nu_data = &nvme_ctrl_base_1v0,
363 	.nu_value = 0x0,
364 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
365 }, {
366 	.nu_desc = "unsupported CSI (1.4)",
367 	.nu_fields = nvme_log_fields,
368 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
369 	.nu_data = &nvme_ctrl_ns_1v4,
370 	.nu_value = 0x0,
371 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
372 }, {
373 	.nu_desc = "invalid CSI (2.0) (1)",
374 	.nu_fields = nvme_log_fields,
375 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
376 	.nu_data = &nvme_ctrl_ns_2v0,
377 	.nu_value = 0x100,
378 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
379 }, {
380 	.nu_desc = "invalid CSI (2.0) (2)",
381 	.nu_fields = nvme_log_fields,
382 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
383 	.nu_data = &nvme_ctrl_ns_2v0,
384 	.nu_value = UINT64_MAX,
385 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
386 }, {
387 	.nu_desc = "valid CSI (2.0) (1)",
388 	.nu_fields = nvme_log_fields,
389 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
390 	.nu_data = &nvme_ctrl_ns_2v0,
391 	.nu_value = 0x1,
392 	.nu_ret = NVME_FIELD_ERR_OK
393 }, {
394 	.nu_desc = "valid CSI (2.0) (2)",
395 	.nu_fields = nvme_log_fields,
396 	.nu_index = NVME_LOG_REQ_FIELD_CSI,
397 	.nu_data = &nvme_ctrl_ns_2v0,
398 	.nu_value = 0xff,
399 	.nu_ret = NVME_FIELD_ERR_OK
400 }, {
401 	.nu_desc = "unsupported rae (1.0)",
402 	.nu_fields = nvme_log_fields,
403 	.nu_index = NVME_LOG_REQ_FIELD_RAE,
404 	.nu_data = &nvme_ctrl_base_1v0,
405 	.nu_value = 0x0,
406 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
407 }, {
408 	.nu_desc = "invalid rae (1)",
409 	.nu_fields = nvme_log_fields,
410 	.nu_index = NVME_LOG_REQ_FIELD_RAE,
411 	.nu_data = &nvme_ctrl_ns_1v4,
412 	.nu_value = 0x2,
413 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
414 }, {
415 	.nu_desc = "invalid rae (2)",
416 	.nu_fields = nvme_log_fields,
417 	.nu_index = NVME_LOG_REQ_FIELD_RAE,
418 	.nu_data = &nvme_ctrl_ns_1v4,
419 	.nu_value = 0x34,
420 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
421 }, {
422 	.nu_desc = "valid rae (1)",
423 	.nu_fields = nvme_log_fields,
424 	.nu_index = NVME_LOG_REQ_FIELD_RAE,
425 	.nu_data = &nvme_ctrl_ns_1v4,
426 	.nu_value = 0x0,
427 	.nu_ret = NVME_FIELD_ERR_OK
428 }, {
429 	.nu_desc = "valid rae (2)",
430 	.nu_fields = nvme_log_fields,
431 	.nu_index = NVME_LOG_REQ_FIELD_RAE,
432 	.nu_data = &nvme_ctrl_ns_1v4,
433 	.nu_value = 0x1,
434 	.nu_ret = NVME_FIELD_ERR_OK
435 }, {
436 	.nu_desc = "unsupported offset (1.0)",
437 	.nu_fields = nvme_log_fields,
438 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
439 	.nu_data = &nvme_ctrl_base_1v0,
440 	.nu_value = 0x3,
441 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
442 }, {
443 	.nu_desc = "unsupported offset (1.4 No LPA)",
444 	.nu_fields = nvme_log_fields,
445 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
446 	.nu_data = &nvme_ctrl_nolpa_1v4,
447 	.nu_value = 0x4,
448 	.nu_ret = NVME_FIELD_ERR_UNSUP_FIELD
449 }, {
450 	.nu_desc = "unaligned offset (1.4) (1)",
451 	.nu_fields = nvme_log_fields,
452 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
453 	.nu_data = &nvme_ctrl_ns_1v4,
454 	.nu_value = 0x3,
455 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
456 }, {
457 	.nu_desc = "unaligned offset (1.4) (2)",
458 	.nu_fields = nvme_log_fields,
459 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
460 	.nu_data = &nvme_ctrl_ns_1v4,
461 	.nu_value = UINT64_MAX,
462 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
463 }, {
464 	.nu_desc = "unaligned offset (1.4) (3)",
465 	.nu_fields = nvme_log_fields,
466 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
467 	.nu_data = &nvme_ctrl_ns_1v4,
468 	.nu_value = 0x3,
469 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
470 }, {
471 	.nu_desc = "valid offset (1.4) (1)",
472 	.nu_fields = nvme_log_fields,
473 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
474 	.nu_data = &nvme_ctrl_ns_1v4,
475 	.nu_value = 0x0,
476 	.nu_ret = NVME_FIELD_ERR_OK
477 }, {
478 	.nu_desc = "valid offset (1.4) (2)",
479 	.nu_fields = nvme_log_fields,
480 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
481 	.nu_data = &nvme_ctrl_ns_1v4,
482 	.nu_value = 0x4444,
483 	.nu_ret = NVME_FIELD_ERR_OK
484 }, {
485 	.nu_desc = "valid offset (1.4) (3)",
486 	.nu_fields = nvme_log_fields,
487 	.nu_index = NVME_LOG_REQ_FIELD_OFFSET,
488 	.nu_data = &nvme_ctrl_ns_1v4,
489 	.nu_value = 0xfffffffffffffffc,
490 	.nu_ret = NVME_FIELD_ERR_OK
491 }, {
492 	.nu_desc = "unsupported nsid (1.0)",
493 	.nu_fields = nvme_log_fields,
494 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
495 	.nu_data = &nvme_ctrl_base_1v0,
496 	.nu_value = 0x1,
497 	.nu_ret = NVME_FIELD_ERR_UNSUP_VERSION
498 }, {
499 	.nu_desc = "unsupported nsid (2.0 No NS)",
500 	.nu_fields = nvme_log_fields,
501 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
502 	.nu_data = &nvme_ctrl_nons_2v0,
503 	.nu_value = 0x1,
504 	.nu_ret = NVME_FIELD_ERR_UNSUP_FIELD
505 }, {
506 	.nu_desc = "invalid nsid (1.4) (1)",
507 	.nu_fields = nvme_log_fields,
508 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
509 	.nu_data = &nvme_ctrl_ns_1v4,
510 	.nu_value = 0x0,
511 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
512 }, {
513 	.nu_desc = "invalid nsid (1.4) (2)",
514 	.nu_fields = nvme_log_fields,
515 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
516 	.nu_data = &nvme_ctrl_ns_1v4,
517 	.nu_value = 0x1000,
518 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
519 }, {
520 	.nu_desc = "invalid nsid (1.4) (3)",
521 	.nu_fields = nvme_log_fields,
522 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
523 	.nu_data = &nvme_ctrl_ns_1v4,
524 	.nu_value = 0x81,
525 	.nu_ret = NVME_FIELD_ERR_BAD_VALUE
526 }, {
527 	.nu_desc = "valid nsid (1.4) (1)",
528 	.nu_fields = nvme_log_fields,
529 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
530 	.nu_data = &nvme_ctrl_ns_1v4,
531 	.nu_value = 0x1,
532 	.nu_ret = NVME_FIELD_ERR_OK
533 }, {
534 	.nu_desc = "valid nsid (1.4) (2)",
535 	.nu_fields = nvme_log_fields,
536 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
537 	.nu_data = &nvme_ctrl_ns_1v4,
538 	.nu_value = 0x80,
539 	.nu_ret = NVME_FIELD_ERR_OK
540 }, {
541 	.nu_desc = "valid nsid (1.4) (3)",
542 	.nu_fields = nvme_log_fields,
543 	.nu_index = NVME_LOG_REQ_FIELD_NSID,
544 	.nu_data = &nvme_ctrl_ns_1v4,
545 	.nu_value = 0x23,
546 	.nu_ret = NVME_FIELD_ERR_OK
547 } };
548 
549 typedef struct log_scope_test {
550 	const char *lst_desc;
551 	const char *lst_short;
552 	const nvme_valid_ctrl_data_t *lst_data;
553 	nvme_log_disc_scope_t lst_exp_scope;
554 } log_scope_test_t;
555 
556 static const log_scope_test_t log_scope_tests[] = { {
557 	.lst_desc = "error log (1.0)",
558 	.lst_short = "error",
559 	.lst_data = &nvme_ctrl_base_1v0,
560 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
561 }, {
562 	.lst_desc = "error log (2.0)",
563 	.lst_short = "error",
564 	.lst_data = &nvme_ctrl_ns_2v0,
565 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
566 }, {
567 	.lst_desc = "health log (1.0)",
568 	.lst_short = "health",
569 	.lst_data = &nvme_ctrl_base_1v0,
570 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
571 }, {
572 	.lst_desc = "health log (1.4 No LPA)",
573 	.lst_short = "health",
574 	.lst_data = &nvme_ctrl_nolpa_1v4,
575 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
576 }, {
577 	.lst_desc = "health log (1.0 NS Health)",
578 	.lst_short = "health",
579 	.lst_data = &nvme_ctrl_health_1v0,
580 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL | NVME_LOG_SCOPE_NS
581 }, {
582 	.lst_desc = "health log (1.4 LPA)",
583 	.lst_short = "health",
584 	.lst_data = &nvme_ctrl_ns_1v4,
585 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL | NVME_LOG_SCOPE_NS
586 }, {
587 	.lst_desc = "health log (2.0 LPA)",
588 	.lst_short = "health",
589 	.lst_data = &nvme_ctrl_ns_2v0,
590 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL | NVME_LOG_SCOPE_NS
591 }, {
592 	.lst_desc = "firmware log (1.0)",
593 	.lst_short = "firmware",
594 	.lst_data = &nvme_ctrl_base_1v0,
595 	.lst_exp_scope = NVME_LOG_SCOPE_NVM
596 }, {
597 	.lst_desc = "firmware log (2.0)",
598 	.lst_short = "firmware",
599 	.lst_data = &nvme_ctrl_ns_2v0,
600 	.lst_exp_scope = NVME_LOG_SCOPE_NVM
601 }, {
602 	.lst_desc = "changed namespace log (2.0)",
603 	.lst_short = "changens",
604 	.lst_data = &nvme_ctrl_ns_2v0,
605 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
606 }, {
607 	.lst_desc = "supported logs log (2.0)",
608 	.lst_short = "suplog",
609 	.lst_data = &nvme_ctrl_ns_2v0,
610 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
611 }, {
612 	.lst_desc = "commands supported and effects log (1.2)",
613 	.lst_short = "cmdeff",
614 	.lst_data = &nvme_ctrl_ns_1v2,
615 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
616 }, {
617 	.lst_desc = "commands supported and effects log (2.0)",
618 	.lst_short = "cmdeff",
619 	.lst_data = &nvme_ctrl_ns_2v0,
620 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
621 } };
622 
623 typedef struct log_size_test {
624 	const char *lt_desc;
625 	const char *lt_short;
626 	const nvme_valid_ctrl_data_t *lt_data;
627 	uint64_t lt_size;
628 	bool lt_var;
629 } log_size_test_t;
630 
631 static const log_size_test_t log_size_tests[] = { {
632 	.lt_desc = "error log (4 entries)",
633 	.lt_short = "error",
634 	.lt_data = &nvme_ctrl_base_1v0,
635 	.lt_size = 4 * sizeof (nvme_error_log_entry_t),
636 	.lt_var = false
637 }, {
638 	.lt_desc = "error log (1 entries)",
639 	.lt_short = "error",
640 	.lt_data = &nvme_ctrl_ns_1v4,
641 	.lt_size = sizeof (nvme_error_log_entry_t),
642 	.lt_var = false
643 }, {
644 	.lt_desc = "health log (1.0)",
645 	.lt_short = "health",
646 	.lt_data = &nvme_ctrl_base_1v0,
647 	.lt_size = sizeof (nvme_health_log_t),
648 	.lt_var = false
649 }, {
650 	.lt_desc = "health log (1.4)",
651 	.lt_short = "health",
652 	.lt_data = &nvme_ctrl_ns_1v4,
653 	.lt_size = sizeof (nvme_health_log_t),
654 	.lt_var = false
655 }, {
656 	.lt_desc = "firmware log (1.0)",
657 	.lt_short = "firmware",
658 	.lt_data = &nvme_ctrl_base_1v0,
659 	.lt_size = sizeof (nvme_fwslot_log_t),
660 	.lt_var = false
661 }, {
662 	.lt_desc = "firmware log (1.4)",
663 	.lt_short = "firmware",
664 	.lt_data = &nvme_ctrl_ns_1v4,
665 	.lt_size = sizeof (nvme_fwslot_log_t),
666 	.lt_var = false
667 }, {
668 	.lt_desc = "changed namespace log (1.0)",
669 	.lt_short = "changens",
670 	.lt_data = &nvme_ctrl_base_1v0,
671 	.lt_size = sizeof (nvme_nschange_list_t),
672 	.lt_var = false
673 }, {
674 	.lt_desc = "changed namespace log (1.4)",
675 	.lt_short = "changens",
676 	.lt_data = &nvme_ctrl_ns_1v4,
677 	.lt_size = sizeof (nvme_nschange_list_t),
678 	.lt_var = false
679 }, {
680 	.lt_desc = "commands supported and effects log (1.2)",
681 	.lt_short = "cmdeff",
682 	.lt_data = &nvme_ctrl_ns_1v2,
683 	.lt_size = sizeof (nvme_cmdeff_log_t),
684 	.lt_var = false
685 }, {
686 	.lt_desc = "commands supported and effects log (1.4)",
687 	.lt_short = "cmdeff",
688 	.lt_data = &nvme_ctrl_ns_1v4,
689 	.lt_size = sizeof (nvme_cmdeff_log_t),
690 	.lt_var = false
691 }, {
692 	.lt_desc = "supported logs log (2.0)",
693 	.lt_short = "suplog",
694 	.lt_data = &nvme_ctrl_ns_2v0,
695 	.lt_size = sizeof (nvme_suplog_log_t),
696 	.lt_var = false
697 } };
698 
699 typedef struct log_impl_test {
700 	const char *lit_desc;
701 	const char *lit_short;
702 	const nvme_valid_ctrl_data_t *lit_data;
703 	bool lit_impl;
704 } log_impl_test_t;
705 
706 static const log_impl_test_t log_impl_tests[] = { {
707 	.lit_desc = "supported logs (1.0)",
708 	.lit_short = "suplog",
709 	.lit_data = &nvme_ctrl_base_1v0,
710 	.lit_impl = false
711 }, {
712 	.lit_desc = "supported logs (2.0)",
713 	.lit_short = "suplog",
714 	.lit_data = &nvme_ctrl_base_2v0,
715 	.lit_impl = true
716 }, {
717 	.lit_desc = "error (1.0)",
718 	.lit_short = "error",
719 	.lit_data = &nvme_ctrl_base_1v0,
720 	.lit_impl = true
721 }, {
722 	.lit_desc = "error (1.4)",
723 	.lit_short = "error",
724 	.lit_data = &nvme_ctrl_ns_1v4,
725 	.lit_impl = true
726 }, {
727 	.lit_desc = "health (1.0)",
728 	.lit_short = "health",
729 	.lit_data = &nvme_ctrl_base_1v0,
730 	.lit_impl = true
731 }, {
732 	.lit_desc = "health (1.4)",
733 	.lit_short = "health",
734 	.lit_data = &nvme_ctrl_ns_1v4,
735 	.lit_impl = true
736 }, {
737 	.lit_desc = "firmware (1.0)",
738 	.lit_short = "firmware",
739 	.lit_data = &nvme_ctrl_base_1v0,
740 	.lit_impl = true
741 }, {
742 	.lit_desc = "firmware (1.4)",
743 	.lit_short = "firmware",
744 	.lit_data = &nvme_ctrl_ns_1v4,
745 	.lit_impl = true
746 }, {
747 	.lit_desc = "changed namespace (1.0)",
748 	.lit_short = "changens",
749 	.lit_data = &nvme_ctrl_base_1v0,
750 	.lit_impl = false
751 }, {
752 	.lit_desc = "changed namespace (1.4 No LPA)",
753 	.lit_short = "changens",
754 	.lit_data = &nvme_ctrl_ns_1v4,
755 	.lit_impl = true
756 }, {
757 	.lit_desc = "changed namespace (1.2 No OAES)",
758 	.lit_short = "changens",
759 	.lit_data = &nvme_ctrl_base_1v2,
760 	.lit_impl = false
761 }, {
762 	.lit_desc = "commands supported and effects (1.0)",
763 	.lit_short = "cmdeff",
764 	.lit_data = &nvme_ctrl_base_1v0,
765 	.lit_impl = false
766 }, {
767 	.lit_desc = "commands supported and effects (1.4 LPA)",
768 	.lit_short = "cmdeff",
769 	.lit_data = &nvme_ctrl_ns_1v4,
770 	.lit_impl = true
771 }, {
772 	.lit_desc = "commands supported and effects (2.0 No LPA)",
773 	.lit_short = "cmdeff",
774 	.lit_data = &nvme_ctrl_base_2v0,
775 	.lit_impl = false
776 } };
777 
778 static const nvme_log_page_info_t *
log_test_find_info(const char * desc,const char * name)779 log_test_find_info(const char *desc, const char *name)
780 {
781 	for (size_t i = 0; i < nvme_std_log_npages; i++) {
782 		if (strcmp(nvme_std_log_pages[i].nlpi_short, name) == 0) {
783 			return (&nvme_std_log_pages[i]);
784 		}
785 	}
786 
787 	errx(EXIT_FAILURE, "malformed test: %s: cannot find log page %s",
788 	    desc, name);
789 }
790 
791 static bool
log_scope_test_one(const log_scope_test_t * test)792 log_scope_test_one(const log_scope_test_t *test)
793 {
794 	nvme_log_disc_scope_t scope;
795 	const nvme_log_page_info_t *info;
796 
797 	info = log_test_find_info(test->lst_desc, test->lst_short);
798 	scope = nvme_log_page_info_scope(info, test->lst_data);
799 	if (scope != test->lst_exp_scope) {
800 		warnx("TEST FAILED: %s: found scope 0x%x, expected 0x%x",
801 		    test->lst_desc, scope, test->lst_exp_scope);
802 		return (false);
803 	}
804 
805 	(void) printf("TEST PASSED: %s: correct scope\n", test->lst_desc);
806 	return (true);
807 }
808 
809 static bool
log_size_test_one(const log_size_test_t * test)810 log_size_test_one(const log_size_test_t *test)
811 {
812 	const nvme_log_page_info_t *info;
813 	uint64_t len;
814 	bool var, ret = true;
815 
816 	info = log_test_find_info(test->lt_desc, test->lt_short);
817 	len = nvme_log_page_info_size(info, test->lt_data, &var);
818 
819 	if (len != test->lt_size) {
820 		warnx("TEST FAILED: %s: expected size %" PRIu64 ", found %"
821 		    PRIu64, test->lt_desc, test->lt_size, len);
822 		ret = false;
823 	} else {
824 		(void) printf("TEST PASSED: %s: found correct size\n",
825 		    test->lt_desc);
826 	}
827 
828 	if (var != test->lt_var) {
829 		warnx("TEST FAILED: %s: expected var %u, found %u",
830 		    test->lt_desc, test->lt_var, var);
831 		ret = false;
832 	} else {
833 		(void) printf("TEST PASSED: %s: variable length flag correct\n",
834 		    test->lt_desc);
835 	}
836 
837 	return (ret);
838 }
839 
840 static bool
log_impl_test_one(const log_impl_test_t * test)841 log_impl_test_one(const log_impl_test_t *test)
842 {
843 	const nvme_log_page_info_t *info;
844 	bool impl;
845 
846 	info = log_test_find_info(test->lit_desc, test->lit_short);
847 	impl = nvme_log_page_info_supported(info, test->lit_data);
848 	if (impl != test->lit_impl) {
849 		warnx("TEST FAILED: %s: expected impl %u, found %u",
850 		    test->lit_desc, test->lit_impl, impl);
851 		return (false);
852 	}
853 
854 	(void) printf("TEST PASSED: %s: got correct impl\n", test->lit_desc);
855 	return (true);
856 }
857 
858 int
main(void)859 main(void)
860 {
861 	int ret = EXIT_SUCCESS;
862 
863 	if (!nvme_unit_field_test(log_field_tests,
864 	    ARRAY_SIZE(log_field_tests))) {
865 		ret = EXIT_FAILURE;
866 	}
867 
868 	for (size_t i = 0; i < ARRAY_SIZE(log_scope_tests); i++) {
869 		if (!log_scope_test_one(&log_scope_tests[i])) {
870 			ret = EXIT_FAILURE;
871 		}
872 	}
873 
874 	for (size_t i = 0; i < ARRAY_SIZE(log_size_tests); i++) {
875 		if (!log_size_test_one(&log_size_tests[i])) {
876 			ret = EXIT_FAILURE;
877 		}
878 	}
879 
880 	for (size_t i = 0; i < ARRAY_SIZE(log_impl_tests); i++) {
881 		if (!log_impl_test_one(&log_impl_tests[i])) {
882 			ret = EXIT_FAILURE;
883 		}
884 	}
885 
886 	if (ret == EXIT_SUCCESS) {
887 		(void) printf("All tests passed successfully!\n");
888 	}
889 
890 	return (ret);
891 }
892