xref: /spdk/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c (revision a3ae6eaa75cd933b3c198db169c751ca335b5be7)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2017 Intel Corporation.
3  *   All rights reserved.
4  *   Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5  */
6 
7 #include "spdk/stdinc.h"
8 
9 #include "spdk_cunit.h"
10 #include "spdk_internal/mock.h"
11 
12 #include "common/lib/test_env.c"
13 #include "spdk/bdev_module.h"
14 #include "nvmf/ctrlr_discovery.c"
15 #include "nvmf/subsystem.c"
16 
17 SPDK_LOG_REGISTER_COMPONENT(nvmf)
18 
19 DEFINE_STUB_V(spdk_bdev_module_release_bdev,
20 	      (struct spdk_bdev *bdev));
21 
22 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t,
23 	    (const struct spdk_bdev *bdev), 512);
24 
25 DEFINE_STUB(spdk_nvmf_transport_stop_listen,
26 	    int,
27 	    (struct spdk_nvmf_transport *transport,
28 	     const struct spdk_nvme_transport_id *trid), 0);
29 
30 DEFINE_STUB(spdk_nvmf_transport_get_first,
31 	    struct spdk_nvmf_transport *,
32 	    (struct spdk_nvmf_tgt *tgt), NULL);
33 
34 DEFINE_STUB(spdk_nvmf_transport_get_next,
35 	    struct spdk_nvmf_transport *,
36 	    (struct spdk_nvmf_transport *transport), NULL);
37 
38 DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
39 
40 DEFINE_STUB_V(nvmf_ctrlr_async_event_discovery_log_change_notice, (void *ctx));
41 
42 DEFINE_STUB(spdk_nvmf_qpair_disconnect, int,
43 	    (struct spdk_nvmf_qpair *qpair,
44 	     nvmf_qpair_disconnect_cb cb_fn, void *ctx), 0);
45 
46 DEFINE_STUB(spdk_bdev_open_ext, int,
47 	    (const char *bdev_name, bool write,	spdk_bdev_event_cb_t event_cb,
48 	     void *event_ctx, struct spdk_bdev_desc **desc), 0);
49 
50 DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *,
51 	    (struct spdk_bdev_desc *desc), NULL);
52 
53 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
54 	    (const struct spdk_bdev *bdev), 0);
55 
56 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
57 	    (const struct spdk_bdev *bdev), false);
58 
59 DEFINE_STUB(spdk_bdev_module_claim_bdev, int,
60 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
61 	     struct spdk_bdev_module *module), 0);
62 
63 DEFINE_STUB(spdk_bdev_io_type_supported, bool,
64 	    (struct spdk_bdev *bdev, enum spdk_bdev_io_type io_type), false);
65 
66 DEFINE_STUB_V(nvmf_ctrlr_reservation_notice_log,
67 	      (struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ns *ns,
68 	       enum spdk_nvme_reservation_notification_log_page_type type));
69 
70 DEFINE_STUB(spdk_nvmf_request_complete, int,
71 	    (struct spdk_nvmf_request *req), -1);
72 
73 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, int,
74 	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
75 
76 DEFINE_STUB(spdk_nvme_transport_id_trtype_str, const char *,
77 	    (enum spdk_nvme_transport_type trtype), NULL);
78 
79 DEFINE_STUB(spdk_bdev_is_zoned, bool, (const struct spdk_bdev *bdev), false);
80 
81 DEFINE_STUB(spdk_bdev_get_max_zone_append_size, uint32_t,
82 	    (const struct spdk_bdev *bdev), 0);
83 
84 const char *
85 spdk_bdev_get_name(const struct spdk_bdev *bdev)
86 {
87 	return "test";
88 }
89 
90 const struct spdk_uuid *
91 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
92 {
93 	return &bdev->uuid;
94 }
95 
96 int
97 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
98 			       const struct spdk_nvme_transport_id *trid2)
99 {
100 	return !(trid1->trtype == trid2->trtype && strcasecmp(trid1->traddr, trid2->traddr) == 0 &&
101 		 strcasecmp(trid1->trsvcid, trid2->trsvcid) == 0);
102 }
103 
104 int
105 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
106 			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
107 {
108 	return 0;
109 }
110 
111 static struct spdk_nvmf_listener g_listener = {};
112 
113 struct spdk_nvmf_listener *
114 nvmf_transport_find_listener(struct spdk_nvmf_transport *transport,
115 			     const struct spdk_nvme_transport_id *trid)
116 {
117 	struct spdk_nvmf_listener *listener;
118 
119 	if (TAILQ_EMPTY(&transport->listeners)) {
120 		return &g_listener;
121 	}
122 
123 	TAILQ_FOREACH(listener, &transport->listeners, link) {
124 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
125 			return listener;
126 		}
127 	}
128 
129 	return NULL;
130 }
131 
132 void
133 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
134 				 struct spdk_nvme_transport_id *trid,
135 				 struct spdk_nvmf_discovery_log_page_entry *entry)
136 {
137 	transport->ops->listener_discover(transport, trid, entry);
138 }
139 
140 static void
141 test_dummy_listener_discover(struct spdk_nvmf_transport *transport,
142 			     struct spdk_nvme_transport_id *trid, struct spdk_nvmf_discovery_log_page_entry *entry)
143 {
144 	entry->trtype = 42;
145 }
146 
147 struct spdk_nvmf_transport_ops g_transport_ops = { .listener_discover = test_dummy_listener_discover };
148 
149 static struct spdk_nvmf_transport g_transport = {
150 	.ops = &g_transport_ops
151 };
152 
153 struct spdk_nvmf_transport *
154 spdk_nvmf_transport_create(const char *transport_name,
155 			   struct spdk_nvmf_transport_opts *tprt_opts)
156 {
157 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
158 		return &g_transport;
159 	}
160 
161 	return NULL;
162 }
163 
164 struct spdk_nvmf_subsystem *
165 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
166 {
167 	return NULL;
168 }
169 
170 DEFINE_RETURN_MOCK(spdk_nvmf_tgt_get_transport, struct spdk_nvmf_transport *);
171 struct spdk_nvmf_transport *
172 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
173 {
174 	HANDLE_RETURN_MOCK(spdk_nvmf_tgt_get_transport);
175 	return &g_transport;
176 }
177 
178 int
179 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
180 {
181 	if (trtype == NULL || str == NULL) {
182 		return -EINVAL;
183 	}
184 
185 	if (strcasecmp(str, "PCIe") == 0) {
186 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
187 	} else if (strcasecmp(str, "RDMA") == 0) {
188 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
189 	} else {
190 		return -ENOENT;
191 	}
192 	return 0;
193 }
194 
195 void
196 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
197 {
198 }
199 
200 void
201 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
202 {
203 }
204 
205 int
206 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
207 				 struct spdk_nvmf_subsystem *subsystem)
208 {
209 	return 0;
210 }
211 
212 int
213 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
214 			      struct spdk_nvmf_subsystem *subsystem,
215 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
216 {
217 	return 0;
218 }
219 
220 void
221 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
222 				 struct spdk_nvmf_subsystem *subsystem,
223 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
224 {
225 }
226 
227 void
228 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
229 				struct spdk_nvmf_subsystem *subsystem,
230 				uint32_t nsid,
231 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
232 {
233 }
234 
235 void
236 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
237 				 struct spdk_nvmf_subsystem *subsystem,
238 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
239 {
240 }
241 
242 static void
243 _subsystem_add_listen_done(void *cb_arg, int status)
244 {
245 	SPDK_CU_ASSERT_FATAL(status == 0);
246 }
247 
248 static void
249 test_gen_trid(struct spdk_nvme_transport_id *trid, enum spdk_nvme_transport_type trtype,
250 	      enum spdk_nvmf_adrfam adrfam, const char *tradd, const char *trsvcid)
251 {
252 	snprintf(trid->traddr, sizeof(trid->traddr), "%s", tradd);
253 	snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", trsvcid);
254 	trid->adrfam = adrfam;
255 	trid->trtype = trtype;
256 	switch (trtype) {
257 	case SPDK_NVME_TRANSPORT_RDMA:
258 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_RDMA);
259 		break;
260 	case SPDK_NVME_TRANSPORT_TCP:
261 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_TCP);
262 		break;
263 	default:
264 		SPDK_CU_ASSERT_FATAL(0 && "not supported by test");
265 	}
266 }
267 
268 static void
269 test_discovery_log(void)
270 {
271 	struct spdk_nvmf_tgt tgt = {};
272 	struct spdk_nvmf_subsystem *subsystem;
273 	uint8_t buffer[8192];
274 	struct iovec iov;
275 	struct spdk_nvmf_discovery_log_page *disc_log;
276 	struct spdk_nvmf_discovery_log_page_entry *entry;
277 	struct spdk_nvme_transport_id trid = {};
278 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
279 	int rc;
280 
281 	iov.iov_base = buffer;
282 	iov.iov_len = 8192;
283 
284 	tgt.max_subsystems = 1024;
285 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
286 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
287 
288 	/* Add one subsystem and verify that the discovery log contains it */
289 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
290 					       SPDK_NVMF_SUBTYPE_NVME, 0);
291 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
292 
293 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn);
294 	CU_ASSERT(rc == 0);
295 
296 	/* Get only genctr (first field in the header) */
297 	memset(buffer, 0xCC, sizeof(buffer));
298 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
299 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
300 				    &trid);
301 	/* No listeners yet on new subsystem, so genctr should still be 0. */
302 	CU_ASSERT(disc_log->genctr == 0);
303 
304 	test_gen_trid(&trid, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "1234", "5678");
305 	spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL);
306 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
307 
308 	/* Get only genctr (first field in the header) */
309 	memset(buffer, 0xCC, sizeof(buffer));
310 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
311 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
312 				    &trid);
313 	CU_ASSERT(disc_log->genctr == 1); /* one added subsystem and listener */
314 
315 	/* Get only the header, no entries */
316 	memset(buffer, 0xCC, sizeof(buffer));
317 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
318 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
319 				    &trid);
320 	CU_ASSERT(disc_log->genctr == 1);
321 	CU_ASSERT(disc_log->numrec == 1);
322 
323 	/* Offset 0, exact size match */
324 	memset(buffer, 0xCC, sizeof(buffer));
325 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
326 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0,
327 				    sizeof(*disc_log) + sizeof(disc_log->entries[0]), &trid);
328 	CU_ASSERT(disc_log->genctr != 0);
329 	CU_ASSERT(disc_log->numrec == 1);
330 	CU_ASSERT(disc_log->entries[0].trtype == 42);
331 
332 	/* Offset 0, oversize buffer */
333 	memset(buffer, 0xCC, sizeof(buffer));
334 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
335 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(buffer), &trid);
336 	CU_ASSERT(disc_log->genctr != 0);
337 	CU_ASSERT(disc_log->numrec == 1);
338 	CU_ASSERT(disc_log->entries[0].trtype == 42);
339 	CU_ASSERT(spdk_mem_all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]),
340 				    sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0]))));
341 
342 	/* Get just the first entry, no header */
343 	memset(buffer, 0xCC, sizeof(buffer));
344 	entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
345 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1,
346 				    offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), sizeof(*entry), &trid);
347 	CU_ASSERT(entry->trtype == 42);
348 
349 	/* remove the host and verify that the discovery log contains nothing */
350 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
351 	CU_ASSERT(rc == 0);
352 
353 	/* Get only the header, no entries */
354 	memset(buffer, 0xCC, sizeof(buffer));
355 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
356 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
357 				    &trid);
358 	CU_ASSERT(disc_log->genctr != 0);
359 	CU_ASSERT(disc_log->numrec == 0);
360 
361 	/* destroy the subsystem and verify that the discovery log contains nothing */
362 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
363 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
364 	CU_ASSERT(rc == 0);
365 
366 	/* Get only the header, no entries */
367 	memset(buffer, 0xCC, sizeof(buffer));
368 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
369 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
370 				    &trid);
371 	CU_ASSERT(disc_log->genctr != 0);
372 	CU_ASSERT(disc_log->numrec == 0);
373 
374 	free(tgt.subsystems);
375 }
376 
377 static void
378 test_rdma_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
379 		   struct spdk_nvmf_discovery_log_page_entry *entry)
380 {
381 	entry->trtype = SPDK_NVMF_TRTYPE_RDMA;
382 	entry->adrfam = trid->adrfam;
383 	memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
384 	memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
385 }
386 
387 static void
388 test_tcp_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
389 		  struct spdk_nvmf_discovery_log_page_entry *entry)
390 {
391 	entry->trtype = SPDK_NVMF_TRTYPE_TCP;
392 	entry->adrfam = trid->adrfam;
393 	memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
394 	memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
395 }
396 
397 static void
398 test_discovery_log_with_filters(void)
399 {
400 	struct spdk_nvmf_tgt tgt = {};
401 	struct spdk_nvmf_transport_ops rdma_tr_ops = { .listener_discover = test_rdma_discover }, tcp_tr_ops
402 		= { .listener_discover = test_tcp_discover };
403 	struct spdk_nvmf_transport rdma_tr = {.ops = &rdma_tr_ops }, tcp_tr = { .ops = &tcp_tr_ops };
404 	struct spdk_nvmf_subsystem *subsystem;
405 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
406 	uint8_t buffer[8192];
407 	struct iovec iov;
408 	struct spdk_nvmf_discovery_log_page *disc_log;
409 	struct spdk_nvmf_listener rdma_listener_1 = {}, rdma_listener_2 = {}, rdma_listener_3 = {},
410 	tcp_listener_1 = {}, tcp_listener_2 = {}, tcp_listener_3 = {};
411 	struct spdk_nvme_transport_id rdma_trid_1 = {}, rdma_trid_2 = {}, rdma_trid_3 = {}, tcp_trid_1 = {},
412 	tcp_trid_2 = {}, tcp_trid_3 = {};
413 
414 	iov.iov_base = buffer;
415 	iov.iov_len = 8192;
416 
417 	tgt.max_subsystems = 4;
418 	tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
419 	SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
420 
421 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
422 					       SPDK_NVMF_SUBTYPE_NVME, 0);
423 	subsystem->flags.allow_any_host = true;
424 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
425 
426 	test_gen_trid(&rdma_trid_1, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4420");
427 	test_gen_trid(&rdma_trid_2, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4420");
428 	test_gen_trid(&rdma_trid_3, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4421");
429 	test_gen_trid(&tcp_trid_1, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4421");
430 	test_gen_trid(&tcp_trid_2, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4422");
431 	test_gen_trid(&tcp_trid_3, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4422");
432 
433 	rdma_listener_1.trid = rdma_trid_1;
434 	rdma_listener_2.trid = rdma_trid_2;
435 	rdma_listener_3.trid = rdma_trid_3;
436 	TAILQ_INIT(&rdma_tr.listeners);
437 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_1, link);
438 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_2, link);
439 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_3, link);
440 
441 	tcp_listener_1.trid = tcp_trid_1;
442 	tcp_listener_2.trid = tcp_trid_2;
443 	tcp_listener_3.trid = tcp_trid_3;
444 	TAILQ_INIT(&tcp_tr.listeners);
445 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_1, link);
446 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_2, link);
447 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_3, link);
448 
449 	MOCK_SET(spdk_nvmf_tgt_get_transport, &rdma_tr);
450 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_1, _subsystem_add_listen_done, NULL);
451 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_2, _subsystem_add_listen_done, NULL);
452 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_3, _subsystem_add_listen_done, NULL);
453 	MOCK_SET(spdk_nvmf_tgt_get_transport, &tcp_tr);
454 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_1, _subsystem_add_listen_done, NULL);
455 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_2, _subsystem_add_listen_done, NULL);
456 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_3, _subsystem_add_listen_done, NULL);
457 	MOCK_CLEAR(spdk_nvmf_tgt_get_transport);
458 
459 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
460 
461 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
462 	memset(buffer, 0, sizeof(buffer));
463 
464 	/* Test case 1 - check that all trids are reported */
465 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
466 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
467 	CU_ASSERT(disc_log->numrec == 6);
468 
469 	/* Test case 2 - check that only entries of the same transport type are returned */
470 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
471 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
472 	CU_ASSERT(disc_log->numrec == 3);
473 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
474 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
475 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_1.trtype);
476 
477 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
478 	CU_ASSERT(disc_log->numrec == 3);
479 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
480 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
481 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_1.trtype);
482 
483 	/* Test case 3 - check that only entries of the same transport address are returned */
484 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
485 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
486 	CU_ASSERT(disc_log->numrec == 3);
487 	/* one tcp and 2 rdma  */
488 	CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
489 		  != 0);
490 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
491 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
492 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_1.traddr) == 0);
493 
494 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
495 	CU_ASSERT(disc_log->numrec == 3);
496 	/* one rdma and two tcp */
497 	CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
498 		  != 0);
499 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
500 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
501 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_1.traddr) == 0);
502 
503 	/* Test case 4 - check that only entries of the same transport address and type returned */
504 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
505 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
506 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
507 	CU_ASSERT(disc_log->numrec == 2);
508 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
509 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
510 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
511 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
512 
513 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
514 	CU_ASSERT(disc_log->numrec == 1);
515 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
516 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
517 
518 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
519 	CU_ASSERT(disc_log->numrec == 2);
520 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
521 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
522 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
523 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
524 
525 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
526 	CU_ASSERT(disc_log->numrec == 1);
527 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
528 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
529 
530 	/* Test case 5 - check that only entries of the same transport address and type returned */
531 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
532 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
533 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
534 	CU_ASSERT(disc_log->numrec == 2);
535 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
536 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, rdma_trid_2.trsvcid) == 0);
537 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
538 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_2.trtype);
539 
540 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
541 	CU_ASSERT(disc_log->numrec == 1);
542 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
543 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
544 
545 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
546 	CU_ASSERT(disc_log->numrec == 1);
547 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
548 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
549 
550 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
551 	CU_ASSERT(disc_log->numrec == 2);
552 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
553 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_2.trsvcid) == 0);
554 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
555 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_2.trtype);
556 
557 	/* Test case 6 - check that only entries of the same transport address and type returned.
558 	 * That also implies trtype since RDMA and TCP listeners can't occupy the same socket */
559 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
560 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
561 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
562 	CU_ASSERT(disc_log->numrec == 1);
563 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
564 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
565 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
566 
567 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
568 	CU_ASSERT(disc_log->numrec == 1);
569 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
570 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
571 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
572 
573 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
574 	CU_ASSERT(disc_log->numrec == 1);
575 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
576 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
577 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
578 
579 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
580 	CU_ASSERT(disc_log->numrec == 1);
581 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
582 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
583 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
584 
585 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
586 	CU_ASSERT(disc_log->numrec == 1);
587 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
588 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
589 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
590 
591 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
592 	CU_ASSERT(disc_log->numrec == 1);
593 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
594 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
595 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
596 
597 	/* Test case 7 - check that only entries of the same transport address, svcid and type returned */
598 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
599 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
600 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
601 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
602 	CU_ASSERT(disc_log->numrec == 1);
603 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
604 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
605 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
606 
607 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
608 	CU_ASSERT(disc_log->numrec == 1);
609 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
610 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
611 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
612 
613 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
614 	CU_ASSERT(disc_log->numrec == 1);
615 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
616 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
617 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
618 
619 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
620 	CU_ASSERT(disc_log->numrec == 1);
621 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
622 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
623 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
624 
625 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
626 	CU_ASSERT(disc_log->numrec == 1);
627 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
628 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
629 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
630 
631 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
632 	CU_ASSERT(disc_log->numrec == 1);
633 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
634 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
635 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
636 
637 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
638 	spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
639 	free(tgt.subsystems);
640 }
641 
642 int
643 main(int argc, char **argv)
644 {
645 	CU_pSuite	suite = NULL;
646 	unsigned int	num_failures;
647 
648 	CU_set_error_action(CUEA_ABORT);
649 	CU_initialize_registry();
650 
651 	suite = CU_add_suite("nvmf", NULL, NULL);
652 
653 	CU_ADD_TEST(suite, test_discovery_log);
654 	CU_ADD_TEST(suite, test_discovery_log_with_filters);
655 
656 	CU_basic_set_mode(CU_BRM_VERBOSE);
657 	CU_basic_run_tests();
658 	num_failures = CU_get_number_of_failures();
659 	CU_cleanup_registry();
660 	return num_failures;
661 }
662