xref: /spdk/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c (revision ad2dc6c532f1cbddd79d3915b74d28e0a3f99b71)
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 
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 int
154 spdk_nvmf_transport_create_async(const char *transport_name,
155 				 struct spdk_nvmf_transport_opts *tprt_opts,
156 				 spdk_nvmf_transport_create_done_cb cb_fn, void *cb_arg)
157 {
158 	if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) {
159 		cb_fn(cb_arg, &g_transport);
160 		return 0;
161 	}
162 
163 	return -1;
164 }
165 
166 struct spdk_nvmf_subsystem *
167 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
168 {
169 	return NULL;
170 }
171 
172 DEFINE_RETURN_MOCK(spdk_nvmf_tgt_get_transport, struct spdk_nvmf_transport *);
173 struct spdk_nvmf_transport *
174 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
175 {
176 	HANDLE_RETURN_MOCK(spdk_nvmf_tgt_get_transport);
177 	return &g_transport;
178 }
179 
180 int
181 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
182 {
183 	if (trtype == NULL || str == NULL) {
184 		return -EINVAL;
185 	}
186 
187 	if (strcasecmp(str, "PCIe") == 0) {
188 		*trtype = SPDK_NVME_TRANSPORT_PCIE;
189 	} else if (strcasecmp(str, "RDMA") == 0) {
190 		*trtype = SPDK_NVME_TRANSPORT_RDMA;
191 	} else {
192 		return -ENOENT;
193 	}
194 	return 0;
195 }
196 
197 void
198 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
199 {
200 }
201 
202 void
203 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr)
204 {
205 }
206 
207 int
208 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group,
209 				 struct spdk_nvmf_subsystem *subsystem)
210 {
211 	return 0;
212 }
213 
214 int
215 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group,
216 			      struct spdk_nvmf_subsystem *subsystem,
217 			      spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
218 {
219 	return 0;
220 }
221 
222 void
223 nvmf_poll_group_remove_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 }
228 
229 void
230 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group,
231 				struct spdk_nvmf_subsystem *subsystem,
232 				uint32_t nsid,
233 				spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
234 {
235 }
236 
237 void
238 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
239 				 struct spdk_nvmf_subsystem *subsystem,
240 				 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg)
241 {
242 }
243 
244 static void
245 _subsystem_add_listen_done(void *cb_arg, int status)
246 {
247 	SPDK_CU_ASSERT_FATAL(status == 0);
248 }
249 
250 static void
251 test_gen_trid(struct spdk_nvme_transport_id *trid, enum spdk_nvme_transport_type trtype,
252 	      enum spdk_nvmf_adrfam adrfam, const char *tradd, const char *trsvcid)
253 {
254 	snprintf(trid->traddr, sizeof(trid->traddr), "%s", tradd);
255 	snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", trsvcid);
256 	trid->adrfam = adrfam;
257 	trid->trtype = trtype;
258 	switch (trtype) {
259 	case SPDK_NVME_TRANSPORT_RDMA:
260 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_RDMA);
261 		break;
262 	case SPDK_NVME_TRANSPORT_TCP:
263 		snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_TCP);
264 		break;
265 	default:
266 		SPDK_CU_ASSERT_FATAL(0 && "not supported by test");
267 	}
268 }
269 
270 static void
271 test_discovery_log(void)
272 {
273 	struct spdk_nvmf_tgt tgt = {};
274 	struct spdk_nvmf_subsystem *subsystem;
275 	uint8_t buffer[8192];
276 	struct iovec iov;
277 	struct spdk_nvmf_discovery_log_page *disc_log;
278 	struct spdk_nvmf_discovery_log_page_entry *entry;
279 	struct spdk_nvme_transport_id trid = {};
280 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
281 	int rc;
282 
283 	iov.iov_base = buffer;
284 	iov.iov_len = 8192;
285 
286 	tgt.max_subsystems = 1024;
287 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
288 	RB_INIT(&tgt.subsystems);
289 
290 	/* Add one subsystem and verify that the discovery log contains it */
291 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
292 					       SPDK_NVMF_SUBTYPE_NVME, 0);
293 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
294 
295 	rc = spdk_nvmf_subsystem_add_host(subsystem, hostnqn, NULL);
296 	CU_ASSERT(rc == 0);
297 
298 	/* Get only genctr (first field in the header) */
299 	memset(buffer, 0xCC, sizeof(buffer));
300 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
301 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
302 				    &trid);
303 	/* No listeners yet on new subsystem, so genctr should still be 0. */
304 	CU_ASSERT(disc_log->genctr == 0);
305 
306 	test_gen_trid(&trid, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "1234", "5678");
307 	spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL);
308 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
309 
310 	/* Get only genctr (first field in the header) */
311 	memset(buffer, 0xCC, sizeof(buffer));
312 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
313 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(disc_log->genctr),
314 				    &trid);
315 	CU_ASSERT(disc_log->genctr == 1); /* one added subsystem and listener */
316 
317 	/* Get only the header, no entries */
318 	memset(buffer, 0xCC, sizeof(buffer));
319 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
320 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
321 				    &trid);
322 	CU_ASSERT(disc_log->genctr == 1);
323 	CU_ASSERT(disc_log->numrec == 1);
324 
325 	/* Offset 0, exact size match */
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,
329 				    sizeof(*disc_log) + sizeof(disc_log->entries[0]), &trid);
330 	CU_ASSERT(disc_log->genctr != 0);
331 	CU_ASSERT(disc_log->numrec == 1);
332 	CU_ASSERT(disc_log->entries[0].trtype == 42);
333 
334 	/* Offset 0, oversize buffer */
335 	memset(buffer, 0xCC, sizeof(buffer));
336 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
337 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(buffer), &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 	CU_ASSERT(spdk_mem_all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]),
342 				    sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0]))));
343 
344 	/* Get just the first entry, no header */
345 	memset(buffer, 0xCC, sizeof(buffer));
346 	entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
347 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1,
348 				    offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), sizeof(*entry), &trid);
349 	CU_ASSERT(entry->trtype == 42);
350 
351 	/* remove the host and verify that the discovery log contains nothing */
352 	rc = spdk_nvmf_subsystem_remove_host(subsystem, hostnqn);
353 	CU_ASSERT(rc == 0);
354 
355 	/* Get only the header, no entries */
356 	memset(buffer, 0xCC, sizeof(buffer));
357 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
358 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
359 				    &trid);
360 	CU_ASSERT(disc_log->genctr != 0);
361 	CU_ASSERT(disc_log->numrec == 0);
362 
363 	/* destroy the subsystem and verify that the discovery log contains nothing */
364 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
365 	rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
366 	CU_ASSERT(rc == 0);
367 
368 	/* Get only the header, no entries */
369 	memset(buffer, 0xCC, sizeof(buffer));
370 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
371 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, sizeof(*disc_log),
372 				    &trid);
373 	CU_ASSERT(disc_log->genctr != 0);
374 	CU_ASSERT(disc_log->numrec == 0);
375 
376 	spdk_bit_array_free(&tgt.subsystem_ids);
377 }
378 
379 static void
380 test_rdma_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
381 		   struct spdk_nvmf_discovery_log_page_entry *entry)
382 {
383 	entry->trtype = SPDK_NVMF_TRTYPE_RDMA;
384 	entry->adrfam = trid->adrfam;
385 	memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
386 	memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
387 }
388 
389 static void
390 test_tcp_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
391 		  struct spdk_nvmf_discovery_log_page_entry *entry)
392 {
393 	entry->trtype = SPDK_NVMF_TRTYPE_TCP;
394 	entry->adrfam = trid->adrfam;
395 	memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
396 	memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
397 }
398 
399 static void
400 test_discovery_log_with_filters(void)
401 {
402 	struct spdk_nvmf_tgt tgt = {};
403 	struct spdk_nvmf_transport_ops rdma_tr_ops = { .listener_discover = test_rdma_discover }, tcp_tr_ops
404 		= { .listener_discover = test_tcp_discover };
405 	struct spdk_nvmf_transport rdma_tr = {.ops = &rdma_tr_ops }, tcp_tr = { .ops = &tcp_tr_ops };
406 	struct spdk_nvmf_subsystem *subsystem;
407 	const char *hostnqn = "nqn.2016-06.io.spdk:host1";
408 	uint8_t buffer[8192];
409 	struct iovec iov;
410 	struct spdk_nvmf_discovery_log_page *disc_log;
411 	struct spdk_nvmf_listener rdma_listener_1 = {}, rdma_listener_2 = {}, rdma_listener_3 = {},
412 	tcp_listener_1 = {}, tcp_listener_2 = {}, tcp_listener_3 = {};
413 	struct spdk_nvme_transport_id rdma_trid_1 = {}, rdma_trid_2 = {}, rdma_trid_3 = {}, tcp_trid_1 = {},
414 	tcp_trid_2 = {}, tcp_trid_3 = {};
415 
416 	iov.iov_base = buffer;
417 	iov.iov_len = 8192;
418 
419 	tgt.max_subsystems = 4;
420 	tgt.subsystem_ids = spdk_bit_array_create(tgt.max_subsystems);
421 	RB_INIT(&tgt.subsystems);
422 
423 	subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
424 					       SPDK_NVMF_SUBTYPE_NVME, 0);
425 	subsystem->flags.allow_any_host = true;
426 	SPDK_CU_ASSERT_FATAL(subsystem != NULL);
427 
428 	test_gen_trid(&rdma_trid_1, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4420");
429 	test_gen_trid(&rdma_trid_2, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4420");
430 	test_gen_trid(&rdma_trid_3, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4421");
431 	test_gen_trid(&tcp_trid_1, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4421");
432 	test_gen_trid(&tcp_trid_2, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4422");
433 	test_gen_trid(&tcp_trid_3, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4422");
434 
435 	rdma_listener_1.trid = rdma_trid_1;
436 	rdma_listener_2.trid = rdma_trid_2;
437 	rdma_listener_3.trid = rdma_trid_3;
438 	TAILQ_INIT(&rdma_tr.listeners);
439 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_1, link);
440 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_2, link);
441 	TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_3, link);
442 
443 	tcp_listener_1.trid = tcp_trid_1;
444 	tcp_listener_2.trid = tcp_trid_2;
445 	tcp_listener_3.trid = tcp_trid_3;
446 	TAILQ_INIT(&tcp_tr.listeners);
447 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_1, link);
448 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_2, link);
449 	TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_3, link);
450 
451 	MOCK_SET(spdk_nvmf_tgt_get_transport, &rdma_tr);
452 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_1, _subsystem_add_listen_done, NULL);
453 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_2, _subsystem_add_listen_done, NULL);
454 	spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_3, _subsystem_add_listen_done, NULL);
455 	MOCK_SET(spdk_nvmf_tgt_get_transport, &tcp_tr);
456 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_1, _subsystem_add_listen_done, NULL);
457 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_2, _subsystem_add_listen_done, NULL);
458 	spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_3, _subsystem_add_listen_done, NULL);
459 	MOCK_CLEAR(spdk_nvmf_tgt_get_transport);
460 
461 	subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
462 
463 	disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
464 	memset(buffer, 0, sizeof(buffer));
465 
466 	/* Test case 1 - check that all trids are reported */
467 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
468 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
469 	CU_ASSERT(disc_log->numrec == 6);
470 
471 	/* Test case 2 - check that only entries of the same transport type are returned */
472 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
473 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
474 	CU_ASSERT(disc_log->numrec == 3);
475 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
476 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
477 	CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_1.trtype);
478 
479 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
480 	CU_ASSERT(disc_log->numrec == 3);
481 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
482 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
483 	CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_1.trtype);
484 
485 	/* Test case 3 - check that only entries of the same transport address are returned */
486 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
487 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
488 	CU_ASSERT(disc_log->numrec == 3);
489 	/* one tcp and 2 rdma  */
490 	CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
491 		  != 0);
492 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
493 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
494 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_1.traddr) == 0);
495 
496 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
497 	CU_ASSERT(disc_log->numrec == 3);
498 	/* one rdma and two tcp */
499 	CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
500 		  != 0);
501 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
502 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
503 	CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_1.traddr) == 0);
504 
505 	/* Test case 4 - check that only entries of the same transport address and type returned */
506 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
507 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
508 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
509 	CU_ASSERT(disc_log->numrec == 2);
510 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
511 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
512 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
513 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
514 
515 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
516 	CU_ASSERT(disc_log->numrec == 1);
517 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
518 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
519 
520 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
521 	CU_ASSERT(disc_log->numrec == 2);
522 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
523 	CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
524 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
525 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
526 
527 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
528 	CU_ASSERT(disc_log->numrec == 1);
529 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
530 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
531 
532 	/* Test case 5 - check that only entries of the same transport address and type returned */
533 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
534 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
535 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
536 	CU_ASSERT(disc_log->numrec == 2);
537 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
538 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, rdma_trid_2.trsvcid) == 0);
539 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
540 	CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_2.trtype);
541 
542 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
543 	CU_ASSERT(disc_log->numrec == 1);
544 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
545 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
546 
547 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
548 	CU_ASSERT(disc_log->numrec == 1);
549 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
550 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
551 
552 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
553 	CU_ASSERT(disc_log->numrec == 2);
554 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
555 	CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_2.trsvcid) == 0);
556 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
557 	CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_2.trtype);
558 
559 	/* Test case 6 - check that only entries of the same transport address and type returned.
560 	 * That also implies trtype since RDMA and TCP listeners can't occupy the same socket */
561 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
562 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
563 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
564 	CU_ASSERT(disc_log->numrec == 1);
565 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
566 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
567 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
568 
569 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
570 	CU_ASSERT(disc_log->numrec == 1);
571 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
572 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
573 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
574 
575 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
576 	CU_ASSERT(disc_log->numrec == 1);
577 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
578 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
579 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
580 
581 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
582 	CU_ASSERT(disc_log->numrec == 1);
583 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
584 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
585 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
586 
587 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
588 	CU_ASSERT(disc_log->numrec == 1);
589 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
590 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
591 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
592 
593 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
594 	CU_ASSERT(disc_log->numrec == 1);
595 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
596 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
597 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
598 
599 	/* Test case 7 - check that only entries of the same transport address, svcid and type returned */
600 	tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
601 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
602 			       SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
603 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_1);
604 	CU_ASSERT(disc_log->numrec == 1);
605 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
606 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
607 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
608 
609 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_2);
610 	CU_ASSERT(disc_log->numrec == 1);
611 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
612 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
613 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
614 
615 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &rdma_trid_3);
616 	CU_ASSERT(disc_log->numrec == 1);
617 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
618 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
619 	CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
620 
621 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_1);
622 	CU_ASSERT(disc_log->numrec == 1);
623 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
624 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
625 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
626 
627 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_2);
628 	CU_ASSERT(disc_log->numrec == 1);
629 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
630 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
631 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
632 
633 	nvmf_get_discovery_log_page(&tgt, hostnqn, &iov, 1, 0, 8192, &tcp_trid_3);
634 	CU_ASSERT(disc_log->numrec == 1);
635 	CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
636 	CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
637 	CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
638 
639 	subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
640 	spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
641 	spdk_bit_array_free(&tgt.subsystem_ids);
642 }
643 
644 int
645 main(int argc, char **argv)
646 {
647 	CU_pSuite	suite = NULL;
648 	unsigned int	num_failures;
649 
650 	CU_initialize_registry();
651 
652 	suite = CU_add_suite("nvmf", NULL, NULL);
653 
654 	CU_ADD_TEST(suite, test_discovery_log);
655 	CU_ADD_TEST(suite, test_discovery_log_with_filters);
656 
657 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
658 	CU_cleanup_registry();
659 	return num_failures;
660 }
661