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 namespaces log (2.0)",
603 	.lst_short = "changens",
604 	.lst_data = &nvme_ctrl_ns_2v0,
605 	.lst_exp_scope = NVME_LOG_SCOPE_CTRL
606 } };
607 
608 typedef struct log_size_test {
609 	const char *lt_desc;
610 	const char *lt_short;
611 	const nvme_valid_ctrl_data_t *lt_data;
612 	uint64_t lt_size;
613 	bool lt_var;
614 } log_size_test_t;
615 
616 static const log_size_test_t log_size_tests[] = { {
617 	.lt_desc = "error log (4 entries)",
618 	.lt_short = "error",
619 	.lt_data = &nvme_ctrl_base_1v0,
620 	.lt_size = 4 * sizeof (nvme_error_log_entry_t),
621 	.lt_var = false
622 }, {
623 	.lt_desc = "error log (1 entries)",
624 	.lt_short = "error",
625 	.lt_data = &nvme_ctrl_ns_1v4,
626 	.lt_size = sizeof (nvme_error_log_entry_t),
627 	.lt_var = false
628 }, {
629 	.lt_desc = "health log (1.0)",
630 	.lt_short = "health",
631 	.lt_data = &nvme_ctrl_base_1v0,
632 	.lt_size = sizeof (nvme_health_log_t),
633 	.lt_var = false
634 }, {
635 	.lt_desc = "health log (1.4)",
636 	.lt_short = "health",
637 	.lt_data = &nvme_ctrl_ns_1v4,
638 	.lt_size = sizeof (nvme_health_log_t),
639 	.lt_var = false
640 }, {
641 	.lt_desc = "firmware log (1.0)",
642 	.lt_short = "firmware",
643 	.lt_data = &nvme_ctrl_base_1v0,
644 	.lt_size = sizeof (nvme_fwslot_log_t),
645 	.lt_var = false
646 }, {
647 	.lt_desc = "firmware log (1.4)",
648 	.lt_short = "firmware",
649 	.lt_data = &nvme_ctrl_ns_1v4,
650 	.lt_size = sizeof (nvme_fwslot_log_t),
651 	.lt_var = false
652 }, {
653 	.lt_desc = "changed namespace log (1.0)",
654 	.lt_short = "changens",
655 	.lt_data = &nvme_ctrl_base_1v0,
656 	.lt_size = sizeof (nvme_nschange_list_t),
657 	.lt_var = false
658 }, {
659 	.lt_desc = "changed namespace log (1.4)",
660 	.lt_short = "changens",
661 	.lt_data = &nvme_ctrl_ns_1v4,
662 	.lt_size = sizeof (nvme_nschange_list_t),
663 	.lt_var = false
664 } };
665 
666 typedef struct log_impl_test {
667 	const char *lit_desc;
668 	const char *lit_short;
669 	const nvme_valid_ctrl_data_t *lit_data;
670 	bool lit_impl;
671 } log_impl_test_t;
672 
673 static const log_impl_test_t log_impl_tests[] = { {
674 	.lit_desc = "error (1.0)",
675 	.lit_short = "error",
676 	.lit_data = &nvme_ctrl_base_1v0,
677 	.lit_impl = true
678 }, {
679 	.lit_desc = "error (1.4)",
680 	.lit_short = "error",
681 	.lit_data = &nvme_ctrl_ns_1v4,
682 	.lit_impl = true
683 }, {
684 	.lit_desc = "health (1.0)",
685 	.lit_short = "health",
686 	.lit_data = &nvme_ctrl_base_1v0,
687 	.lit_impl = true
688 }, {
689 	.lit_desc = "health (1.4)",
690 	.lit_short = "health",
691 	.lit_data = &nvme_ctrl_ns_1v4,
692 	.lit_impl = true
693 }, {
694 	.lit_desc = "firmware (1.0)",
695 	.lit_short = "firmware",
696 	.lit_data = &nvme_ctrl_base_1v0,
697 	.lit_impl = true
698 }, {
699 	.lit_desc = "firmware (1.4)",
700 	.lit_short = "firmware",
701 	.lit_data = &nvme_ctrl_ns_1v4,
702 	.lit_impl = true
703 }, {
704 	.lit_desc = "changed namespace (1.0)",
705 	.lit_short = "changens",
706 	.lit_data = &nvme_ctrl_base_1v0,
707 	.lit_impl = false
708 }, {
709 	.lit_desc = "changed namespace (1.4 No LPA)",
710 	.lit_short = "changens",
711 	.lit_data = &nvme_ctrl_ns_1v4,
712 	.lit_impl = true
713 }, {
714 	.lit_desc = "changed namespace (1.2 No OAES)",
715 	.lit_short = "changens",
716 	.lit_data = &nvme_ctrl_base_1v2,
717 	.lit_impl = false
718 } };
719 
720 static const nvme_log_page_info_t *
log_test_find_info(const char * desc,const char * name)721 log_test_find_info(const char *desc, const char *name)
722 {
723 	for (size_t i = 0; i < nvme_std_log_npages; i++) {
724 		if (strcmp(nvme_std_log_pages[i].nlpi_short, name) == 0) {
725 			return (&nvme_std_log_pages[i]);
726 		}
727 	}
728 
729 	errx(EXIT_FAILURE, "malformed test: %s: cannot find log page %s",
730 	    desc, name);
731 }
732 
733 static bool
log_scope_test_one(const log_scope_test_t * test)734 log_scope_test_one(const log_scope_test_t *test)
735 {
736 	nvme_log_disc_scope_t scope;
737 	const nvme_log_page_info_t *info;
738 
739 	info = log_test_find_info(test->lst_desc, test->lst_short);
740 	scope = nvme_log_page_info_scope(info, test->lst_data);
741 	if (scope != test->lst_exp_scope) {
742 		warnx("TEST FAILED: %s: found scope 0x%x, expected 0x%x",
743 		    test->lst_desc, scope, test->lst_exp_scope);
744 		return (false);
745 	}
746 
747 	(void) printf("TEST PASSED: %s: correct scope\n", test->lst_desc);
748 	return (true);
749 }
750 
751 static bool
log_size_test_one(const log_size_test_t * test)752 log_size_test_one(const log_size_test_t *test)
753 {
754 	const nvme_log_page_info_t *info;
755 	uint64_t len;
756 	bool var, ret = true;
757 
758 	info = log_test_find_info(test->lt_desc, test->lt_short);
759 	len = nvme_log_page_info_size(info, test->lt_data, &var);
760 
761 	if (len != test->lt_size) {
762 		warnx("TEST FAILED: %s: expected size %" PRIu64 ", found %"
763 		    PRIu64, test->lt_desc, test->lt_size, len);
764 		ret = false;
765 	} else {
766 		(void) printf("TEST PASSED: %s: found correct size\n",
767 		    test->lt_desc);
768 	}
769 
770 	if (var != test->lt_var) {
771 		warnx("TEST FAILED: %s: expected var %u, found %u",
772 		    test->lt_desc, test->lt_var, var);
773 		ret = false;
774 	} else {
775 		(void) printf("TEST PASSED: %s: variable length flag correct\n",
776 		    test->lt_desc);
777 	}
778 
779 	return (ret);
780 }
781 
782 static bool
log_impl_test_one(const log_impl_test_t * test)783 log_impl_test_one(const log_impl_test_t *test)
784 {
785 	const nvme_log_page_info_t *info;
786 	bool impl;
787 
788 	info = log_test_find_info(test->lit_desc, test->lit_short);
789 	impl = nvme_log_page_info_supported(info, test->lit_data);
790 	if (impl != test->lit_impl) {
791 		warnx("TEST FAILED: %s: expected impl %u, found %u",
792 		    test->lit_desc, test->lit_impl, impl);
793 		return (false);
794 	}
795 
796 	(void) printf("TEST PASSED: %s: got correct impl\n", test->lit_desc);
797 	return (true);
798 }
799 
800 int
main(void)801 main(void)
802 {
803 	int ret = EXIT_SUCCESS;
804 
805 	if (!nvme_unit_field_test(log_field_tests,
806 	    ARRAY_SIZE(log_field_tests))) {
807 		ret = EXIT_FAILURE;
808 	}
809 
810 	for (size_t i = 0; i < ARRAY_SIZE(log_scope_tests); i++) {
811 		if (!log_scope_test_one(&log_scope_tests[i])) {
812 			ret = EXIT_FAILURE;
813 		}
814 	}
815 
816 	for (size_t i = 0; i < ARRAY_SIZE(log_size_tests); i++) {
817 		if (!log_size_test_one(&log_size_tests[i])) {
818 			ret = EXIT_FAILURE;
819 		}
820 	}
821 
822 	for (size_t i = 0; i < ARRAY_SIZE(log_impl_tests); i++) {
823 		if (!log_impl_test_one(&log_impl_tests[i])) {
824 			ret = EXIT_FAILURE;
825 		}
826 	}
827 
828 	if (ret == EXIT_SUCCESS) {
829 		(void) printf("All tests passed successfully!\n");
830 	}
831 
832 	return (ret);
833 }
834