xref: /spdk/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c (revision 5a8c76d991809d2b09d0d68cf3a81951410d5bff)
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_internal/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 DEFINE_STUB(spdk_nvmf_qpair_disconnect, int, (struct spdk_nvmf_qpair *qpair), 0);
42 
43 DEFINE_STUB(spdk_bdev_open_ext, int,
44 	    (const char *bdev_name, bool write,	spdk_bdev_event_cb_t event_cb,
45 	     void *event_ctx, struct spdk_bdev_desc **desc), 0);
46 
47 DEFINE_STUB(spdk_bdev_desc_get_bdev, struct spdk_bdev *,
48 	    (struct spdk_bdev_desc *desc), NULL);
49 
50 DEFINE_STUB(spdk_bdev_get_md_size, uint32_t,
51 	    (const struct spdk_bdev *bdev), 0);
52 
53 DEFINE_STUB(spdk_bdev_is_md_interleaved, bool,
54 	    (const struct spdk_bdev *bdev), false);
55 
56 DEFINE_STUB(spdk_bdev_module_claim_bdev, int,
57 	    (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
58 	     struct spdk_bdev_module *module), 0);
59 
60 DEFINE_STUB(spdk_bdev_io_type_supported, bool,
61 	    (struct spdk_bdev *bdev, enum spdk_bdev_io_type io_type), false);
62 
63 DEFINE_STUB_V(nvmf_ctrlr_reservation_notice_log,
64 	      (struct spdk_nvmf_ctrlr *ctrlr, struct spdk_nvmf_ns *ns,
65 	       enum spdk_nvme_reservation_notification_log_page_type type));
66 
67 DEFINE_STUB(spdk_nvmf_request_complete, int,
68 	    (struct spdk_nvmf_request *req), -1);
69 
70 DEFINE_STUB(nvmf_ctrlr_async_event_ana_change_notice, int,
71 	    (struct spdk_nvmf_ctrlr *ctrlr), 0);
72 
73 DEFINE_STUB(nvmf_ctrlr_async_event_ns_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 DEFINE_STUB(spdk_key_dup, struct spdk_key *, (struct spdk_key *k), NULL);
84 DEFINE_STUB(spdk_key_get_name, const char *, (struct spdk_key *k), NULL);
85 DEFINE_STUB_V(spdk_keyring_put_key, (struct spdk_key *k));
86 DEFINE_STUB(nvmf_auth_is_supported, bool, (void), false);
87 
88 DEFINE_STUB(spdk_bdev_get_nvme_ctratt, union spdk_bdev_nvme_ctratt,
89 	    (struct spdk_bdev *bdev), {});
90 DEFINE_STUB(nvmf_tgt_update_mdns_prr, int, (struct spdk_nvmf_tgt *tgt), 0);
91 
92 const char *
93 spdk_bdev_get_name(const struct spdk_bdev *bdev)
94 {
95 	return "test";
96 }
97 
98 const struct spdk_uuid *
99 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
100 {
101 	return &bdev->uuid;
102 }
103 
104 int
105 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
106 			       const struct spdk_nvme_transport_id *trid2)
107 {
108 	return !(trid1->trtype == trid2->trtype && strcasecmp(trid1->traddr, trid2->traddr) == 0 &&
109 		 strcasecmp(trid1->trsvcid, trid2->trsvcid) == 0);
110 }
111 
112 int
113 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
114 			   const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
115 {
116 	return 0;
117 }
118 
119 static struct spdk_nvmf_listener g_listener = {};
120 
121 struct spdk_nvmf_listener *
122 nvmf_transport_find_listener(struct spdk_nvmf_transport *transport,
123 			     const struct spdk_nvme_transport_id *trid)
124 {
125 	struct spdk_nvmf_listener *listener;
126 
127 	if (TAILQ_EMPTY(&transport->listeners)) {
128 		return &g_listener;
129 	}
130 
131 	TAILQ_FOREACH(listener, &transport->listeners, link) {
132 		if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
133 			return listener;
134 		}
135 	}
136 
137 	return NULL;
138 }
139 
140 void
141 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
142 				 struct spdk_nvme_transport_id *trid,
143 				 struct spdk_nvmf_discovery_log_page_entry *entry)
144 {
145 	transport->ops->listener_discover(transport, trid, entry);
146 }
147 
148 static void
149 test_dummy_listener_discover(struct spdk_nvmf_transport *transport,
150 			     struct spdk_nvme_transport_id *trid, struct spdk_nvmf_discovery_log_page_entry *entry)
151 {
152 	entry->trtype = 42;
153 }
154 
155 struct spdk_nvmf_transport_ops g_transport_ops = { .listener_discover = test_dummy_listener_discover };
156 
157 static struct spdk_nvmf_transport g_transport = {
158 	.ops = &g_transport_ops
159 };
160 
161 int
162 spdk_nvmf_transport_create_async(const char *transport_name,
163 				 struct spdk_nvmf_transport_opts *tprt_opts,
164 				 spdk_nvmf_transport_create_done_cb cb_fn, void *cb_arg)
165 {
166 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
167 		cb_fn(cb_arg, &g_transport);
168 		return 0;
169 	}
170 
171 	return -1;
172 }
173 
174 struct spdk_nvmf_subsystem *
175 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
176 {
177 	return NULL;
178 }
179 
180 DEFINE_RETURN_MOCK(spdk_nvmf_tgt_get_transport, struct spdk_nvmf_transport *);
181 struct spdk_nvmf_transport *
182 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
183 {
184 	HANDLE_RETURN_MOCK(spdk_nvmf_tgt_get_transport);
185 	return &g_transport;
186 }
187 
188 int
189 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
190 {
191 	if (trtype == NULL || str == NULL) {
192 		return -EINVAL;
193 	}
194 
195 	if (strcasecmp(str, "PCIe") == 0) {
196 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
197 	} else if (strcasecmp(str, "RDMA") == 0) {
198 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
199 	} else {
200 		return -ENOENT;
201 	}
202 	return 0;
203 }
204 
205 void
206 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
207 {
208 }
209 
210 void
211 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
212 {
213 }
214 
215 int
216 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
217 				 struct spdk_nvmf_subsystem *subsystem)
218 {
219 	return 0;
220 }
221 
222 int
223 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
224 			      struct spdk_nvmf_subsystem *subsystem,
225 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
226 {
227 	return 0;
228 }
229 
230 void
231 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group,
232 				 struct spdk_nvmf_subsystem *subsystem,
233 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
234 {
235 }
236 
237 void
238 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
239 				struct spdk_nvmf_subsystem *subsystem,
240 				uint32_t nsid,
241 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
242 {
243 }
244 
245 void
246 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
247 				 struct spdk_nvmf_subsystem *subsystem,
248 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
249 {
250 }
251 
252 static void
253 _subsystem_add_listen_done(void *cb_arg, int status)
254 {
255 	SPDK_CU_ASSERT_FATAL(status == 0);
256 }
257 
258 static void
259 test_gen_trid(struct spdk_nvme_transport_id *trid, enum spdk_nvme_transport_type trtype,
260 	      enum spdk_nvmf_adrfam adrfam, const char *tradd, const char *trsvcid)
261 {
262 	snprintf(trid->traddr, sizeof(trid->traddr), "%s", tradd);
263 	snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", trsvcid);
264 	trid->adrfam = adrfam;
265 	trid->trtype = trtype;
266 	switch (trtype) {
267 	case SPDK_NVME_TRANSPORT_RDMA:
268 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_RDMA);
269 		break;
270 	case SPDK_NVME_TRANSPORT_TCP:
271 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_TCP);
272 		break;
273 	default:
274 		SPDK_CU_ASSERT_FATAL(0 && "not supported by test");
275 	}
276 }
277 
278 static void
279 test_discovery_log(void)
280 {
281 	struct spdk_nvmf_tgt tgt = {};
282 	struct spdk_nvmf_subsystem *subsystem;
283 	uint8_t buffer[8192];
284 	struct iovec iov;
285 	struct spdk_nvmf_discovery_log_page *disc_log;
286 	struct spdk_nvmf_discovery_log_page_entry *entry;
287 	struct spdk_nvme_transport_id trid = {};
288 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
289 	int rc;
290 
291 	iov.iov_base = buffer;
292 	iov.iov_len = 8192;
293 
294 	tgt.max_subsystems = 1024;
295 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
296 	RB_INIT(&tgt.subsystems);
297 
298 	/* Add one subsystem and verify that the discovery log contains it */
299 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
300 					       SPDK_NVMF_SUBTYPE_NVME, 0);
301 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
302 
303 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn, NULL);
304 	CU_ASSERT(rc == 0);
305 
306 	/* Get only genctr (first field in the header) */
307 	memset(buffer, 0xCC, sizeof(buffer));
308 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
309 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
310 				    &trid);
311 	/* No listeners yet on new subsystem, so genctr should still be 0. */
312 	CU_ASSERT(disc_log->genctr == 0);
313 
314 	test_gen_trid(&trid, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "1234", "5678");
315 	spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL);
316 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
317 
318 	/* Get only genctr (first field in the header) */
319 	memset(buffer, 0xCC, sizeof(buffer));
320 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
321 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
322 				    &trid);
323 	CU_ASSERT(disc_log->genctr == 1); /* one added subsystem and listener */
324 
325 	/* Get only the header, no entries */
326 	memset(buffer, 0xCC, sizeof(buffer));
327 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
328 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
329 				    &trid);
330 	CU_ASSERT(disc_log->genctr == 1);
331 	CU_ASSERT(disc_log->numrec == 1);
332 
333 	/* Offset 0, exact size match */
334 	memset(buffer, 0xCC, sizeof(buffer));
335 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
336 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0,
337 				    sizeof(*disc_log) + sizeof(disc_log->entries[0]), &trid);
338 	CU_ASSERT(disc_log->genctr != 0);
339 	CU_ASSERT(disc_log->numrec == 1);
340 	CU_ASSERT(disc_log->entries[0].trtype == 42);
341 
342 	/* Offset 0, oversize buffer */
343 	memset(buffer, 0xCC, sizeof(buffer));
344 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
345 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(buffer), &trid);
346 	CU_ASSERT(disc_log->genctr != 0);
347 	CU_ASSERT(disc_log->numrec == 1);
348 	CU_ASSERT(disc_log->entries[0].trtype == 42);
349 	CU_ASSERT(spdk_mem_all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]),
350 				    sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0]))));
351 
352 	/* Get just the first entry, no header */
353 	memset(buffer, 0xCC, sizeof(buffer));
354 	entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
355 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1,
356 				    offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), sizeof(*entry), &trid);
357 	CU_ASSERT(entry->trtype == 42);
358 
359 	/* remove the host and verify that the discovery log contains nothing */
360 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
361 	CU_ASSERT(rc == 0);
362 
363 	/* Get only the header, no entries */
364 	memset(buffer, 0xCC, sizeof(buffer));
365 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
366 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
367 				    &trid);
368 	CU_ASSERT(disc_log->genctr != 0);
369 	CU_ASSERT(disc_log->numrec == 0);
370 
371 	/* destroy the subsystem and verify that the discovery log contains nothing */
372 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
373 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
374 	CU_ASSERT(rc == 0);
375 
376 	/* Get only the header, no entries */
377 	memset(buffer, 0xCC, sizeof(buffer));
378 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
379 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
380 				    &trid);
381 	CU_ASSERT(disc_log->genctr != 0);
382 	CU_ASSERT(disc_log->numrec == 0);
383 
384 	spdk_bit_array_free(&tgt.subsystem_ids);
385 }
386 
387 static void
388 test_rdma_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_RDMA;
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_tcp_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
399 		  struct spdk_nvmf_discovery_log_page_entry *entry)
400 {
401 	entry->trtype = SPDK_NVMF_TRTYPE_TCP;
402 	entry->adrfam = trid->adrfam;
403 	memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
404 	memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
405 }
406 
407 static void
408 test_discovery_log_with_filters(void)
409 {
410 	struct spdk_nvmf_tgt tgt = {};
411 	struct spdk_nvmf_transport_ops rdma_tr_ops = { .listener_discover = test_rdma_discover }, tcp_tr_ops
412 		= { .listener_discover = test_tcp_discover };
413 	struct spdk_nvmf_transport rdma_tr = {.ops = &rdma_tr_ops }, tcp_tr = { .ops = &tcp_tr_ops };
414 	struct spdk_nvmf_subsystem *subsystem;
415 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
416 	uint8_t buffer[8192];
417 	struct iovec iov;
418 	struct spdk_nvmf_discovery_log_page *disc_log;
419 	struct spdk_nvmf_listener rdma_listener_1 = {}, rdma_listener_2 = {}, rdma_listener_3 = {},
420 	tcp_listener_1 = {}, tcp_listener_2 = {}, tcp_listener_3 = {};
421 	struct spdk_nvme_transport_id rdma_trid_1 = {}, rdma_trid_2 = {}, rdma_trid_3 = {}, rdma_trid_4 = {},
422 	tcp_trid_1 = {}, tcp_trid_2 = {}, tcp_trid_3 = {}, tcp_trid_4 = {};
423 	struct spdk_nvmf_referral ref1 = {}, ref2 = {};
424 
425 	iov.iov_base = buffer;
426 	iov.iov_len = 8192;
427 
428 	tgt.max_subsystems = 4;
429 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
430 	RB_INIT(&tgt.subsystems);
431 
432 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
433 					       SPDK_NVMF_SUBTYPE_NVME, 0);
434 	subsystem->allow_any_host = true;
435 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
436 
437 	TAILQ_INIT(&tgt.referrals);
438 
439 	test_gen_trid(&rdma_trid_1, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4420");
440 	test_gen_trid(&rdma_trid_2, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4420");
441 	test_gen_trid(&rdma_trid_3, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4421");
442 	test_gen_trid(&rdma_trid_4, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4430");
443 	test_gen_trid(&tcp_trid_1, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4421");
444 	test_gen_trid(&tcp_trid_2, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4422");
445 	test_gen_trid(&tcp_trid_3, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4422");
446 	test_gen_trid(&tcp_trid_4, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4430");
447 
448 	rdma_listener_1.trid = rdma_trid_1;
449 	rdma_listener_2.trid = rdma_trid_2;
450 	rdma_listener_3.trid = rdma_trid_3;
451 	TAILQ_INIT(&rdma_tr.listeners);
452 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_1, link);
453 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_2, link);
454 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_3, link);
455 
456 	tcp_listener_1.trid = tcp_trid_1;
457 	tcp_listener_2.trid = tcp_trid_2;
458 	tcp_listener_3.trid = tcp_trid_3;
459 	TAILQ_INIT(&tcp_tr.listeners);
460 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_1, link);
461 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_2, link);
462 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_3, link);
463 
464 	MOCK_SET(spdk_nvmf_tgt_get_transport, &rdma_tr);
465 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_1, _subsystem_add_listen_done, NULL);
466 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_2, _subsystem_add_listen_done, NULL);
467 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_3, _subsystem_add_listen_done, NULL);
468 	MOCK_SET(spdk_nvmf_tgt_get_transport, &tcp_tr);
469 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_1, _subsystem_add_listen_done, NULL);
470 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_2, _subsystem_add_listen_done, NULL);
471 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_3, _subsystem_add_listen_done, NULL);
472 	MOCK_CLEAR(spdk_nvmf_tgt_get_transport);
473 
474 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
475 
476 	ref1.trid = rdma_trid_4;
477 
478 	ref1.entry.trtype = rdma_trid_4.trtype;
479 	ref1.entry.adrfam = rdma_trid_4.adrfam;
480 	ref1.entry.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
481 	ref1.entry.treq.secure_channel = SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED;
482 	ref1.entry.cntlid = 0xffff;
483 	memcpy(ref1.entry.trsvcid, rdma_trid_4.trsvcid, sizeof(ref1.entry.trsvcid));
484 	memcpy(ref1.entry.traddr, rdma_trid_4.traddr, sizeof(ref1.entry.traddr));
485 	snprintf(ref1.entry.subnqn, sizeof(ref1.entry.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
486 
487 	ref2.trid = tcp_trid_4;
488 
489 	ref2.entry.trtype = tcp_trid_4.trtype;
490 	ref2.entry.adrfam = tcp_trid_4.adrfam;
491 	ref2.entry.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
492 	ref2.entry.treq.secure_channel = SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED;
493 	ref2.entry.cntlid = 0xffff;
494 	memcpy(ref2.entry.trsvcid, tcp_trid_4.trsvcid, sizeof(ref2.entry.trsvcid));
495 	memcpy(ref2.entry.traddr, tcp_trid_4.traddr, sizeof(ref2.entry.traddr));
496 	snprintf(ref2.entry.subnqn, sizeof(ref2.entry.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
497 
498 	TAILQ_INSERT_HEAD(&tgt.referrals, &ref1, link);
499 	TAILQ_INSERT_HEAD(&tgt.referrals, &ref2, link);
500 
501 	spdk_nvmf_send_discovery_log_notice(&tgt, NULL);
502 
503 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
504 	memset(buffer, 0, sizeof(buffer));
505 
506 	/* Test case 1 - check that all trids are reported */
507 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
508 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
509 	CU_ASSERT(disc_log->numrec == 8);
510 
511 	/* Test case 2 - check that only entries of the same transport type are returned */
512 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
513 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
514 	CU_ASSERT(disc_log->numrec == 5);
515 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
516 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
517 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_1.trtype);
518 	CU_ASSERT(disc_log->entries[3].trtype == tcp_trid_4.trtype);
519 	CU_ASSERT(disc_log->entries[4].trtype == rdma_trid_4.trtype);
520 
521 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
522 	CU_ASSERT(disc_log->numrec == 5);
523 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
524 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
525 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_1.trtype);
526 	CU_ASSERT(disc_log->entries[3].trtype == tcp_trid_1.trtype);
527 	CU_ASSERT(disc_log->entries[4].trtype == rdma_trid_4.trtype);
528 
529 	/* Test case 3 - check that only entries of the same transport address are returned */
530 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
531 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
532 	CU_ASSERT(disc_log->numrec == 5);
533 	/* 1 tcp and 3 rdma  */
534 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
535 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
536 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_1.traddr) == 0);
537 	CU_ASSERT(strcasecmp(disc_log->entries[3].traddr, tcp_trid_4.traddr) == 0);
538 	CU_ASSERT(strcasecmp(disc_log->entries[4].traddr, rdma_trid_4.traddr) == 0);
539 
540 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
541 	CU_ASSERT(disc_log->numrec == 5);
542 	/* 1 rdma and 3 tcp */
543 	CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
544 		  != 0);
545 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
546 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
547 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_1.traddr) == 0);
548 	CU_ASSERT(strcasecmp(disc_log->entries[3].traddr, tcp_trid_1.traddr) == 0);
549 	CU_ASSERT(strcasecmp(disc_log->entries[4].traddr, rdma_trid_4.traddr) == 0);
550 
551 	/* Test case 4 - check that only entries of the same transport address and type returned */
552 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
553 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
554 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
555 	CU_ASSERT(disc_log->numrec == 4);
556 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
557 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
558 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_4.traddr) == 0);
559 	CU_ASSERT(strcasecmp(disc_log->entries[3].traddr, rdma_trid_4.traddr) == 0);
560 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
561 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
562 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_4.trtype);
563 	CU_ASSERT(disc_log->entries[3].trtype == rdma_trid_4.trtype);
564 
565 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
566 	CU_ASSERT(disc_log->numrec == 3);
567 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
568 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
569 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
570 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
571 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
572 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
573 
574 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
575 	CU_ASSERT(disc_log->numrec == 4);
576 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
577 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
578 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_4.traddr) == 0);
579 	CU_ASSERT(strcasecmp(disc_log->entries[3].traddr, rdma_trid_4.traddr) == 0);
580 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
581 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
582 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_4.trtype);
583 	CU_ASSERT(disc_log->entries[3].trtype == rdma_trid_4.trtype);
584 
585 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
586 	CU_ASSERT(disc_log->numrec == 3);
587 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
588 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
589 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
590 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
591 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
592 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
593 
594 	/* Test case 5 - check that only entries of the same transport address and type returned */
595 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
596 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
597 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
598 	CU_ASSERT(disc_log->numrec == 4);
599 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
600 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, rdma_trid_2.trsvcid) == 0);
601 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, tcp_trid_4.trsvcid) == 0);
602 	CU_ASSERT(strcasecmp(disc_log->entries[3].trsvcid, rdma_trid_4.trsvcid) == 0);
603 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
604 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_2.trtype);
605 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_4.trtype);
606 	CU_ASSERT(disc_log->entries[3].trtype == rdma_trid_4.trtype);
607 
608 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
609 	CU_ASSERT(disc_log->numrec == 3);
610 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
611 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
612 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
613 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
614 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
615 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
616 
617 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
618 	CU_ASSERT(disc_log->numrec == 3);
619 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
620 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
621 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
622 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
623 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
624 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
625 
626 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
627 	CU_ASSERT(disc_log->numrec == 4);
628 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
629 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_2.trsvcid) == 0);
630 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, tcp_trid_4.trsvcid) == 0);
631 	CU_ASSERT(strcasecmp(disc_log->entries[3].trsvcid, rdma_trid_4.trsvcid) == 0);
632 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
633 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_2.trtype);
634 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_4.trtype);
635 	CU_ASSERT(disc_log->entries[3].trtype == rdma_trid_4.trtype);
636 
637 	/* Test case 6 - check that only entries of the same transport address and type returned.
638 	 * That also implies trtype since RDMA and TCP listeners can't occupy the same socket */
639 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
640 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
641 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
642 	CU_ASSERT(disc_log->numrec == 3);
643 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
644 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
645 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
646 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
647 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
648 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
649 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
650 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
651 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
652 
653 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
654 	CU_ASSERT(disc_log->numrec == 3);
655 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
656 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
657 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
658 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
659 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
660 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
661 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
662 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
663 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
664 
665 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
666 	CU_ASSERT(disc_log->numrec == 3);
667 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
668 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
669 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
670 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
671 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
672 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
673 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
674 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
675 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
676 
677 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
678 	CU_ASSERT(disc_log->numrec == 3);
679 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
680 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
681 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
682 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
683 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
684 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
685 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
686 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
687 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
688 
689 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
690 	CU_ASSERT(disc_log->numrec == 3);
691 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
692 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
693 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
694 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
695 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
696 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
697 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
698 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
699 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
700 
701 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
702 	CU_ASSERT(disc_log->numrec == 3);
703 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
704 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
705 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
706 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
707 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
708 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
709 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
710 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
711 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
712 
713 	/* Test case 7 - check that only entries of the same transport address, svcid and type returned */
714 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
715 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
716 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
717 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
718 	CU_ASSERT(disc_log->numrec == 3);
719 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
720 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
721 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
722 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
723 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
724 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
725 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
726 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
727 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
728 
729 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
730 	CU_ASSERT(disc_log->numrec == 3);
731 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
732 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
733 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
734 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
735 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
736 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
737 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
738 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
739 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
740 
741 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
742 	CU_ASSERT(disc_log->numrec == 3);
743 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
744 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
745 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
746 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
747 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
748 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
749 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
750 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
751 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
752 
753 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
754 	CU_ASSERT(disc_log->numrec == 3);
755 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
756 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
757 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
758 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
759 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
760 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
761 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
762 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
763 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
764 
765 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
766 	CU_ASSERT(disc_log->numrec == 3);
767 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
768 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
769 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
770 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
771 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
772 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
773 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
774 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
775 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
776 
777 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
778 	CU_ASSERT(disc_log->numrec == 3);
779 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
780 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_4.traddr) == 0);
781 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_4.traddr) == 0);
782 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
783 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_4.trsvcid) == 0);
784 	CU_ASSERT(strcasecmp(disc_log->entries[2].trsvcid, rdma_trid_4.trsvcid) == 0);
785 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
786 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_4.trtype);
787 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_4.trtype);
788 
789 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
790 	spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
791 	spdk_bit_array_free(&tgt.subsystem_ids);
792 }
793 
794 int
795 main(int argc, char **argv)
796 {
797 	CU_pSuite	suite = NULL;
798 	unsigned int	num_failures;
799 
800 	CU_initialize_registry();
801 
802 	suite = CU_add_suite("nvmf", NULL, NULL);
803 
804 	CU_ADD_TEST(suite, test_discovery_log);
805 	CU_ADD_TEST(suite, test_discovery_log_with_filters);
806 
807 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
808 	CU_cleanup_registry();
809 	return num_failures;
810 }
811