예제 #1
0
파일: nvmf_ut.c 프로젝트: 64116278/spdk
static void
nvmf_test_connect(void)
{
	uint64_t fabric_conn = 0;
	uint64_t fabric_conn_admin = 1;
	uint64_t fabric_conn_IO = 2;
	struct nvmf_session *sess, *io_sess;
	struct spdk_nvmf_fabric_connect_cmd connect = {};
	struct spdk_nvmf_fabric_connect_data connect_data = {};
	struct spdk_nvmf_fabric_connect_rsp response = {};
	struct spdk_nvmf_fabric_connect_rsp expect_rsp = {};


	connect.opcode = 0x7f;
	connect.cid = 0x01;
	connect.fctype = 0x01;
	connect_data.cntlid = 0xffff;
	connect.qid = 0;
	connect.sqsize = 64;

	/* change cmd field to do failure test first */
	/* invalid subnqn and qid = 0*/
	strcpy((char *)connect_data.subnqn, "fake");
	CU_ASSERT_PTR_NULL(nvmf_connect((void *)fabric_conn, &connect, &connect_data, &response));
	CU_ASSERT_NOT_EQUAL(response.status.sc, 0);
	/* valid subnqn and qid = 0 and cntlid != 0xfffff */
	strcpy((char *)connect_data.subnqn, "subsystem1");
	connect_data.cntlid = 0x000f;
	CU_ASSERT_PTR_NULL(nvmf_connect((void *)fabric_conn, &connect, &connect_data, &response));
	CU_ASSERT_EQUAL(response.status.sc, SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
	/* invalid subnqn and qid = 1 */
	strcpy((char *)connect_data.subnqn, "fake");
	connect.qid = 1;
	connect_data.cntlid = 0;
	CU_ASSERT_PTR_NULL(nvmf_connect((void *)fabric_conn, &connect, &connect_data, &response));
	CU_ASSERT_EQUAL(response.status.sc, SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY);
	/* valid subnqn but session is not created. */
	strcpy((char *)connect_data.subnqn, "subsystem1");
	connect_data.cntlid = 0;
	CU_ASSERT_PTR_NULL(nvmf_connect((void *)fabric_conn, &connect, &connect_data, &response));
	CU_ASSERT_EQUAL(response.status.sc, SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY);
	/* create admin connection */
	connect.qid = 0;
	connect_data.cntlid = 0xffff;
	sess = nvmf_connect((void *)fabric_conn_admin, &connect, &connect_data, &response);
	SPDK_CU_ASSERT_FATAL(sess != NULL);
	nvmf_init_session_properties(sess, 64);
	sess->max_connections_allowed = 2;
	CU_ASSERT_EQUAL(sess->num_connections, 1);
	CU_ASSERT_PTR_EQUAL(sess->connections.tqh_first->fabric_conn, fabric_conn_admin);
	expect_rsp.status_code_specific.success.cntlid = SS_SC_CNTLID;
	expect_rsp.status.sc = 0;
	help_response_check(&response, &expect_rsp);
	/* create IO connection */
	connect.cid = 0x02;
	connect.qid = 1;
	connect_data.cntlid = SS_SC_CNTLID;
	io_sess = nvmf_connect((void *)fabric_conn_IO, &connect, &connect_data, &response);
	SPDK_CU_ASSERT_FATAL(io_sess != NULL);
	CU_ASSERT_EQUAL(io_sess->num_connections, 2);
	/* check admin and io connection are in same session. */
	CU_ASSERT_PTR_EQUAL(io_sess, sess);
	expect_rsp.status_code_specific.success.cntlid = SS_SC_CNTLID;
	expect_rsp.status.sc = 0;
	help_response_check(&response, &expect_rsp);
	/* right subnqn, session is created, but wrong cntlid */
	connect_data.cntlid = 1;
	connect.qid = 2;
	CU_ASSERT_PTR_NULL(nvmf_connect((void *)&fabric_conn, &connect, &connect_data, &response));
	CU_ASSERT_EQUAL(response.status.sc, SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY);
}
예제 #2
0
파일: request.c 프로젝트: Shengliang/spdk
static bool
nvmf_process_connect(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_fabric_connect_cmd *connect;
	struct spdk_nvmf_fabric_connect_data *connect_data;
	struct spdk_nvmf_fabric_connect_rsp *response;
	struct spdk_nvmf_conn *conn = req->conn;
	struct nvmf_session *session;

	if (req->length < sizeof(struct spdk_nvmf_fabric_connect_data)) {
		SPDK_ERRLOG("Connect command data length 0x%x too small\n", req->length);
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_FIELD;
		return true;
	}

	connect = &req->cmd->connect_cmd;
	connect_data = (struct spdk_nvmf_fabric_connect_data *)req->data;

	RTE_VERIFY(connect_data != NULL);

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "Connect cmd: cid 0x%x recfmt 0x%x qid %u sqsize %u\n",
		      connect->cid, connect->recfmt, connect->qid, connect->sqsize);

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "Connect data:\n");
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "  cntlid:  0x%04x\n", connect_data->cntlid);
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "  hostid: %08x-%04x-%04x-%02x%02x-%04x%08x ***\n",
		      ntohl(*(uint32_t *)&connect_data->hostid[0]),
		      ntohs(*(uint16_t *)&connect_data->hostid[4]),
		      ntohs(*(uint16_t *)&connect_data->hostid[6]),
		      connect_data->hostid[8],
		      connect_data->hostid[9],
		      ntohs(*(uint16_t *)&connect_data->hostid[10]),
		      ntohl(*(uint32_t *)&connect_data->hostid[12]));
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "  subnqn: \"%s\"\n", (char *)&connect_data->subnqn[0]);
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "  hostnqn: \"%s\"\n", (char *)&connect_data->hostnqn[0]);

	response = &req->rsp->connect_rsp;

	session = nvmf_connect((void *)conn, connect, connect_data, response);
	if (session != NULL) {
		conn->sess = session;
		conn->qid = connect->qid;
		if (connect->qid > 0) {
			conn->type = CONN_TYPE_IOQ; /* I/O Connection */
		} else {
			/* When session first created, set some attributes */
			nvmf_init_conn_properites(conn, session, response);
		}
	}

	/* Allocate RDMA reqs according to the queue depth and conn type*/
	if (spdk_nvmf_rdma_alloc_reqs(conn)) {
		SPDK_ERRLOG("Unable to allocate sufficient RDMA work requests\n");
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
		return true;
	}

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "connect capsule response: cntlid = 0x%04x\n",
		      response->status_code_specific.success.cntlid);
	return true;
}
예제 #3
0
파일: conn.c 프로젝트: varun2784/spdk
static void
nvmf_connect_continue(struct spdk_nvmf_conn *conn,
		      struct nvme_qp_tx_desc *tx_desc)
{
	struct nvme_qp_rx_desc *rx_desc;
	struct nvmf_request *req;
	struct spdk_nvmf_fabric_connect_cmd *connect;
	struct spdk_nvmf_fabric_connect_data *connect_data;
	struct spdk_nvmf_fabric_connect_rsp *response;
	struct nvmf_session *session;
	int ret;

	if (tx_desc == NULL) {
		SPDK_TRACELOG(SPDK_TRACE_DEBUG, " tx_desc does not exist!\n");
		return;
	}
	rx_desc = tx_desc->rx_desc;
	if (rx_desc == NULL) {
		SPDK_TRACELOG(SPDK_TRACE_DEBUG, " rx_desc does not exist!\n");
		return;
	}

	connect = (struct spdk_nvmf_fabric_connect_cmd *)&rx_desc->msg_buf;
	connect_data = (struct spdk_nvmf_fabric_connect_data *)rx_desc->bb;

	req = &tx_desc->req_state;

	/* clear the SGL details for any RDMA previously performed */
	req->length = 0;

	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** Connect Capsule Data *** %p\n", connect_data);
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** cntlid  = %x ***\n", connect_data->cntlid);
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** hostid = %04x%04x-%04x-%04x-%04x-%04x%04x%04x ***\n",
		      htons(*(unsigned short *) &connect_data->hostid[0]),
		      htons(*(unsigned short *) &connect_data->hostid[2]),
		      htons(*(unsigned short *) &connect_data->hostid[4]),
		      htons(*(unsigned short *) &connect_data->hostid[6]),
		      htons(*(unsigned short *) &connect_data->hostid[8]),
		      htons(*(unsigned short *) &connect_data->hostid[10]),
		      htons(*(unsigned short *) &connect_data->hostid[12]),
		      htons(*(unsigned short *) &connect_data->hostid[14]));
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** subsiqn = %s ***\n", (char *)&connect_data->subnqn[0]);
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** hostiqn = %s ***\n", (char *)&connect_data->hostnqn[0]);

	response = &req->rsp->connect_rsp;

	session = nvmf_connect((void *)conn, connect, connect_data, response);
	if (session != NULL) {
		conn->sess = session;
		conn->qid = connect->qid;
		if (connect->qid > 0) {
			conn->type = CONN_TYPE_IOQ; /* I/O Connection */
		} else {
			/* When session first created, set some attributes */
			nvmf_init_conn_properites(conn, session, response);
		}
	}

	/* synchronous call, nvmf library expected to init
	   response status.
	 */
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "send connect capsule response\n");
	SPDK_TRACELOG(SPDK_TRACE_NVMF, "    *** cntlid  = %x ***\n",
		      response->status_code_specific.success.cntlid);
	ret = spdk_nvmf_send_response(conn, req);
	if (ret) {
		SPDK_ERRLOG("Unable to send aq qp tx descriptor\n");
		goto connect_error;
	}
	return;

connect_error:
	/* recover the tx_desc */
	if (tx_desc != NULL) {
		tx_desc->rx_desc = NULL;
		nvmf_deactive_tx_desc(tx_desc);
	}
}