1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright (C) 2015 Intel Corporation. All rights reserved.
4 * Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
5 */
6
7 #include "spdk_internal/cunit.h"
8
9 #include "nvme/nvme_ctrlr_cmd.c"
10
11 #include "spdk_internal/mock.h"
12
13 #define CTRLR_CDATA_ELPE 5
14
15 pid_t g_spdk_nvme_pid;
16
17 struct nvme_request g_req;
18
19 uint32_t error_num_entries;
20 uint32_t health_log_nsid = 1;
21 uint8_t feature = 1;
22 uint32_t feature_cdw11 = 1;
23 uint32_t feature_cdw12 = 1;
24 uint8_t get_feature = 1;
25 uint32_t get_feature_cdw11 = 1;
26 uint32_t fw_img_size = 1024;
27 uint32_t fw_img_offset = 0;
28 uint16_t abort_cid = 1;
29 uint16_t abort_sqid = 1;
30 uint32_t namespace_management_nsid = 1;
31 uint64_t PRP_ENTRY_1 = 4096;
32 uint64_t PRP_ENTRY_2 = 4096;
33 uint32_t format_nvme_nsid = 1;
34 uint32_t sanitize_nvme_nsid = 1;
35 uint32_t expected_host_id_size = 0xFF;
36 uint32_t directive_nsid = 1;
37
38 uint32_t expected_feature_ns = 2;
39 uint32_t expected_feature_cdw10 = SPDK_NVME_FEAT_LBA_RANGE_TYPE;
40 uint32_t expected_feature_cdw11 = 1;
41 uint32_t expected_feature_cdw12 = 1;
42
43 typedef void (*verify_request_fn_t)(struct nvme_request *req);
44 verify_request_fn_t verify_fn;
45
46 DEFINE_STUB(nvme_transport_qpair_iterate_requests, int,
47 (struct spdk_nvme_qpair *qpair,
48 int (*iter_fn)(struct nvme_request *req, void *arg),
49 void *arg), 0);
50
51 DEFINE_STUB(nvme_qpair_abort_queued_reqs_with_cbarg, uint32_t,
52 (struct spdk_nvme_qpair *qpair, void *cmd_cb_arg), 0);
53
54 DEFINE_STUB(spdk_nvme_ctrlr_get_admin_qp_failure_reason, spdk_nvme_qp_failure_reason,
55 (struct spdk_nvme_ctrlr *ctrlr), 0);
56
57 static int
nvme_ns_cmp(struct spdk_nvme_ns * ns1,struct spdk_nvme_ns * ns2)58 nvme_ns_cmp(struct spdk_nvme_ns *ns1, struct spdk_nvme_ns *ns2)
59 {
60 return ns1->id - ns2->id;
61 }
62
63 RB_GENERATE_STATIC(nvme_ns_tree, spdk_nvme_ns, node, nvme_ns_cmp);
64
65 static void
verify_firmware_log_page(struct nvme_request * req)66 verify_firmware_log_page(struct nvme_request *req)
67 {
68 uint32_t temp_cdw10;
69
70 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
71 CU_ASSERT(req->cmd.nsid == SPDK_NVME_GLOBAL_NS_TAG);
72
73 temp_cdw10 = ((sizeof(struct spdk_nvme_firmware_page) / sizeof(uint32_t) - 1) << 16) |
74 SPDK_NVME_LOG_FIRMWARE_SLOT;
75 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
76 }
77
78 static void
verify_health_log_page(struct nvme_request * req)79 verify_health_log_page(struct nvme_request *req)
80 {
81 uint32_t temp_cdw10;
82
83 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
84 CU_ASSERT(req->cmd.nsid == health_log_nsid);
85
86 temp_cdw10 = ((sizeof(struct spdk_nvme_health_information_page) / sizeof(uint32_t) - 1) << 16) |
87 SPDK_NVME_LOG_HEALTH_INFORMATION;
88 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
89 }
90
91 static void
verify_error_log_page(struct nvme_request * req)92 verify_error_log_page(struct nvme_request *req)
93 {
94 uint32_t temp_cdw10;
95
96 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
97 CU_ASSERT(req->cmd.nsid == SPDK_NVME_GLOBAL_NS_TAG);
98
99 temp_cdw10 = (((sizeof(struct spdk_nvme_error_information_entry) * error_num_entries) /
100 sizeof(uint32_t) - 1) << 16) | SPDK_NVME_LOG_ERROR;
101 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
102 }
103
104 static void
verify_set_feature_cmd(struct nvme_request * req)105 verify_set_feature_cmd(struct nvme_request *req)
106 {
107 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_SET_FEATURES);
108 CU_ASSERT(req->cmd.cdw10 == feature);
109 CU_ASSERT(req->cmd.cdw11 == feature_cdw11);
110 CU_ASSERT(req->cmd.cdw12 == feature_cdw12);
111 }
112
113 static void
verify_set_feature_ns_cmd(struct nvme_request * req)114 verify_set_feature_ns_cmd(struct nvme_request *req)
115 {
116 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_SET_FEATURES);
117 CU_ASSERT(req->cmd.cdw10 == expected_feature_cdw10);
118 CU_ASSERT(req->cmd.cdw11 == expected_feature_cdw11);
119 CU_ASSERT(req->cmd.cdw12 == expected_feature_cdw12);
120 CU_ASSERT(req->cmd.nsid == expected_feature_ns);
121 }
122
123 static void
verify_get_feature_cmd(struct nvme_request * req)124 verify_get_feature_cmd(struct nvme_request *req)
125 {
126 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_FEATURES);
127 CU_ASSERT(req->cmd.cdw10 == get_feature);
128 CU_ASSERT(req->cmd.cdw11 == get_feature_cdw11);
129 }
130
131 static void
verify_get_feature_ns_cmd(struct nvme_request * req)132 verify_get_feature_ns_cmd(struct nvme_request *req)
133 {
134 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_FEATURES);
135 CU_ASSERT(req->cmd.cdw10 == expected_feature_cdw10);
136 CU_ASSERT(req->cmd.cdw11 == expected_feature_cdw11);
137 CU_ASSERT(req->cmd.nsid == expected_feature_ns);
138 }
139
140 static void
verify_abort_cmd(struct nvme_request * req)141 verify_abort_cmd(struct nvme_request *req)
142 {
143 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_ABORT);
144 CU_ASSERT(req->cmd.cdw10 == (((uint32_t)abort_cid << 16) | abort_sqid));
145 }
146
147 static void
verify_io_cmd_raw_no_payload_build(struct nvme_request * req)148 verify_io_cmd_raw_no_payload_build(struct nvme_request *req)
149 {
150 struct spdk_nvme_cmd command = {};
151 struct nvme_payload payload = {};
152
153 CU_ASSERT(memcmp(&req->cmd, &command, sizeof(req->cmd)) == 0);
154 CU_ASSERT(memcmp(&req->payload, &payload, sizeof(req->payload)) == 0);
155 }
156
157 static void
verify_io_raw_cmd(struct nvme_request * req)158 verify_io_raw_cmd(struct nvme_request *req)
159 {
160 struct spdk_nvme_cmd command = {};
161
162 CU_ASSERT(memcmp(&req->cmd, &command, sizeof(req->cmd)) == 0);
163 }
164
165 static void
verify_io_raw_cmd_with_md(struct nvme_request * req)166 verify_io_raw_cmd_with_md(struct nvme_request *req)
167 {
168 struct spdk_nvme_cmd command = {};
169
170 CU_ASSERT(memcmp(&req->cmd, &command, sizeof(req->cmd)) == 0);
171 }
172
173 static void
verify_set_host_id_cmd(struct nvme_request * req)174 verify_set_host_id_cmd(struct nvme_request *req)
175 {
176 switch (expected_host_id_size) {
177 case 8:
178 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_FEAT_HOST_IDENTIFIER);
179 CU_ASSERT(req->cmd.cdw11 == 0);
180 CU_ASSERT(req->cmd.cdw12 == 0);
181 break;
182 case 16:
183 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_FEAT_HOST_IDENTIFIER);
184 CU_ASSERT(req->cmd.cdw11 == 1);
185 CU_ASSERT(req->cmd.cdw12 == 0);
186 break;
187 default:
188 CU_ASSERT(0);
189 }
190 }
191
192 static void
verify_intel_smart_log_page(struct nvme_request * req)193 verify_intel_smart_log_page(struct nvme_request *req)
194 {
195 uint32_t temp_cdw10;
196
197 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
198 CU_ASSERT(req->cmd.nsid == health_log_nsid);
199
200 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_smart_information_page) /
201 sizeof(uint32_t) - 1) << 16) |
202 SPDK_NVME_INTEL_LOG_SMART;
203 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
204 }
205
206 static void
verify_intel_temperature_log_page(struct nvme_request * req)207 verify_intel_temperature_log_page(struct nvme_request *req)
208 {
209 uint32_t temp_cdw10;
210
211 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
212
213 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_temperature_page) / sizeof(uint32_t) - 1) << 16) |
214 SPDK_NVME_INTEL_LOG_TEMPERATURE;
215 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
216 }
217
218 static void
verify_intel_read_latency_log_page(struct nvme_request * req)219 verify_intel_read_latency_log_page(struct nvme_request *req)
220 {
221 uint32_t temp_cdw10;
222
223 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
224
225 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_rw_latency_page) / sizeof(uint32_t) - 1) << 16) |
226 SPDK_NVME_INTEL_LOG_READ_CMD_LATENCY;
227 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
228 }
229
230 static void
verify_intel_write_latency_log_page(struct nvme_request * req)231 verify_intel_write_latency_log_page(struct nvme_request *req)
232 {
233 uint32_t temp_cdw10;
234
235 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
236
237 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_rw_latency_page) / sizeof(uint32_t) - 1) << 16) |
238 SPDK_NVME_INTEL_LOG_WRITE_CMD_LATENCY;
239 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
240 }
241
242 static void
verify_intel_get_log_page_directory(struct nvme_request * req)243 verify_intel_get_log_page_directory(struct nvme_request *req)
244 {
245 uint32_t temp_cdw10;
246
247 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
248
249 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_log_page_directory) / sizeof(uint32_t) - 1) << 16) |
250 SPDK_NVME_INTEL_LOG_PAGE_DIRECTORY;
251 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
252 }
253
254 static void
verify_intel_marketing_description_log_page(struct nvme_request * req)255 verify_intel_marketing_description_log_page(struct nvme_request *req)
256 {
257 uint32_t temp_cdw10;
258
259 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_LOG_PAGE);
260
261 temp_cdw10 = ((sizeof(struct spdk_nvme_intel_marketing_description_page) / sizeof(
262 uint32_t) - 1) << 16) |
263 SPDK_NVME_INTEL_MARKETING_DESCRIPTION;
264 CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
265 }
266
267 static void
verify_namespace_attach(struct nvme_request * req)268 verify_namespace_attach(struct nvme_request *req)
269 {
270 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_NS_ATTACHMENT);
271 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_NS_CTRLR_ATTACH);
272 CU_ASSERT(req->cmd.nsid == namespace_management_nsid);
273 }
274
275 static void
verify_namespace_detach(struct nvme_request * req)276 verify_namespace_detach(struct nvme_request *req)
277 {
278 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_NS_ATTACHMENT);
279 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_NS_CTRLR_DETACH);
280 CU_ASSERT(req->cmd.nsid == namespace_management_nsid);
281 }
282
283 static void
verify_namespace_create(struct nvme_request * req)284 verify_namespace_create(struct nvme_request *req)
285 {
286 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_NS_MANAGEMENT);
287 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_NS_MANAGEMENT_CREATE);
288 CU_ASSERT(req->cmd.nsid == 0);
289 }
290
291 static void
verify_namespace_delete(struct nvme_request * req)292 verify_namespace_delete(struct nvme_request *req)
293 {
294 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_NS_MANAGEMENT);
295 CU_ASSERT(req->cmd.cdw10 == SPDK_NVME_NS_MANAGEMENT_DELETE);
296 CU_ASSERT(req->cmd.nsid == namespace_management_nsid);
297 }
298
299 static void
verify_doorbell_buffer_config(struct nvme_request * req)300 verify_doorbell_buffer_config(struct nvme_request *req)
301 {
302 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_DOORBELL_BUFFER_CONFIG);
303 CU_ASSERT(req->cmd.dptr.prp.prp1 == PRP_ENTRY_1);
304 CU_ASSERT(req->cmd.dptr.prp.prp2 == PRP_ENTRY_2);
305 }
306
307 static void
verify_format_nvme(struct nvme_request * req)308 verify_format_nvme(struct nvme_request *req)
309 {
310 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_FORMAT_NVM);
311 CU_ASSERT(req->cmd.cdw10 == 0);
312 CU_ASSERT(req->cmd.nsid == format_nvme_nsid);
313 }
314
315 static void
verify_fw_commit(struct nvme_request * req)316 verify_fw_commit(struct nvme_request *req)
317 {
318 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_FIRMWARE_COMMIT);
319 CU_ASSERT(req->cmd.cdw10 == 0x09);
320 }
321
322 static void
verify_fw_image_download(struct nvme_request * req)323 verify_fw_image_download(struct nvme_request *req)
324 {
325 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD);
326 CU_ASSERT(req->cmd.cdw10 == spdk_nvme_bytes_to_numd(fw_img_size));
327 CU_ASSERT(req->cmd.cdw11 == fw_img_offset >> 2);
328 }
329
330 static void
verify_nvme_sanitize(struct nvme_request * req)331 verify_nvme_sanitize(struct nvme_request *req)
332 {
333 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_SANITIZE);
334 CU_ASSERT(req->cmd.cdw10 == 0x309);
335 CU_ASSERT(req->cmd.cdw11 == 0);
336 CU_ASSERT(req->cmd.nsid == sanitize_nvme_nsid);
337 }
338
339 static void
verify_directive_receive(struct nvme_request * req)340 verify_directive_receive(struct nvme_request *req)
341 {
342 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_DIRECTIVE_RECEIVE);
343 CU_ASSERT(req->cmd.nsid == directive_nsid);
344 }
345
346 static void
verify_directive_send(struct nvme_request * req)347 verify_directive_send(struct nvme_request *req)
348 {
349 CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_DIRECTIVE_SEND);
350 CU_ASSERT(req->cmd.nsid == directive_nsid);
351 }
352
353 struct nvme_request *
nvme_allocate_request_user_copy(struct spdk_nvme_qpair * qpair,void * buffer,uint32_t payload_size,spdk_nvme_cmd_cb cb_fn,void * cb_arg,bool host_to_controller)354 nvme_allocate_request_user_copy(struct spdk_nvme_qpair *qpair, void *buffer, uint32_t payload_size,
355 spdk_nvme_cmd_cb cb_fn, void *cb_arg, bool host_to_controller)
356 {
357 /* For the unit test, we don't actually need to copy the buffer */
358 return nvme_allocate_request_contig(qpair, buffer, payload_size, cb_fn, cb_arg);
359 }
360
361 int
nvme_qpair_submit_request(struct spdk_nvme_qpair * qpair,struct nvme_request * req)362 nvme_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_request *req)
363 {
364 verify_fn(req);
365 /* stop analyzer from thinking stack variable addresses are stored in a global */
366 memset(req, 0, sizeof(*req));
367
368 return 0;
369 }
370
371 DEFINE_RETURN_MOCK(nvme_ctrlr_submit_admin_request, int);
372 int
nvme_ctrlr_submit_admin_request(struct spdk_nvme_ctrlr * ctrlr,struct nvme_request * req)373 nvme_ctrlr_submit_admin_request(struct spdk_nvme_ctrlr *ctrlr, struct nvme_request *req)
374 {
375 HANDLE_RETURN_MOCK(nvme_ctrlr_submit_admin_request);
376 verify_fn(req);
377 /* stop analyzer from thinking stack variable addresses are stored in a global */
378 memset(req, 0, sizeof(*req));
379
380 return 0;
381 }
382
383 static struct spdk_nvme_ns g_inactive_ns = {};
384
385 struct spdk_nvme_ns *
spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr * ctrlr,uint32_t nsid)386 spdk_nvme_ctrlr_get_ns(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid)
387 {
388 struct spdk_nvme_ns tmp;
389 struct spdk_nvme_ns *ns;
390
391 if (nsid < 1 || nsid > ctrlr->cdata.nn) {
392 return NULL;
393 }
394
395 tmp.id = nsid;
396 ns = RB_FIND(nvme_ns_tree, &ctrlr->ns, &tmp);
397
398 if (ns == NULL) {
399 return &g_inactive_ns;
400 }
401
402 return ns;
403 }
404
405 #define DECLARE_AND_CONSTRUCT_CTRLR() \
406 struct spdk_nvme_ctrlr ctrlr = {}; \
407 struct spdk_nvme_qpair adminq = {}; \
408 struct nvme_request req; \
409 \
410 STAILQ_INIT(&adminq.free_req); \
411 STAILQ_INSERT_HEAD(&adminq.free_req, &req, stailq); \
412 ctrlr.adminq = &adminq; \
413 CU_ASSERT(pthread_mutex_init(&ctrlr.ctrlr_lock, NULL) == 0);
414
415 #define DECONSTRUCT_CTRLR() \
416 CU_ASSERT(pthread_mutex_destroy(&ctrlr.ctrlr_lock) == 0);
417
418 static void
test_firmware_get_log_page(void)419 test_firmware_get_log_page(void)
420 {
421 DECLARE_AND_CONSTRUCT_CTRLR();
422 struct spdk_nvme_firmware_page payload = {};
423
424 verify_fn = verify_firmware_log_page;
425
426 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_LOG_FIRMWARE_SLOT, SPDK_NVME_GLOBAL_NS_TAG,
427 &payload,
428 sizeof(payload), 0, NULL, NULL);
429
430 DECONSTRUCT_CTRLR();
431 }
432
433 static void
test_health_get_log_page(void)434 test_health_get_log_page(void)
435 {
436 DECLARE_AND_CONSTRUCT_CTRLR();
437 struct spdk_nvme_health_information_page payload = {};
438
439 verify_fn = verify_health_log_page;
440
441 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_LOG_HEALTH_INFORMATION, health_log_nsid,
442 &payload,
443 sizeof(payload), 0, NULL, NULL);
444
445 DECONSTRUCT_CTRLR();
446 }
447
448 static void
test_error_get_log_page(void)449 test_error_get_log_page(void)
450 {
451 DECLARE_AND_CONSTRUCT_CTRLR();
452 struct spdk_nvme_error_information_entry payload = {};
453
454 ctrlr.cdata.elpe = CTRLR_CDATA_ELPE;
455
456 verify_fn = verify_error_log_page;
457
458 /* valid page */
459 error_num_entries = 1;
460 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_LOG_ERROR, SPDK_NVME_GLOBAL_NS_TAG, &payload,
461 sizeof(payload), 0, NULL, NULL);
462
463 DECONSTRUCT_CTRLR();
464 }
465
466 static void
test_intel_smart_get_log_page(void)467 test_intel_smart_get_log_page(void)
468 {
469 DECLARE_AND_CONSTRUCT_CTRLR();
470 struct spdk_nvme_intel_smart_information_page payload = {};
471
472 verify_fn = verify_intel_smart_log_page;
473
474 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_LOG_SMART, health_log_nsid, &payload,
475 sizeof(payload), 0, NULL, NULL);
476
477 DECONSTRUCT_CTRLR();
478 }
479
480 static void
test_intel_temperature_get_log_page(void)481 test_intel_temperature_get_log_page(void)
482 {
483 DECLARE_AND_CONSTRUCT_CTRLR();
484 struct spdk_nvme_intel_temperature_page payload = {};
485
486 verify_fn = verify_intel_temperature_log_page;
487
488 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_LOG_TEMPERATURE, SPDK_NVME_GLOBAL_NS_TAG,
489 &payload, sizeof(payload), 0, NULL, NULL);
490
491 DECONSTRUCT_CTRLR();
492 }
493
494 static void
test_intel_read_latency_get_log_page(void)495 test_intel_read_latency_get_log_page(void)
496 {
497 DECLARE_AND_CONSTRUCT_CTRLR();
498 struct spdk_nvme_intel_rw_latency_page payload = {};
499
500 verify_fn = verify_intel_read_latency_log_page;
501
502 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_LOG_READ_CMD_LATENCY,
503 SPDK_NVME_GLOBAL_NS_TAG,
504 &payload, sizeof(payload), 0, NULL, NULL);
505
506 DECONSTRUCT_CTRLR();
507 }
508
509 static void
test_intel_write_latency_get_log_page(void)510 test_intel_write_latency_get_log_page(void)
511 {
512 DECLARE_AND_CONSTRUCT_CTRLR();
513 struct spdk_nvme_intel_rw_latency_page payload = {};
514
515 verify_fn = verify_intel_write_latency_log_page;
516
517 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_LOG_WRITE_CMD_LATENCY,
518 SPDK_NVME_GLOBAL_NS_TAG,
519 &payload, sizeof(payload), 0, NULL, NULL);
520
521 DECONSTRUCT_CTRLR();
522 }
523
524 static void
test_intel_get_log_page_directory(void)525 test_intel_get_log_page_directory(void)
526 {
527 DECLARE_AND_CONSTRUCT_CTRLR();
528 struct spdk_nvme_intel_log_page_directory payload = {};
529
530 verify_fn = verify_intel_get_log_page_directory;
531
532 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_LOG_PAGE_DIRECTORY,
533 SPDK_NVME_GLOBAL_NS_TAG,
534 &payload, sizeof(payload), 0, NULL, NULL);
535
536 DECONSTRUCT_CTRLR();
537 }
538
539 static void
test_intel_marketing_description_get_log_page(void)540 test_intel_marketing_description_get_log_page(void)
541 {
542 DECLARE_AND_CONSTRUCT_CTRLR();
543 struct spdk_nvme_intel_marketing_description_page payload = {};
544
545 verify_fn = verify_intel_marketing_description_log_page;
546
547 spdk_nvme_ctrlr_cmd_get_log_page(&ctrlr, SPDK_NVME_INTEL_MARKETING_DESCRIPTION,
548 SPDK_NVME_GLOBAL_NS_TAG,
549 &payload, sizeof(payload), 0, NULL, NULL);
550
551 DECONSTRUCT_CTRLR();
552 }
553
554 static void
test_generic_get_log_pages(void)555 test_generic_get_log_pages(void)
556 {
557 test_error_get_log_page();
558 test_health_get_log_page();
559 test_firmware_get_log_page();
560 }
561
562 static void
test_intel_get_log_pages(void)563 test_intel_get_log_pages(void)
564 {
565 test_intel_get_log_page_directory();
566 test_intel_smart_get_log_page();
567 test_intel_temperature_get_log_page();
568 test_intel_read_latency_get_log_page();
569 test_intel_write_latency_get_log_page();
570 test_intel_marketing_description_get_log_page();
571 }
572
573 static void
test_set_feature_cmd(void)574 test_set_feature_cmd(void)
575 {
576 DECLARE_AND_CONSTRUCT_CTRLR();
577
578 verify_fn = verify_set_feature_cmd;
579
580 spdk_nvme_ctrlr_cmd_set_feature(&ctrlr, feature, feature_cdw11, feature_cdw12, NULL, 0, NULL, NULL);
581
582 DECONSTRUCT_CTRLR();
583 }
584
585 static void
test_get_feature_ns_cmd(void)586 test_get_feature_ns_cmd(void)
587 {
588 DECLARE_AND_CONSTRUCT_CTRLR();
589
590 verify_fn = verify_get_feature_ns_cmd;
591
592 spdk_nvme_ctrlr_cmd_get_feature_ns(&ctrlr, expected_feature_cdw10,
593 expected_feature_cdw11, NULL, 0,
594 NULL, NULL, expected_feature_ns);
595
596 DECONSTRUCT_CTRLR();
597 }
598
599 static void
test_set_feature_ns_cmd(void)600 test_set_feature_ns_cmd(void)
601 {
602 DECLARE_AND_CONSTRUCT_CTRLR();
603
604 verify_fn = verify_set_feature_ns_cmd;
605
606 spdk_nvme_ctrlr_cmd_set_feature_ns(&ctrlr, expected_feature_cdw10,
607 expected_feature_cdw11, expected_feature_cdw12,
608 NULL, 0, NULL, NULL, expected_feature_ns);
609
610 DECONSTRUCT_CTRLR();
611 }
612
613 static void
test_get_feature_cmd(void)614 test_get_feature_cmd(void)
615 {
616 DECLARE_AND_CONSTRUCT_CTRLR();
617
618 verify_fn = verify_get_feature_cmd;
619
620 spdk_nvme_ctrlr_cmd_get_feature(&ctrlr, get_feature, get_feature_cdw11, NULL, 0, NULL, NULL);
621
622 DECONSTRUCT_CTRLR();
623 }
624
625 static void
test_abort_cmd(void)626 test_abort_cmd(void)
627 {
628 DECLARE_AND_CONSTRUCT_CTRLR();
629 struct spdk_nvme_qpair qpair = {};
630
631 STAILQ_INIT(&ctrlr.queued_aborts);
632
633 verify_fn = verify_abort_cmd;
634
635 qpair.id = abort_sqid;
636 spdk_nvme_ctrlr_cmd_abort(&ctrlr, &qpair, abort_cid, NULL, NULL);
637
638 DECONSTRUCT_CTRLR();
639 }
640
641 static void
test_io_cmd_raw_no_payload_build(void)642 test_io_cmd_raw_no_payload_build(void)
643 {
644 DECLARE_AND_CONSTRUCT_CTRLR();
645 struct spdk_nvme_qpair qpair = {};
646 struct spdk_nvme_cmd cmd = {};
647
648 verify_fn = verify_io_cmd_raw_no_payload_build;
649
650 spdk_nvme_ctrlr_io_cmd_raw_no_payload_build(&ctrlr, &qpair, &cmd, NULL, NULL);
651
652 DECONSTRUCT_CTRLR();
653 }
654
655 static void
test_io_raw_cmd(void)656 test_io_raw_cmd(void)
657 {
658 DECLARE_AND_CONSTRUCT_CTRLR();
659 struct spdk_nvme_qpair qpair = {};
660 struct spdk_nvme_cmd cmd = {};
661
662 verify_fn = verify_io_raw_cmd;
663
664 spdk_nvme_ctrlr_cmd_io_raw(&ctrlr, &qpair, &cmd, NULL, 1, NULL, NULL);
665
666 DECONSTRUCT_CTRLR();
667 }
668
669 static void
test_io_raw_cmd_with_md(void)670 test_io_raw_cmd_with_md(void)
671 {
672 DECLARE_AND_CONSTRUCT_CTRLR();
673 struct spdk_nvme_qpair qpair = {};
674 struct spdk_nvme_cmd cmd = {};
675
676 verify_fn = verify_io_raw_cmd_with_md;
677
678 spdk_nvme_ctrlr_cmd_io_raw_with_md(&ctrlr, &qpair, &cmd, NULL, 1, NULL, NULL, NULL);
679
680 DECONSTRUCT_CTRLR();
681 }
682
683 static int
test_set_host_id_by_case(uint32_t host_id_size)684 test_set_host_id_by_case(uint32_t host_id_size)
685 {
686 DECLARE_AND_CONSTRUCT_CTRLR();
687 int rc = 0;
688
689 expected_host_id_size = host_id_size;
690 verify_fn = verify_set_host_id_cmd;
691
692 rc = nvme_ctrlr_cmd_set_host_id(&ctrlr, NULL, expected_host_id_size, NULL, NULL);
693
694 DECONSTRUCT_CTRLR();
695 return rc;
696 }
697
698 static void
test_set_host_id_cmds(void)699 test_set_host_id_cmds(void)
700 {
701 int rc = 0;
702
703 rc = test_set_host_id_by_case(8);
704 CU_ASSERT(rc == 0);
705 rc = test_set_host_id_by_case(16);
706 CU_ASSERT(rc == 0);
707 rc = test_set_host_id_by_case(1024);
708 CU_ASSERT(rc == -EINVAL);
709 }
710
711 static void
test_get_log_pages(void)712 test_get_log_pages(void)
713 {
714 test_generic_get_log_pages();
715 test_intel_get_log_pages();
716 }
717
718 static void
test_namespace_attach(void)719 test_namespace_attach(void)
720 {
721 DECLARE_AND_CONSTRUCT_CTRLR();
722 struct spdk_nvme_ctrlr_list payload = {};
723
724 verify_fn = verify_namespace_attach;
725
726 nvme_ctrlr_cmd_attach_ns(&ctrlr, namespace_management_nsid, &payload, NULL, NULL);
727
728 DECONSTRUCT_CTRLR();
729 }
730
731 static void
test_namespace_detach(void)732 test_namespace_detach(void)
733 {
734 DECLARE_AND_CONSTRUCT_CTRLR();
735 struct spdk_nvme_ctrlr_list payload = {};
736
737 verify_fn = verify_namespace_detach;
738
739 nvme_ctrlr_cmd_detach_ns(&ctrlr, namespace_management_nsid, &payload, NULL, NULL);
740
741 DECONSTRUCT_CTRLR();
742 }
743
744 static void
test_namespace_create(void)745 test_namespace_create(void)
746 {
747 DECLARE_AND_CONSTRUCT_CTRLR();
748 struct spdk_nvme_ns_data payload = {};
749
750 verify_fn = verify_namespace_create;
751 nvme_ctrlr_cmd_create_ns(&ctrlr, &payload, NULL, NULL);
752
753 DECONSTRUCT_CTRLR();
754 }
755
756 static void
test_namespace_delete(void)757 test_namespace_delete(void)
758 {
759 DECLARE_AND_CONSTRUCT_CTRLR();
760
761 verify_fn = verify_namespace_delete;
762 nvme_ctrlr_cmd_delete_ns(&ctrlr, namespace_management_nsid, NULL, NULL);
763
764 DECONSTRUCT_CTRLR();
765 }
766
767 static void
test_doorbell_buffer_config(void)768 test_doorbell_buffer_config(void)
769 {
770 DECLARE_AND_CONSTRUCT_CTRLR();
771
772 verify_fn = verify_doorbell_buffer_config;
773
774 nvme_ctrlr_cmd_doorbell_buffer_config(&ctrlr, PRP_ENTRY_1, PRP_ENTRY_2, NULL, NULL);
775
776 DECONSTRUCT_CTRLR();
777 }
778
779 static void
test_format_nvme(void)780 test_format_nvme(void)
781 {
782 DECLARE_AND_CONSTRUCT_CTRLR();
783 struct spdk_nvme_format format = {};
784
785 verify_fn = verify_format_nvme;
786
787 nvme_ctrlr_cmd_format(&ctrlr, format_nvme_nsid, &format, NULL, NULL);
788
789 DECONSTRUCT_CTRLR();
790 }
791
792 static void
test_fw_commit(void)793 test_fw_commit(void)
794 {
795 DECLARE_AND_CONSTRUCT_CTRLR();
796 struct spdk_nvme_fw_commit fw_commit = {};
797
798 fw_commit.ca = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
799 fw_commit.fs = 1;
800
801 verify_fn = verify_fw_commit;
802
803 nvme_ctrlr_cmd_fw_commit(&ctrlr, &fw_commit, NULL, NULL);
804
805 DECONSTRUCT_CTRLR();
806 }
807
808 static void
test_fw_image_download(void)809 test_fw_image_download(void)
810 {
811 DECLARE_AND_CONSTRUCT_CTRLR();
812
813 verify_fn = verify_fw_image_download;
814
815 nvme_ctrlr_cmd_fw_image_download(&ctrlr, fw_img_size, fw_img_offset, NULL,
816 NULL, NULL);
817
818 DECONSTRUCT_CTRLR();
819 }
820
821 static void
test_sanitize(void)822 test_sanitize(void)
823 {
824 DECLARE_AND_CONSTRUCT_CTRLR();
825 struct spdk_nvme_sanitize sanitize = {};
826
827 sanitize.sanact = 1;
828 sanitize.ause = 1;
829 sanitize.oipbp = 1;
830 sanitize.ndas = 1;
831
832 verify_fn = verify_nvme_sanitize;
833
834 nvme_ctrlr_cmd_sanitize(&ctrlr, sanitize_nvme_nsid, &sanitize, 0, NULL, NULL);
835
836 DECONSTRUCT_CTRLR();
837 }
838
839 static void
test_directive_receive(void)840 test_directive_receive(void)
841 {
842 DECLARE_AND_CONSTRUCT_CTRLR();
843 verify_fn = verify_directive_receive;
844
845 spdk_nvme_ctrlr_cmd_directive_receive(&ctrlr, directive_nsid, 0, 0, 0, NULL, 0,
846 0, 0, NULL, NULL);
847
848 DECONSTRUCT_CTRLR();
849 }
850
851 static void
test_directive_send(void)852 test_directive_send(void)
853 {
854 DECLARE_AND_CONSTRUCT_CTRLR();
855 verify_fn = verify_directive_send;
856
857 spdk_nvme_ctrlr_cmd_directive_send(&ctrlr, directive_nsid, 0, 0, 0, NULL, 0,
858 0, 0, NULL, NULL);
859
860 DECONSTRUCT_CTRLR();
861 }
862
863 static void
test_directive(void)864 test_directive(void)
865 {
866 test_directive_receive();
867 test_directive_send();
868 }
869
870 static void
test_nvme_request_add_abort(void)871 test_nvme_request_add_abort(void)
872 {
873 int rc;
874 struct nvme_request req = {};
875 struct nvme_request parent = {};
876 struct nvme_request child = {};
877 struct spdk_nvme_qpair qpair = {};
878 struct spdk_nvme_qpair admin_qpair = {};
879 struct spdk_nvme_ctrlr ctrlr = {};
880
881 parent.qpair = &qpair;
882 qpair.ctrlr = &ctrlr;
883 ctrlr.adminq = &admin_qpair;
884
885 parent.user_cb_arg = req.cb_arg;
886 parent.cmd.cdw10_bits.abort.sqid = 1;
887 req.cmd.cid = 2;
888
889 /* For allocating request */
890 TAILQ_INIT(&parent.children);
891 STAILQ_INIT(&admin_qpair.free_req);
892 STAILQ_INSERT_HEAD(&admin_qpair.free_req, &child, stailq);
893
894 rc = nvme_request_add_abort(&req, &parent);
895 CU_ASSERT(rc == 0);
896 SPDK_CU_ASSERT_FATAL(&child == TAILQ_FIRST(&parent.children));
897 CU_ASSERT(child.cb_arg == &child);
898 CU_ASSERT(child.cmd.opc == SPDK_NVME_OPC_ABORT);
899 CU_ASSERT(child.parent == &parent);
900 CU_ASSERT(child.cmd.cdw10_bits.abort.sqid == 1);
901 CU_ASSERT(child.cmd.cdw10_bits.abort.cid == 2);
902 CU_ASSERT(parent.num_children == 1);
903
904 nvme_request_remove_child(&parent, &child);
905 CU_ASSERT(STAILQ_EMPTY(&admin_qpair.free_req));
906 CU_ASSERT(TAILQ_EMPTY(&parent.children));
907 CU_ASSERT(parent.num_children == 0);
908 CU_ASSERT(child.parent == NULL);
909
910 /* Parent invalid */
911 req.cb_arg = (void *)0xDEADBEEF;
912 req.parent = NULL;
913 parent.user_cb_arg = (void *)0xDDADBEEF;
914 STAILQ_INSERT_HEAD(&admin_qpair.free_req, &child, stailq);
915
916 rc = nvme_request_add_abort(&req, &parent);
917 CU_ASSERT(rc == 0);
918 CU_ASSERT(!STAILQ_EMPTY(&admin_qpair.free_req));
919 STAILQ_REMOVE_HEAD(&admin_qpair.free_req, stailq);
920 CU_ASSERT(STAILQ_EMPTY(&admin_qpair.free_req));
921
922 /* Child request empty */
923 parent.user_cb_arg = req.cb_arg;
924
925 rc = nvme_request_add_abort(&req, &parent);
926 CU_ASSERT(rc == -ENOMEM);
927 }
928
929 static void
test_spdk_nvme_ctrlr_cmd_abort(void)930 test_spdk_nvme_ctrlr_cmd_abort(void)
931 {
932 int rc;
933 struct spdk_nvme_ctrlr ctrlr = {};
934 struct spdk_nvme_qpair admin_qpair = {};
935 struct spdk_nvme_qpair *qpair = NULL;
936 struct nvme_request req = {};
937
938 /* For allocating request */
939 STAILQ_INIT(&admin_qpair.free_req);
940 STAILQ_INSERT_HEAD(&admin_qpair.free_req, &req, stailq);
941 ctrlr.adminq = &admin_qpair;
942 admin_qpair.id = 0;
943 MOCK_SET(nvme_ctrlr_submit_admin_request, 0);
944 CU_ASSERT(pthread_mutex_init(&ctrlr.ctrlr_lock, NULL) == 0);
945
946 rc = spdk_nvme_ctrlr_cmd_abort(&ctrlr, qpair, 2, (void *)0xDEADBEEF, (void *)0xDCADBEEF);
947 CU_ASSERT(rc == 0);
948 CU_ASSERT(req.cb_arg == &req);
949 CU_ASSERT(req.user_cb_fn == (void *)0xDEADBEEF);
950 CU_ASSERT(req.user_cb_arg == (void *)0xDCADBEEF);
951 CU_ASSERT(req.cmd.opc == SPDK_NVME_OPC_ABORT);
952 CU_ASSERT(req.cmd.cdw10_bits.abort.sqid == 0);
953 CU_ASSERT(req.cmd.cdw10_bits.abort.cid == 2);
954 CU_ASSERT(STAILQ_EMPTY(&admin_qpair.free_req));
955
956 /* Request empty */
957 rc = spdk_nvme_ctrlr_cmd_abort(&ctrlr, qpair, 2, (void *)0xDEADBEEF, (void *)0xDCADBEEF);
958 CU_ASSERT(rc == -ENOMEM);
959 MOCK_CLEAR(nvme_ctrlr_submit_admin_request);
960 CU_ASSERT(pthread_mutex_destroy(&ctrlr.ctrlr_lock) == 0);
961 }
962
963 static void
test_nvme_ctrlr_cmd_identify(void)964 test_nvme_ctrlr_cmd_identify(void)
965 {
966 DECLARE_AND_CONSTRUCT_CTRLR();
967 struct nvme_payload payload = {};
968 int rc;
969 MOCK_SET(nvme_ctrlr_submit_admin_request, 0);
970
971 rc = nvme_ctrlr_cmd_identify(&ctrlr, SPDK_NVME_IDENTIFY_NS, 2, 1, 0, &payload,
972 SPDK_NVME_IDENTIFY_BUFLEN, NULL, NULL);
973 CU_ASSERT(rc == 0);
974 CU_ASSERT(req.cmd.opc == SPDK_NVME_OPC_IDENTIFY);
975 CU_ASSERT(req.cmd.cdw10_bits.identify.cns == SPDK_NVME_IDENTIFY_NS);
976 CU_ASSERT(req.cmd.cdw10_bits.identify.cntid == 2);
977 CU_ASSERT(req.cmd.cdw11_bits.identify.csi == 0);
978 CU_ASSERT(req.cmd.nsid == 1);
979 CU_ASSERT(STAILQ_EMPTY(&ctrlr.adminq->free_req));
980 DECONSTRUCT_CTRLR();
981 MOCK_CLEAR(nvme_ctrlr_submit_admin_request);
982 }
983
984 static void
test_spdk_nvme_ctrlr_cmd_security_receive_send(void)985 test_spdk_nvme_ctrlr_cmd_security_receive_send(void)
986 {
987 DECLARE_AND_CONSTRUCT_CTRLR();
988 struct nvme_payload payload = {};
989 int rc;
990 MOCK_SET(nvme_ctrlr_submit_admin_request, 0);
991
992 rc = spdk_nvme_ctrlr_cmd_security_send(&ctrlr, 0xea, 0xaabb, 0xcc, &payload, 4096, NULL, NULL);
993 CU_ASSERT(rc == 0);
994 CU_ASSERT(req.cmd.opc == SPDK_NVME_OPC_SECURITY_SEND);
995 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.nssf == 0xcc);
996 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.spsp0 == 0xbb);
997 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.spsp1 == 0xaa);
998 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.secp == 0xea);
999 CU_ASSERT(req.cmd.cdw11 == 4096);
1000 SPDK_CU_ASSERT_FATAL(STAILQ_EMPTY(&ctrlr.adminq->free_req));
1001
1002 memset(&req, 0, sizeof(req));
1003 STAILQ_INSERT_HEAD(&ctrlr.adminq->free_req, &req, stailq);
1004 rc = spdk_nvme_ctrlr_cmd_security_receive(&ctrlr, 0xea, 0xaabb, 0xcc, &payload, 4096, NULL, NULL);
1005 CU_ASSERT(rc == 0);
1006 CU_ASSERT(req.cmd.opc == SPDK_NVME_OPC_SECURITY_RECEIVE);
1007 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.nssf == 0xcc);
1008 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.spsp0 == 0xbb);
1009 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.spsp1 == 0xaa);
1010 CU_ASSERT(req.cmd.cdw10_bits.sec_send_recv.secp == 0xea);
1011 CU_ASSERT(req.cmd.cdw11 == 4096);
1012 SPDK_CU_ASSERT_FATAL(STAILQ_EMPTY(&ctrlr.adminq->free_req));
1013 MOCK_CLEAR(nvme_ctrlr_submit_admin_request);
1014
1015 /* Without request valid. */
1016 rc = spdk_nvme_ctrlr_cmd_security_send(&ctrlr, 0xea, 0xaabb, 0xcc, &payload, 4096, NULL, NULL);
1017 CU_ASSERT(rc == -ENOMEM);
1018
1019 rc = spdk_nvme_ctrlr_cmd_security_receive(&ctrlr, 0xea, 0xaabb, 0xcc, &payload, 4096, NULL, NULL);
1020 CU_ASSERT(rc == -ENOMEM);
1021 DECONSTRUCT_CTRLR();
1022 }
1023
1024 int
main(int argc,char ** argv)1025 main(int argc, char **argv)
1026 {
1027 CU_pSuite suite = NULL;
1028 unsigned int num_failures;
1029
1030 CU_initialize_registry();
1031
1032 suite = CU_add_suite("nvme_ctrlr_cmd", NULL, NULL);
1033
1034 CU_ADD_TEST(suite, test_get_log_pages);
1035 CU_ADD_TEST(suite, test_set_feature_cmd);
1036 CU_ADD_TEST(suite, test_set_feature_ns_cmd);
1037 CU_ADD_TEST(suite, test_get_feature_cmd);
1038 CU_ADD_TEST(suite, test_get_feature_ns_cmd);
1039 CU_ADD_TEST(suite, test_abort_cmd);
1040 CU_ADD_TEST(suite, test_set_host_id_cmds);
1041 CU_ADD_TEST(suite, test_io_cmd_raw_no_payload_build);
1042 CU_ADD_TEST(suite, test_io_raw_cmd);
1043 CU_ADD_TEST(suite, test_io_raw_cmd_with_md);
1044 CU_ADD_TEST(suite, test_namespace_attach);
1045 CU_ADD_TEST(suite, test_namespace_detach);
1046 CU_ADD_TEST(suite, test_namespace_create);
1047 CU_ADD_TEST(suite, test_namespace_delete);
1048 CU_ADD_TEST(suite, test_doorbell_buffer_config);
1049 CU_ADD_TEST(suite, test_format_nvme);
1050 CU_ADD_TEST(suite, test_fw_commit);
1051 CU_ADD_TEST(suite, test_fw_image_download);
1052 CU_ADD_TEST(suite, test_sanitize);
1053 CU_ADD_TEST(suite, test_directive);
1054 CU_ADD_TEST(suite, test_nvme_request_add_abort);
1055 CU_ADD_TEST(suite, test_spdk_nvme_ctrlr_cmd_abort);
1056 CU_ADD_TEST(suite, test_nvme_ctrlr_cmd_identify);
1057 CU_ADD_TEST(suite, test_spdk_nvme_ctrlr_cmd_security_receive_send);
1058
1059 num_failures = spdk_ut_run_tests(argc, argv, NULL);
1060 CU_cleanup_registry();
1061 return num_failures;
1062 }
1063