1 /* 2 * BSD LICENSE 3 * 4 * Copyright (c) 2018-2019 Broadcom. All Rights Reserved. 5 * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* NVMF FC LS Command Processor Unit Test */ 35 36 #include "spdk/env.h" 37 #include "spdk_cunit.h" 38 #include "spdk/nvmf.h" 39 #include "spdk_internal/event.h" 40 #include "spdk/endian.h" 41 #include "spdk/trace.h" 42 #include "spdk_internal/log.h" 43 44 #include "ut_multithread.c" 45 46 #include "transport.h" 47 #include "nvmf_internal.h" 48 #include "nvmf_fc.h" 49 50 #include "fc_ls.c" 51 52 #define LAST_RSLT_STOP_TEST 999 53 54 void spdk_set_thread(struct spdk_thread *thread); 55 56 /* 57 * SPDK Stuff 58 */ 59 60 DEFINE_STUB(spdk_nvmf_request_complete, int, (struct spdk_nvmf_request *req), -ENOSPC); 61 DEFINE_STUB(spdk_nvmf_subsystem_host_allowed, bool, 62 (struct spdk_nvmf_subsystem *subsystem, const char *hostnqn), true); 63 DEFINE_STUB_V(spdk_nvme_trid_populate_transport, (struct spdk_nvme_transport_id *trid, 64 enum spdk_nvme_transport_type trtype)); 65 66 static const char *fc_ut_subsystem_nqn = 67 "nqn.2017-11.io.spdk:sn.390c0dc7c87011e786b300a0989adc53:subsystem.good"; 68 static struct spdk_nvmf_host fc_ut_initiator = { 69 .nqn = "nqn.2017-11.fc_host", 70 }; 71 static struct spdk_nvmf_host *fc_ut_host = &fc_ut_initiator; 72 static struct spdk_nvmf_tgt g_nvmf_tgt; 73 static struct spdk_nvmf_transport_opts g_nvmf_transport_opts = { 74 .max_queue_depth = 128, 75 .max_qpairs_per_ctrlr = 4, 76 .max_aq_depth = 32, 77 }; 78 static uint32_t g_hw_queue_depth = 1024; 79 static struct spdk_nvmf_subsystem g_nvmf_subsystem; 80 81 82 int spdk_nvmf_fc_xmt_ls_rsp(struct spdk_nvmf_fc_nport *g_tgt_port, 83 struct spdk_nvmf_fc_ls_rqst *ls_rqst); 84 void spdk_nvmf_fc_request_abort(struct spdk_nvmf_fc_request *fc_req, bool send_abts, 85 spdk_nvmf_fc_caller_cb cb, void *cb_args); 86 void spdk_bdev_io_abort(struct spdk_bdev_io *bdev_io, void *ctx); 87 void spdk_nvmf_fc_request_abort_complete(void *arg1); 88 bool spdk_nvmf_fc_req_in_xfer(struct spdk_nvmf_fc_request *fc_req); 89 90 struct spdk_nvmf_subsystem * 91 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 92 { 93 if (!strcmp(subnqn, g_nvmf_subsystem.subnqn)) { 94 return &g_nvmf_subsystem; 95 } 96 return NULL; 97 } 98 99 int 100 spdk_nvmf_poll_group_add(struct spdk_nvmf_poll_group *group, 101 struct spdk_nvmf_qpair *qpair) 102 { 103 qpair->state = SPDK_NVMF_QPAIR_ACTIVE; 104 return 0; 105 } 106 107 const struct spdk_nvmf_transport_ops spdk_nvmf_transport_fc = { 108 .type = (enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC, 109 .create = NULL, 110 .destroy = NULL, 111 112 .listen = NULL, 113 .stop_listen = NULL, 114 .accept = NULL, 115 116 .listener_discover = NULL, 117 118 .poll_group_create = NULL, 119 .poll_group_destroy = NULL, 120 .poll_group_add = NULL, 121 .poll_group_poll = NULL, 122 123 .req_complete = NULL, 124 125 .qpair_fini = NULL, 126 127 }; 128 129 struct spdk_nvmf_transport g_nvmf_transport = { 130 .ops = &spdk_nvmf_transport_fc, 131 .tgt = &g_nvmf_tgt, 132 }; 133 134 struct spdk_nvmf_transport * 135 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name) 136 { 137 return &g_nvmf_transport; 138 } 139 140 int 141 spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair, nvmf_qpair_disconnect_cb cb_fn, void *ctx) 142 { 143 cb_fn(ctx); 144 return 0; 145 } 146 147 static void 148 new_qpair(struct spdk_nvmf_qpair *qpair, void *cb_arg) 149 { 150 uint32_t i; 151 struct spdk_nvmf_fc_conn *fc_conn; 152 struct spdk_nvmf_fc_hwqp *hwqp = NULL, *sel_hwqp = NULL; 153 struct spdk_nvmf_fc_ls_add_conn_api_data *api_data = NULL; 154 struct spdk_nvmf_fc_port *fc_port; 155 156 fc_conn = SPDK_CONTAINEROF(qpair, struct spdk_nvmf_fc_conn, qpair); 157 api_data = &fc_conn->create_opd->u.add_conn; 158 159 /* Pick a hwqp with least load */ 160 fc_port = fc_conn->fc_assoc->tgtport->fc_port; 161 for (i = 0; i < fc_port->num_io_queues; i ++) { 162 hwqp = &fc_port->io_queues[i]; 163 if (!sel_hwqp || (hwqp->rq_size > sel_hwqp->rq_size)) { 164 sel_hwqp = hwqp; 165 } 166 } 167 168 if (!nvmf_fc_assign_conn_to_hwqp(sel_hwqp, 169 &fc_conn->conn_id, 170 fc_conn->max_queue_depth)) { 171 goto err; 172 } 173 174 fc_conn->hwqp = sel_hwqp; 175 176 /* If this is for ADMIN connection, then update assoc ID. */ 177 if (fc_conn->qpair.qid == 0) { 178 fc_conn->fc_assoc->assoc_id = fc_conn->conn_id; 179 } 180 181 spdk_nvmf_fc_poller_api_func(sel_hwqp, SPDK_NVMF_FC_POLLER_API_ADD_CONNECTION, &api_data->args); 182 183 return; 184 err: 185 nvmf_fc_ls_add_conn_failure(api_data->assoc, api_data->ls_rqst, 186 api_data->args.fc_conn, api_data->aq_conn); 187 } 188 189 struct spdk_nvmf_fc_conn * 190 spdk_nvmf_fc_hwqp_find_fc_conn(struct spdk_nvmf_fc_hwqp *hwqp, uint64_t conn_id) 191 { 192 struct spdk_nvmf_fc_conn *fc_conn; 193 194 TAILQ_FOREACH(fc_conn, &hwqp->connection_list, link) { 195 if (fc_conn->conn_id == conn_id) { 196 return fc_conn; 197 } 198 } 199 200 return NULL; 201 } 202 203 /* 204 * LLD functions 205 */ 206 207 static inline uint64_t 208 nvmf_fc_gen_conn_id(uint32_t qnum, struct spdk_nvmf_fc_hwqp *hwqp) 209 { 210 static uint16_t conn_cnt = 0; 211 return ((uint64_t) qnum | (conn_cnt++ << 8)); 212 } 213 214 bool 215 nvmf_fc_assign_conn_to_hwqp(struct spdk_nvmf_fc_hwqp *hwqp, 216 uint64_t *conn_id, uint32_t sq_size) 217 { 218 SPDK_DEBUGLOG(SPDK_LOG_NVMF_FC_LS, "Assign connection to HWQP\n"); 219 220 221 if (hwqp->rq_size < sq_size) { 222 return false; /* queue has no space for this connection */ 223 } 224 225 hwqp->rq_size -= sq_size; 226 hwqp->num_conns++; 227 228 /* create connection ID */ 229 *conn_id = nvmf_fc_gen_conn_id(hwqp->hwqp_id, hwqp); 230 231 SPDK_DEBUGLOG(SPDK_LOG_NVMF_FC_LS, 232 "New connection assigned to HWQP%d (free %d), conn_id 0x%lx\n", 233 hwqp->hwqp_id, hwqp->rq_size, *conn_id); 234 return true; 235 } 236 237 struct spdk_nvmf_fc_hwqp * 238 nvmf_fc_get_hwqp_from_conn_id(struct spdk_nvmf_fc_hwqp *queues, 239 uint32_t num_queues, uint64_t conn_id) 240 { 241 return &queues[(conn_id & 0xff) % num_queues]; 242 } 243 244 void 245 nvmf_fc_release_conn(struct spdk_nvmf_fc_hwqp *hwqp, uint64_t conn_id, 246 uint32_t sq_size) 247 { 248 hwqp->rq_size += sq_size; 249 } 250 251 struct spdk_nvmf_fc_srsr_bufs * 252 nvmf_fc_alloc_srsr_bufs(size_t rqst_len, size_t rsp_len) 253 { 254 struct spdk_nvmf_fc_srsr_bufs *srsr_bufs; 255 256 srsr_bufs = calloc(1, sizeof(struct spdk_nvmf_fc_srsr_bufs)); 257 if (!srsr_bufs) { 258 return NULL; 259 } 260 261 srsr_bufs->rqst = calloc(1, rqst_len + rsp_len); 262 if (srsr_bufs->rqst) { 263 srsr_bufs->rqst_len = rqst_len; 264 srsr_bufs->rsp = srsr_bufs->rqst + rqst_len; 265 srsr_bufs->rsp_len = rsp_len; 266 } else { 267 free(srsr_bufs); 268 srsr_bufs = NULL; 269 } 270 271 return srsr_bufs; 272 } 273 274 void 275 nvmf_fc_free_srsr_bufs(struct spdk_nvmf_fc_srsr_bufs *srsr_bufs) 276 { 277 if (srsr_bufs) { 278 free(srsr_bufs->rqst); 279 free(srsr_bufs); 280 } 281 } 282 283 int 284 nvmf_fc_xmt_ls_rsp(struct spdk_nvmf_fc_nport *tgtport, struct spdk_nvmf_fc_ls_rqst *ls_rqst) 285 { 286 return spdk_nvmf_fc_xmt_ls_rsp(tgtport, ls_rqst); 287 } 288 289 /* 290 * The Tests 291 */ 292 293 enum _test_run_type { 294 TEST_RUN_TYPE_CREATE_ASSOC = 1, 295 TEST_RUN_TYPE_CREATE_CONN, 296 TEST_RUN_TYPE_DISCONNECT, 297 TEST_RUN_TYPE_CONN_BAD_ASSOC, 298 TEST_RUN_TYPE_FAIL_LS_RSP, 299 TEST_RUN_TYPE_DISCONNECT_BAD_ASSOC, 300 TEST_RUN_TYPE_CREATE_MAX_ASSOC, 301 }; 302 303 static uint32_t g_test_run_type = 0; 304 static uint64_t g_curr_assoc_id = 0; 305 static uint16_t g_create_conn_test_cnt = 0; 306 static uint16_t g_max_assoc_conn_test = 0; 307 static int g_last_rslt = 0; 308 static bool g_spdk_nvmf_fc_xmt_srsr_req = false; 309 static struct spdk_nvmf_fc_remote_port_info g_rem_port; 310 311 static void 312 run_create_assoc_test(const char *subnqn, 313 struct spdk_nvmf_host *host, 314 struct spdk_nvmf_fc_nport *tgt_port) 315 { 316 struct spdk_nvmf_fc_ls_rqst ls_rqst; 317 struct spdk_nvmf_fc_ls_cr_assoc_rqst ca_rqst; 318 uint8_t respbuf[128]; 319 320 memset(&ca_rqst, 0, sizeof(struct spdk_nvmf_fc_ls_cr_assoc_rqst)); 321 322 ca_rqst.w0.ls_cmd = FCNVME_LS_CREATE_ASSOCIATION; 323 to_be32(&ca_rqst.desc_list_len, 324 sizeof(struct spdk_nvmf_fc_ls_cr_assoc_rqst) - 325 (2 * sizeof(uint32_t))); 326 to_be32(&ca_rqst.assoc_cmd.desc_tag, FCNVME_LSDESC_CREATE_ASSOC_CMD); 327 to_be32(&ca_rqst.assoc_cmd.desc_len, 328 sizeof(struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd) - 329 (2 * sizeof(uint32_t))); 330 to_be16(&ca_rqst.assoc_cmd.ersp_ratio, (g_nvmf_transport.opts.max_aq_depth / 2)); 331 to_be16(&ca_rqst.assoc_cmd.sqsize, g_nvmf_transport.opts.max_aq_depth - 1); 332 snprintf(&ca_rqst.assoc_cmd.subnqn[0], strlen(subnqn) + 1, "%s", subnqn); 333 snprintf(&ca_rqst.assoc_cmd.hostnqn[0], strlen(host->nqn) + 1, "%s", host->nqn); 334 ls_rqst.rqstbuf.virt = &ca_rqst; 335 ls_rqst.rspbuf.virt = respbuf; 336 ls_rqst.rqst_len = sizeof(struct spdk_nvmf_fc_ls_cr_assoc_rqst); 337 ls_rqst.rsp_len = 0; 338 ls_rqst.rpi = 5000; 339 ls_rqst.private_data = NULL; 340 ls_rqst.s_id = 0; 341 ls_rqst.nport = tgt_port; 342 ls_rqst.rport = &g_rem_port; 343 ls_rqst.nvmf_tgt = &g_nvmf_tgt; 344 345 spdk_nvmf_fc_handle_ls_rqst(&ls_rqst); 346 poll_thread(0); 347 } 348 349 static void 350 run_create_conn_test(struct spdk_nvmf_host *host, 351 struct spdk_nvmf_fc_nport *tgt_port, 352 uint64_t assoc_id, 353 uint16_t qid) 354 { 355 struct spdk_nvmf_fc_ls_rqst ls_rqst; 356 struct spdk_nvmf_fc_ls_cr_conn_rqst cc_rqst; 357 uint8_t respbuf[128]; 358 359 memset(&cc_rqst, 0, sizeof(struct spdk_nvmf_fc_ls_cr_conn_rqst)); 360 361 /* fill in request descriptor */ 362 cc_rqst.w0.ls_cmd = FCNVME_LS_CREATE_CONNECTION; 363 to_be32(&cc_rqst.desc_list_len, 364 sizeof(struct spdk_nvmf_fc_ls_cr_conn_rqst) - 365 (2 * sizeof(uint32_t))); 366 367 /* fill in connect command descriptor */ 368 to_be32(&cc_rqst.connect_cmd.desc_tag, FCNVME_LSDESC_CREATE_CONN_CMD); 369 to_be32(&cc_rqst.connect_cmd.desc_len, 370 sizeof(struct spdk_nvmf_fc_lsdesc_cr_conn_cmd) - 371 (2 * sizeof(uint32_t))); 372 373 to_be16(&cc_rqst.connect_cmd.ersp_ratio, (g_nvmf_transport.opts.max_queue_depth / 2)); 374 to_be16(&cc_rqst.connect_cmd.sqsize, g_nvmf_transport.opts.max_queue_depth - 1); 375 to_be16(&cc_rqst.connect_cmd.qid, qid); 376 377 /* fill in association id descriptor */ 378 to_be32(&cc_rqst.assoc_id.desc_tag, FCNVME_LSDESC_ASSOC_ID), 379 to_be32(&cc_rqst.assoc_id.desc_len, 380 sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) - 381 (2 * sizeof(uint32_t))); 382 cc_rqst.assoc_id.association_id = assoc_id; /* alreday be64 */ 383 384 ls_rqst.rqstbuf.virt = &cc_rqst; 385 ls_rqst.rspbuf.virt = respbuf; 386 ls_rqst.rqst_len = sizeof(struct spdk_nvmf_fc_ls_cr_conn_rqst); 387 ls_rqst.rsp_len = 0; 388 ls_rqst.rpi = 5000; 389 ls_rqst.private_data = NULL; 390 ls_rqst.s_id = 0; 391 ls_rqst.nport = tgt_port; 392 ls_rqst.rport = &g_rem_port; 393 ls_rqst.nvmf_tgt = &g_nvmf_tgt; 394 395 spdk_nvmf_fc_handle_ls_rqst(&ls_rqst); 396 poll_thread(0); 397 } 398 399 static void 400 run_disconn_test(struct spdk_nvmf_fc_nport *tgt_port, 401 uint64_t assoc_id) 402 { 403 struct spdk_nvmf_fc_ls_rqst ls_rqst; 404 struct spdk_nvmf_fc_ls_disconnect_rqst dc_rqst; 405 uint8_t respbuf[128]; 406 407 memset(&dc_rqst, 0, sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst)); 408 409 /* fill in request descriptor */ 410 dc_rqst.w0.ls_cmd = FCNVME_LS_DISCONNECT; 411 to_be32(&dc_rqst.desc_list_len, 412 sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst) - 413 (2 * sizeof(uint32_t))); 414 415 /* fill in disconnect command descriptor */ 416 to_be32(&dc_rqst.disconn_cmd.desc_tag, FCNVME_LSDESC_DISCONN_CMD); 417 to_be32(&dc_rqst.disconn_cmd.desc_len, 418 sizeof(struct spdk_nvmf_fc_lsdesc_disconn_cmd) - 419 (2 * sizeof(uint32_t))); 420 421 /* fill in association id descriptor */ 422 to_be32(&dc_rqst.assoc_id.desc_tag, FCNVME_LSDESC_ASSOC_ID), 423 to_be32(&dc_rqst.assoc_id.desc_len, 424 sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) - 425 (2 * sizeof(uint32_t))); 426 dc_rqst.assoc_id.association_id = assoc_id; /* alreday be64 */ 427 428 ls_rqst.rqstbuf.virt = &dc_rqst; 429 ls_rqst.rspbuf.virt = respbuf; 430 ls_rqst.rqst_len = sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst); 431 ls_rqst.rsp_len = 0; 432 ls_rqst.rpi = 5000; 433 ls_rqst.private_data = NULL; 434 ls_rqst.s_id = 0; 435 ls_rqst.nport = tgt_port; 436 ls_rqst.rport = &g_rem_port; 437 ls_rqst.nvmf_tgt = &g_nvmf_tgt; 438 439 spdk_nvmf_fc_handle_ls_rqst(&ls_rqst); 440 poll_thread(0); 441 } 442 443 static void 444 disconnect_assoc_cb(void *cb_data, uint32_t err) 445 { 446 CU_ASSERT(err == 0); 447 } 448 449 static int 450 handle_ca_rsp(struct spdk_nvmf_fc_ls_rqst *ls_rqst, bool max_assoc_test) 451 { 452 struct spdk_nvmf_fc_ls_acc_hdr *acc_hdr = 453 (struct spdk_nvmf_fc_ls_acc_hdr *) ls_rqst->rspbuf.virt; 454 455 456 if (acc_hdr->rqst.w0.ls_cmd == FCNVME_LS_CREATE_ASSOCIATION) { 457 if (acc_hdr->w0.ls_cmd == FCNVME_LS_ACC) { 458 struct spdk_nvmf_fc_ls_cr_assoc_acc *acc = 459 (struct spdk_nvmf_fc_ls_cr_assoc_acc *)ls_rqst->rspbuf.virt; 460 461 CU_ASSERT(from_be32(&acc_hdr->desc_list_len) == 462 sizeof(struct spdk_nvmf_fc_ls_cr_assoc_acc) - 8); 463 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_len) == 464 sizeof(struct spdk_nvmf_fc_lsdesc_rqst) - 8); 465 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_tag) == 466 FCNVME_LSDESC_RQST); 467 CU_ASSERT(from_be32(&acc->assoc_id.desc_tag) == 468 FCNVME_LSDESC_ASSOC_ID); 469 CU_ASSERT(from_be32(&acc->assoc_id.desc_len) == 470 sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) - 8); 471 CU_ASSERT(from_be32(&acc->conn_id.desc_tag) == 472 FCNVME_LSDESC_CONN_ID); 473 CU_ASSERT(from_be32(&acc->conn_id.desc_len) == 474 sizeof(struct spdk_nvmf_fc_lsdesc_conn_id) - 8); 475 476 g_curr_assoc_id = acc->assoc_id.association_id; 477 g_create_conn_test_cnt++; 478 return 0; 479 } else if (max_assoc_test) { 480 /* reject reason code should be insufficient resources */ 481 struct spdk_nvmf_fc_ls_rjt *rjt = 482 (struct spdk_nvmf_fc_ls_rjt *)ls_rqst->rspbuf.virt; 483 if (rjt->rjt.reason_code == FCNVME_RJT_RC_INSUFF_RES) { 484 return LAST_RSLT_STOP_TEST; 485 } 486 } 487 CU_FAIL("Unexpected reject response for create association"); 488 } else { 489 CU_FAIL("Response not for create association"); 490 } 491 492 return -EINVAL; 493 } 494 495 static int 496 handle_cc_rsp(struct spdk_nvmf_fc_ls_rqst *ls_rqst) 497 { 498 struct spdk_nvmf_fc_ls_acc_hdr *acc_hdr = 499 (struct spdk_nvmf_fc_ls_acc_hdr *) ls_rqst->rspbuf.virt; 500 501 if (acc_hdr->rqst.w0.ls_cmd == FCNVME_LS_CREATE_CONNECTION) { 502 if (acc_hdr->w0.ls_cmd == FCNVME_LS_ACC) { 503 struct spdk_nvmf_fc_ls_cr_conn_acc *acc = 504 (struct spdk_nvmf_fc_ls_cr_conn_acc *)ls_rqst->rspbuf.virt; 505 506 CU_ASSERT(from_be32(&acc_hdr->desc_list_len) == 507 sizeof(struct spdk_nvmf_fc_ls_cr_conn_acc) - 8); 508 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_len) == 509 sizeof(struct spdk_nvmf_fc_lsdesc_rqst) - 8); 510 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_tag) == 511 FCNVME_LSDESC_RQST); 512 CU_ASSERT(from_be32(&acc->conn_id.desc_tag) == 513 FCNVME_LSDESC_CONN_ID); 514 CU_ASSERT(from_be32(&acc->conn_id.desc_len) == 515 sizeof(struct spdk_nvmf_fc_lsdesc_conn_id) - 8); 516 g_create_conn_test_cnt++; 517 return 0; 518 } 519 520 if (acc_hdr->w0.ls_cmd == FCNVME_LS_RJT) { 521 struct spdk_nvmf_fc_ls_rjt *rjt = 522 (struct spdk_nvmf_fc_ls_rjt *)ls_rqst->rspbuf.virt; 523 if (g_create_conn_test_cnt == g_nvmf_transport.opts.max_qpairs_per_ctrlr) { 524 /* expected to get reject for too many connections */ 525 CU_ASSERT(rjt->rjt.reason_code == 526 FCNVME_RJT_RC_INV_PARAM); 527 CU_ASSERT(rjt->rjt.reason_explanation == 528 FCNVME_RJT_EXP_INV_Q_ID); 529 } else if (!g_max_assoc_conn_test) { 530 CU_FAIL("Unexpected reject response create connection"); 531 } 532 } else { 533 CU_FAIL("Unexpected response code for create connection"); 534 } 535 } else { 536 CU_FAIL("Response not for create connection"); 537 } 538 539 return -EINVAL; 540 } 541 542 static int 543 handle_disconn_rsp(struct spdk_nvmf_fc_ls_rqst *ls_rqst) 544 { 545 struct spdk_nvmf_fc_ls_acc_hdr *acc_hdr = 546 (struct spdk_nvmf_fc_ls_acc_hdr *) ls_rqst->rspbuf.virt; 547 548 if (acc_hdr->rqst.w0.ls_cmd == FCNVME_LS_DISCONNECT) { 549 if (acc_hdr->w0.ls_cmd == FCNVME_LS_ACC) { 550 CU_ASSERT(from_be32(&acc_hdr->desc_list_len) == 551 sizeof(struct spdk_nvmf_fc_ls_disconnect_acc) - 8); 552 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_len) == 553 sizeof(struct spdk_nvmf_fc_lsdesc_rqst) - 8); 554 CU_ASSERT(from_be32(&acc_hdr->rqst.desc_tag) == 555 FCNVME_LSDESC_RQST); 556 return 0; 557 } else { 558 CU_FAIL("Unexpected reject response for disconnect"); 559 } 560 } else { 561 CU_FAIL("Response not for create connection"); 562 } 563 564 return -EINVAL; 565 } 566 567 static int 568 handle_conn_bad_assoc_rsp(struct spdk_nvmf_fc_ls_rqst *ls_rqst) 569 { 570 struct spdk_nvmf_fc_ls_acc_hdr *acc_hdr = 571 (struct spdk_nvmf_fc_ls_acc_hdr *) ls_rqst->rspbuf.virt; 572 573 if (acc_hdr->rqst.w0.ls_cmd == FCNVME_LS_CREATE_CONNECTION) { 574 if (acc_hdr->w0.ls_cmd == FCNVME_LS_RJT) { 575 struct spdk_nvmf_fc_ls_rjt *rjt = 576 (struct spdk_nvmf_fc_ls_rjt *)ls_rqst->rspbuf.virt; 577 578 CU_ASSERT(from_be32(&rjt->desc_list_len) == 579 sizeof(struct spdk_nvmf_fc_ls_rjt) - 8); 580 CU_ASSERT(from_be32(&rjt->rqst.desc_tag) == 581 FCNVME_LSDESC_RQST); 582 CU_ASSERT(from_be32(&rjt->rjt.desc_len) == 583 sizeof(struct spdk_nvmf_fc_lsdesc_rjt) - 8); 584 CU_ASSERT(from_be32(&rjt->rjt.desc_tag) == 585 FCNVME_LSDESC_RJT); 586 CU_ASSERT(rjt->rjt.reason_code == 587 FCNVME_RJT_RC_INV_ASSOC); 588 CU_ASSERT(rjt->rjt.reason_explanation == 589 FCNVME_RJT_EXP_NONE); 590 /* make sure reserved fields are 0 */ 591 CU_ASSERT(rjt->rjt.rsvd8 == 0); 592 CU_ASSERT(rjt->rjt.rsvd12 == 0); 593 return 0; 594 } else { 595 CU_FAIL("Unexpected accept response for create conn. on bad assoc_id"); 596 } 597 } else { 598 CU_FAIL("Response not for create connection on bad assoc_id"); 599 } 600 601 return -EINVAL; 602 } 603 604 static int 605 handle_disconn_bad_assoc_rsp(struct spdk_nvmf_fc_ls_rqst *ls_rqst) 606 { 607 struct spdk_nvmf_fc_ls_acc_hdr *acc_hdr = 608 (struct spdk_nvmf_fc_ls_acc_hdr *) ls_rqst->rspbuf.virt; 609 610 if (acc_hdr->rqst.w0.ls_cmd == FCNVME_LS_DISCONNECT) { 611 if (acc_hdr->w0.ls_cmd == FCNVME_LS_RJT) { 612 struct spdk_nvmf_fc_ls_rjt *rjt = 613 (struct spdk_nvmf_fc_ls_rjt *)ls_rqst->rspbuf.virt; 614 615 CU_ASSERT(from_be32(&rjt->desc_list_len) == 616 sizeof(struct spdk_nvmf_fc_ls_rjt) - 8); 617 CU_ASSERT(from_be32(&rjt->rqst.desc_tag) == 618 FCNVME_LSDESC_RQST); 619 CU_ASSERT(from_be32(&rjt->rjt.desc_len) == 620 sizeof(struct spdk_nvmf_fc_lsdesc_rjt) - 8); 621 CU_ASSERT(from_be32(&rjt->rjt.desc_tag) == 622 FCNVME_LSDESC_RJT); 623 CU_ASSERT(rjt->rjt.reason_code == 624 FCNVME_RJT_RC_INV_ASSOC); 625 CU_ASSERT(rjt->rjt.reason_explanation == 626 FCNVME_RJT_EXP_NONE); 627 return 0; 628 } else { 629 CU_FAIL("Unexpected accept response for disconnect on bad assoc_id"); 630 } 631 } else { 632 CU_FAIL("Response not for dsconnect on bad assoc_id"); 633 } 634 635 return -EINVAL; 636 } 637 638 639 static struct spdk_nvmf_fc_port g_fc_port = { 640 .num_io_queues = 16, 641 .new_qp_cb = new_qpair, 642 }; 643 644 static struct spdk_nvmf_fc_nport g_tgt_port; 645 646 static uint64_t assoc_id[1024]; 647 648 #define FC_LS_UT_MAX_IO_QUEUES 16 649 struct spdk_nvmf_fc_hwqp g_fc_hwqp[FC_LS_UT_MAX_IO_QUEUES]; 650 struct spdk_nvmf_fc_poll_group g_fgroup[FC_LS_UT_MAX_IO_QUEUES]; 651 struct spdk_nvmf_poll_group g_poll_group[FC_LS_UT_MAX_IO_QUEUES]; 652 static bool threads_allocated = false; 653 654 static void 655 ls_assign_hwqp_threads(void) 656 { 657 uint32_t i; 658 659 for (i = 0; i < g_fc_port.num_io_queues; i++) { 660 struct spdk_nvmf_fc_hwqp *hwqp = &g_fc_port.io_queues[i]; 661 if (hwqp->thread == NULL) { 662 hwqp->thread = spdk_get_thread(); 663 } 664 } 665 } 666 667 static void 668 ls_prepare_threads(void) 669 { 670 if (threads_allocated == false) { 671 allocate_threads(8); 672 set_thread(0); 673 } 674 threads_allocated = true; 675 } 676 677 static void 678 setup_polling_threads(void) 679 { 680 ls_prepare_threads(); 681 set_thread(0); 682 ls_assign_hwqp_threads(); 683 } 684 685 static int 686 ls_tests_init(void) 687 { 688 uint16_t i; 689 690 bzero(&g_nvmf_tgt, sizeof(g_nvmf_tgt)); 691 692 g_nvmf_transport.opts = g_nvmf_transport_opts; 693 694 snprintf(g_nvmf_subsystem.subnqn, sizeof(g_nvmf_subsystem.subnqn), "%s", fc_ut_subsystem_nqn); 695 g_fc_port.hw_port_status = SPDK_FC_PORT_ONLINE; 696 g_fc_port.io_queues = g_fc_hwqp; 697 for (i = 0; i < g_fc_port.num_io_queues; i++) { 698 struct spdk_nvmf_fc_hwqp *hwqp = &g_fc_port.io_queues[i]; 699 hwqp->lcore_id = i; 700 hwqp->hwqp_id = i; 701 hwqp->thread = NULL; 702 hwqp->fc_port = &g_fc_port; 703 hwqp->num_conns = 0; 704 hwqp->rq_size = g_hw_queue_depth; 705 TAILQ_INIT(&hwqp->connection_list); 706 TAILQ_INIT(&hwqp->in_use_reqs); 707 708 bzero(&g_poll_group[i], sizeof(struct spdk_nvmf_poll_group)); 709 bzero(&g_fgroup[i], sizeof(struct spdk_nvmf_fc_poll_group)); 710 TAILQ_INIT(&g_poll_group[i].tgroups); 711 TAILQ_INIT(&g_poll_group[i].qpairs); 712 g_fgroup[i].group.transport = &g_nvmf_transport; 713 g_fgroup[i].group.group = &g_poll_group[i]; 714 hwqp->fgroup = &g_fgroup[i]; 715 } 716 717 spdk_nvmf_fc_ls_init(&g_fc_port); 718 bzero(&g_tgt_port, sizeof(struct spdk_nvmf_fc_nport)); 719 g_tgt_port.fc_port = &g_fc_port; 720 TAILQ_INIT(&g_tgt_port.rem_port_list); 721 TAILQ_INIT(&g_tgt_port.fc_associations); 722 723 bzero(&g_rem_port, sizeof(struct spdk_nvmf_fc_remote_port_info)); 724 TAILQ_INSERT_TAIL(&g_tgt_port.rem_port_list, &g_rem_port, link); 725 726 return 0; 727 } 728 729 static int 730 ls_tests_fini(void) 731 { 732 spdk_nvmf_fc_ls_fini(&g_fc_port); 733 free_threads(); 734 return 0; 735 } 736 737 static void 738 create_single_assoc_test(void) 739 { 740 setup_polling_threads(); 741 /* main test driver */ 742 g_test_run_type = TEST_RUN_TYPE_CREATE_ASSOC; 743 run_create_assoc_test(fc_ut_subsystem_nqn, fc_ut_host, &g_tgt_port); 744 745 if (g_last_rslt == 0) { 746 /* disconnect the association */ 747 g_test_run_type = TEST_RUN_TYPE_DISCONNECT; 748 run_disconn_test(&g_tgt_port, g_curr_assoc_id); 749 g_create_conn_test_cnt = 0; 750 } 751 } 752 753 static void 754 create_max_conns_test(void) 755 { 756 uint16_t qid = 1; 757 758 setup_polling_threads(); 759 /* main test driver */ 760 g_test_run_type = TEST_RUN_TYPE_CREATE_ASSOC; 761 run_create_assoc_test(fc_ut_subsystem_nqn, fc_ut_host, &g_tgt_port); 762 763 if (g_last_rslt == 0) { 764 g_test_run_type = TEST_RUN_TYPE_CREATE_CONN; 765 /* create connections until we get too many connections error */ 766 while (g_last_rslt == 0) { 767 if (g_create_conn_test_cnt > g_nvmf_transport.opts.max_qpairs_per_ctrlr) { 768 CU_FAIL("Did not get CIOC failure for too many connections"); 769 break; 770 } 771 run_create_conn_test(fc_ut_host, &g_tgt_port, g_curr_assoc_id, qid++); 772 } 773 774 /* disconnect the association */ 775 g_last_rslt = 0; 776 g_test_run_type = TEST_RUN_TYPE_DISCONNECT; 777 run_disconn_test(&g_tgt_port, g_curr_assoc_id); 778 g_create_conn_test_cnt = 0; 779 } 780 } 781 782 static void 783 invalid_connection_test(void) 784 { 785 setup_polling_threads(); 786 /* run test to create connection to invalid association */ 787 g_test_run_type = TEST_RUN_TYPE_CONN_BAD_ASSOC; 788 run_create_conn_test(fc_ut_host, &g_tgt_port, g_curr_assoc_id, 1); 789 } 790 791 static void 792 create_max_aq_conns_test(void) 793 { 794 /* run test to create max. associations with max. connections */ 795 uint32_t i, j; 796 uint32_t create_assoc_test_cnt = 0; 797 798 setup_polling_threads(); 799 g_max_assoc_conn_test = 1; 800 g_last_rslt = 0; 801 while (1) { 802 g_test_run_type = TEST_RUN_TYPE_CREATE_MAX_ASSOC; 803 run_create_assoc_test(fc_ut_subsystem_nqn, fc_ut_host, &g_tgt_port); 804 if (g_last_rslt == 0) { 805 assoc_id[create_assoc_test_cnt++] = g_curr_assoc_id; 806 g_test_run_type = TEST_RUN_TYPE_CREATE_CONN; 807 for (j = 1; j < g_nvmf_transport.opts.max_qpairs_per_ctrlr; j++) { 808 if (g_last_rslt == 0) { 809 run_create_conn_test(fc_ut_host, &g_tgt_port, g_curr_assoc_id, (uint16_t) j); 810 } 811 } 812 } else { 813 break; 814 } 815 } 816 817 if (g_last_rslt == LAST_RSLT_STOP_TEST) { 818 uint32_t ma = (((g_hw_queue_depth / g_nvmf_transport.opts.max_queue_depth) * 819 (g_fc_port.num_io_queues - 1))) / 820 (g_nvmf_transport.opts.max_qpairs_per_ctrlr - 1); 821 if (create_assoc_test_cnt < ma) { 822 printf("(%d assocs - should be %d) ", create_assoc_test_cnt, ma); 823 CU_FAIL("Didn't create max. associations"); 824 } else { 825 printf("(%d assocs.) ", create_assoc_test_cnt); 826 } 827 g_last_rslt = 0; 828 } 829 830 for (i = 0; i < create_assoc_test_cnt; i++) { 831 int ret; 832 g_spdk_nvmf_fc_xmt_srsr_req = false; 833 ret = spdk_nvmf_fc_delete_association(&g_tgt_port, from_be64(&assoc_id[i]), true, false, 834 disconnect_assoc_cb, 0); 835 CU_ASSERT(ret == 0); 836 poll_thread(0); 837 838 #if (NVMF_FC_LS_SEND_LS_DISCONNECT == 1) 839 if (ret == 0) { 840 /* check that LS disconnect was sent */ 841 CU_ASSERT(g_spdk_nvmf_fc_xmt_srsr_req); 842 } 843 #endif 844 } 845 g_max_assoc_conn_test = 0; 846 } 847 848 static void 849 xmt_ls_rsp_failure_test(void) 850 { 851 setup_polling_threads(); 852 g_test_run_type = TEST_RUN_TYPE_FAIL_LS_RSP; 853 run_create_assoc_test(fc_ut_subsystem_nqn, fc_ut_host, &g_tgt_port); 854 if (g_last_rslt == 0) { 855 /* check target port for associations */ 856 CU_ASSERT(g_tgt_port.assoc_count == 0); 857 } 858 } 859 860 static void 861 disconnect_bad_assoc_test(void) 862 { 863 setup_polling_threads(); 864 g_test_run_type = TEST_RUN_TYPE_DISCONNECT_BAD_ASSOC; 865 run_disconn_test(&g_tgt_port, 0xffff); 866 } 867 868 /* 869 * SPDK functions that are called by LS processing 870 */ 871 872 int 873 spdk_nvmf_fc_xmt_ls_rsp(struct spdk_nvmf_fc_nport *g_tgt_port, 874 struct spdk_nvmf_fc_ls_rqst *ls_rqst) 875 { 876 switch (g_test_run_type) { 877 case TEST_RUN_TYPE_CREATE_ASSOC: 878 g_last_rslt = handle_ca_rsp(ls_rqst, false); 879 break; 880 case TEST_RUN_TYPE_CREATE_CONN: 881 g_last_rslt = handle_cc_rsp(ls_rqst); 882 break; 883 case TEST_RUN_TYPE_DISCONNECT: 884 g_last_rslt = handle_disconn_rsp(ls_rqst); 885 break; 886 case TEST_RUN_TYPE_CONN_BAD_ASSOC: 887 g_last_rslt = handle_conn_bad_assoc_rsp(ls_rqst); 888 break; 889 case TEST_RUN_TYPE_FAIL_LS_RSP: 890 g_last_rslt = handle_ca_rsp(ls_rqst, false); 891 return 1; 892 case TEST_RUN_TYPE_DISCONNECT_BAD_ASSOC: 893 g_last_rslt = handle_disconn_bad_assoc_rsp(ls_rqst); 894 break; 895 case TEST_RUN_TYPE_CREATE_MAX_ASSOC: 896 g_last_rslt = handle_ca_rsp(ls_rqst, true); 897 break; 898 899 default: 900 CU_FAIL("LS Response for Invalid Test Type"); 901 g_last_rslt = 1; 902 } 903 904 return 0; 905 } 906 907 int 908 spdk_nvmf_fc_xmt_srsr_req(struct spdk_nvmf_fc_hwqp *hwqp, 909 struct spdk_nvmf_fc_srsr_bufs *srsr_bufs, 910 spdk_nvmf_fc_caller_cb cb, void *cb_args) 911 { 912 struct spdk_nvmf_fc_ls_disconnect_rqst *dc_rqst = 913 (struct spdk_nvmf_fc_ls_disconnect_rqst *) 914 srsr_bufs->rqst; 915 916 CU_ASSERT(dc_rqst->w0.ls_cmd == FCNVME_LS_DISCONNECT); 917 CU_ASSERT(from_be32(&dc_rqst->desc_list_len) == 918 sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst) - 919 (2 * sizeof(uint32_t))); 920 CU_ASSERT(from_be32(&dc_rqst->assoc_id.desc_tag) == 921 FCNVME_LSDESC_ASSOC_ID); 922 CU_ASSERT(from_be32(&dc_rqst->assoc_id.desc_len) == 923 sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) - 924 (2 * sizeof(uint32_t))); 925 926 g_spdk_nvmf_fc_xmt_srsr_req = true; 927 928 if (cb) { 929 cb(hwqp, 0, cb_args); 930 } 931 932 return 0; 933 } 934 935 DEFINE_STUB_V(spdk_nvmf_fc_request_abort, (struct spdk_nvmf_fc_request *fc_req, 936 bool send_abts, spdk_nvmf_fc_caller_cb cb, void *cb_args)); 937 DEFINE_STUB_V(spdk_bdev_io_abort, (struct spdk_bdev_io *bdev_io, void *ctx)); 938 DEFINE_STUB_V(spdk_nvmf_fc_request_abort_complete, (void *arg1)); 939 940 static void 941 usage(const char *program_name) 942 { 943 printf("%s [options]\n", program_name); 944 printf("options:\n"); 945 spdk_log_usage(stdout, "-t"); 946 printf(" -i value - Number of IO Queues (default: %u)\n", 947 g_fc_port.num_io_queues); 948 printf(" -d value - HW queue depth (default: %u)\n", 949 g_hw_queue_depth); 950 printf(" -q value - SQ size (default: %u)\n", 951 g_nvmf_transport_opts.max_queue_depth); 952 printf(" -c value - Connection count (default: %u)\n", 953 g_nvmf_transport_opts.max_qpairs_per_ctrlr); 954 printf(" -u test# - Unit test# to run\n"); 955 printf(" 0 : Run all tests (default)\n"); 956 printf(" 1 : CASS/DISC create single assoc test\n"); 957 printf(" 2 : Max. conns. test\n"); 958 printf(" 3 : CIOC to invalid assoc_id connection test\n"); 959 printf(" 4 : Create/delete max assoc conns test\n"); 960 printf(" 5 : LS response failure test\n"); 961 printf(" 6 : Disconnect bad assoc_id test\n"); 962 } 963 964 int main(int argc, char **argv) 965 { 966 unsigned int num_failures = 0; 967 CU_pSuite suite = NULL; 968 int test = 0; 969 long int val; 970 int op; 971 972 while ((op = getopt(argc, argv, "a:q:c:t:u:d:i:")) != -1) { 973 switch (op) { 974 case 'q': 975 val = spdk_strtol(optarg, 10); 976 if (val < 16) { 977 fprintf(stderr, "SQ size must be at least 16\n"); 978 return -EINVAL; 979 } 980 g_nvmf_transport_opts.max_queue_depth = (uint16_t)val; 981 break; 982 case 'c': 983 val = spdk_strtol(optarg, 10); 984 if (val < 2) { 985 fprintf(stderr, "Connection count must be at least 2\n"); 986 return -EINVAL; 987 } 988 g_nvmf_transport_opts.max_qpairs_per_ctrlr = (uint16_t)val; 989 break; 990 case 't': 991 if (spdk_log_set_flag(optarg) < 0) { 992 fprintf(stderr, "Unknown trace flag '%s'\n", optarg); 993 usage(argv[0]); 994 return -EINVAL; 995 } 996 break; 997 case 'u': 998 test = (int)spdk_strtol(optarg, 10); 999 break; 1000 case 'd': 1001 val = spdk_strtol(optarg, 10); 1002 if (val < 16) { 1003 fprintf(stderr, "HW queue depth must be at least 16\n"); 1004 return -EINVAL; 1005 } 1006 g_hw_queue_depth = (uint32_t)val; 1007 break; 1008 case 'i': 1009 val = spdk_strtol(optarg, 10); 1010 if (val < 2) { 1011 fprintf(stderr, "Number of io queues must be at least 2\n"); 1012 return -EINVAL; 1013 } 1014 if (val > FC_LS_UT_MAX_IO_QUEUES) { 1015 fprintf(stderr, "Number of io queues can't be greater than %d\n", 1016 FC_LS_UT_MAX_IO_QUEUES); 1017 return -EINVAL; 1018 } 1019 g_fc_port.num_io_queues = (uint32_t)val; 1020 break; 1021 1022 1023 default: 1024 usage(argv[0]); 1025 return -EINVAL; 1026 } 1027 } 1028 1029 if (CU_initialize_registry() != CUE_SUCCESS) { 1030 return CU_get_error(); 1031 } 1032 1033 suite = CU_add_suite("FC-NVMe LS", ls_tests_init, ls_tests_fini); 1034 if (suite == NULL) { 1035 CU_cleanup_registry(); 1036 return CU_get_error(); 1037 } 1038 1039 if (test == 0) { 1040 1041 if (CU_add_test(suite, "CASS/DISC", create_single_assoc_test) == NULL) { 1042 CU_cleanup_registry(); 1043 return CU_get_error(); 1044 } 1045 1046 if (CU_add_test(suite, "Max. Connections", create_max_conns_test) == NULL) { 1047 CU_cleanup_registry(); 1048 return CU_get_error(); 1049 } 1050 1051 if (CU_add_test(suite, "CIOC to bad assoc_id", invalid_connection_test) == NULL) { 1052 CU_cleanup_registry(); 1053 return CU_get_error(); 1054 } 1055 1056 if (CU_add_test(suite, "DISC bad assoc_id", disconnect_bad_assoc_test) == NULL) { 1057 CU_cleanup_registry(); 1058 return CU_get_error(); 1059 } 1060 1061 if (CU_add_test(suite, "Create/delete max. assocs/conns", create_max_aq_conns_test) == NULL) { 1062 CU_cleanup_registry(); 1063 return CU_get_error(); 1064 } 1065 1066 if (CU_add_test(suite, "Xmt LS RSP ERR Cleanup", xmt_ls_rsp_failure_test) == NULL) { 1067 CU_cleanup_registry(); 1068 return CU_get_error(); 1069 } 1070 1071 } else { 1072 1073 switch (test) { 1074 case 1: 1075 if (CU_add_test(suite, "CASS/DISC", create_single_assoc_test) == NULL) { 1076 CU_cleanup_registry(); 1077 return CU_get_error(); 1078 } 1079 break; 1080 case 2: 1081 if (CU_add_test(suite, "Max. Connections", create_max_conns_test) == NULL) { 1082 CU_cleanup_registry(); 1083 return CU_get_error(); 1084 } 1085 break; 1086 case 3: 1087 if (CU_add_test(suite, "CIOC to bad assoc_id", invalid_connection_test) == NULL) { 1088 CU_cleanup_registry(); 1089 return CU_get_error(); 1090 } 1091 break; 1092 case 4: 1093 if (CU_add_test(suite, "Create/delete max. assocs/conns", 1094 create_max_aq_conns_test) == NULL) { 1095 CU_cleanup_registry(); 1096 return CU_get_error(); 1097 } 1098 break; 1099 case 5: 1100 if (CU_add_test(suite, "Xmt LS RSP ERR Cleanup", xmt_ls_rsp_failure_test) == NULL) { 1101 CU_cleanup_registry(); 1102 return CU_get_error(); 1103 } 1104 break; 1105 case 6: 1106 if (CU_add_test(suite, "DISC bad assoc_id", disconnect_bad_assoc_test) == NULL) { 1107 CU_cleanup_registry(); 1108 return CU_get_error(); 1109 } 1110 break; 1111 1112 default: 1113 fprintf(stderr, "Invalid test number\n"); 1114 usage(argv[0]); 1115 CU_cleanup_registry(); 1116 return -EINVAL; 1117 } 1118 } 1119 1120 CU_basic_set_mode(CU_BRM_VERBOSE); 1121 CU_basic_run_tests(); 1122 num_failures = CU_get_number_of_failures(); 1123 CU_cleanup_registry(); 1124 1125 return num_failures; 1126 } 1127