Commit 5323a026 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

nvmf: move fabrics command processing to ctrlr.c



This is the final set of command processing functions (admin and I/O
commands were already handled in ctrlr.c), and it allows us to clean up
the ctrlr.c API some more.

Change-Id: Ic73c56c44d7fd64bfaa72b6f5f6f0984b4dfa053
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
Reviewed-on: https://review.gerrithub.io/378018


Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
parent 4ff0eba8
Loading
Loading
Loading
Loading
+84 −31
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ spdk_nvmf_invalid_connect_response(struct spdk_nvmf_fabric_connect_rsp *rsp,
#define SPDK_NVMF_INVALID_CONNECT_DATA(rsp, field)	\
	spdk_nvmf_invalid_connect_response(rsp, 1, offsetof(struct spdk_nvmf_fabric_connect_data, field))

void
static int
spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_fabric_connect_data *data = req->data;
@@ -183,7 +183,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
	if (req->length < sizeof(struct spdk_nvmf_fabric_connect_data)) {
		SPDK_ERRLOG("Connect command data length 0x%x too small\n", req->length);
		rsp->status.sc = SPDK_NVME_SC_INVALID_FIELD;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "recfmt 0x%x qid %u sqsize %u\n",
@@ -204,7 +204,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
		SPDK_ERRLOG("Connect command unsupported RECFMT %u\n", cmd->recfmt);
		rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
		rsp->status.sc = SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	/* Ensure that subnqn is null terminated */
@@ -212,7 +212,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
	if (!end) {
		SPDK_ERRLOG("Connect SUBNQN is not null terminated\n");
		SPDK_NVMF_INVALID_CONNECT_DATA(rsp, subnqn);
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}
	subnqn = data->subnqn;
	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "  subnqn: \"%s\"\n", subnqn);
@@ -221,7 +221,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
	if (subsystem == NULL) {
		SPDK_ERRLOG("Could not find subsystem '%s'\n", subnqn);
		SPDK_NVMF_INVALID_CONNECT_DATA(rsp, subnqn);
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	/* Ensure that hostnqn is null terminated */
@@ -229,7 +229,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
	if (!end) {
		SPDK_ERRLOG("Connect HOSTNQN is not null terminated\n");
		SPDK_NVMF_INVALID_CONNECT_DATA(rsp, hostnqn);
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}
	hostnqn = data->hostnqn;
	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "  hostnqn: \"%s\"\n", hostnqn);
@@ -238,7 +238,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
		SPDK_ERRLOG("Subsystem '%s' does not allow host '%s'\n", subnqn, hostnqn);
		rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
		rsp->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_HOST;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	/*
@@ -249,7 +249,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
		SPDK_ERRLOG("Invalid SQSIZE %u (min 1, max %u)\n",
			    cmd->sqsize, tgt->opts.max_queue_depth - 1);
		SPDK_NVMF_INVALID_CONNECT_CMD(rsp, sqsize);
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}
	qpair->sq_head_max = cmd->sqsize;
	qpair->qid = cmd->qid;
@@ -263,7 +263,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
			/* This NVMf target only supports dynamic mode. */
			SPDK_ERRLOG("The NVMf target only supports dynamic mode (CNTLID = 0x%x).\n", data->cntlid);
			SPDK_NVMF_INVALID_CONNECT_DATA(rsp, cntlid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		/* Establish a new ctrlr */
@@ -271,7 +271,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
		if (!ctrlr) {
			SPDK_ERRLOG("spdk_nvmf_ctrlr_create() failed\n");
			rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	} else {
		qpair->type = QPAIR_TYPE_IOQ;
@@ -281,33 +281,33 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
		if (ctrlr == NULL) {
			SPDK_ERRLOG("Unknown controller ID 0x%x\n", data->cntlid);
			SPDK_NVMF_INVALID_CONNECT_DATA(rsp, cntlid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		if (ctrlr->subsys->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
			SPDK_ERRLOG("I/O connect not allowed on discovery controller\n");
			SPDK_NVMF_INVALID_CONNECT_CMD(rsp, qid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		if (!ctrlr->vcprop.cc.bits.en) {
			SPDK_ERRLOG("Got I/O connect before ctrlr was enabled\n");
			SPDK_NVMF_INVALID_CONNECT_CMD(rsp, qid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		if (1u << ctrlr->vcprop.cc.bits.iosqes != sizeof(struct spdk_nvme_cmd)) {
			SPDK_ERRLOG("Got I/O connect with invalid IOSQES %u\n",
				    ctrlr->vcprop.cc.bits.iosqes);
			SPDK_NVMF_INVALID_CONNECT_CMD(rsp, qid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		if (1u << ctrlr->vcprop.cc.bits.iocqes != sizeof(struct spdk_nvme_cpl)) {
			SPDK_ERRLOG("Got I/O connect with invalid IOCQES %u\n",
				    ctrlr->vcprop.cc.bits.iocqes);
			SPDK_NVMF_INVALID_CONNECT_CMD(rsp, qid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		/* check if we would exceed ctrlr connection limit */
@@ -315,12 +315,12 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
			SPDK_ERRLOG("qpair limit %d\n", ctrlr->num_qpairs);
			rsp->status.sct = SPDK_NVME_SCT_COMMAND_SPECIFIC;
			rsp->status.sc = SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY;
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}

		if (spdk_nvmf_poll_group_add(ctrlr->group, qpair)) {
			SPDK_NVMF_INVALID_CONNECT_CMD(rsp, qid);
			return;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	}

@@ -335,6 +335,7 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
	rsp->status_code_specific.success.cntlid = ctrlr->cntlid;
	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "connect capsule response: cntlid = 0x%04x\n",
		      rsp->status_code_specific.success.cntlid);
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

void
@@ -506,11 +507,12 @@ find_prop(uint32_t ofst)
	return NULL;
}

void
spdk_nvmf_property_get(struct spdk_nvmf_ctrlr *ctrlr,
		       struct spdk_nvmf_fabric_prop_get_cmd *cmd,
		       struct spdk_nvmf_fabric_prop_get_rsp *response)
static int
spdk_nvmf_property_get(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
	struct spdk_nvmf_fabric_prop_get_cmd *cmd = &req->cmd->prop_get_cmd;
	struct spdk_nvmf_fabric_prop_get_rsp *response = &req->rsp->prop_get_rsp;
	const struct nvmf_prop *prop;

	response->status.sc = 0;
@@ -523,13 +525,13 @@ spdk_nvmf_property_get(struct spdk_nvmf_ctrlr *ctrlr,
	    cmd->attrib.size != SPDK_NVMF_PROP_SIZE_8) {
		SPDK_ERRLOG("Invalid size value %d\n", cmd->attrib.size);
		response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	prop = find_prop(cmd->ofst);
	if (prop == NULL || prop->get_cb == NULL) {
		/* Reserved properties return 0 when read */
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "name: %s\n", prop->name);
@@ -537,18 +539,21 @@ spdk_nvmf_property_get(struct spdk_nvmf_ctrlr *ctrlr,
		SPDK_ERRLOG("offset 0x%x size mismatch: cmd %u, prop %u\n",
			    cmd->ofst, cmd->attrib.size, prop->size);
		response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	response->value.u64 = prop->get_cb(ctrlr);
	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "response value: 0x%" PRIx64 "\n", response->value.u64);

	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

void
spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
		       struct spdk_nvmf_fabric_prop_set_cmd *cmd,
		       struct spdk_nvme_cpl *response)
static int
spdk_nvmf_property_set(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_ctrlr *ctrlr = req->qpair->ctrlr;
	struct spdk_nvmf_fabric_prop_set_cmd *cmd = &req->cmd->prop_set_cmd;
	struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
	const struct nvmf_prop *prop;
	uint64_t value;

@@ -559,7 +564,7 @@ spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
	if (prop == NULL || prop->set_cb == NULL) {
		SPDK_ERRLOG("Invalid offset 0x%x\n", cmd->ofst);
		response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "name: %s\n", prop->name);
@@ -567,7 +572,7 @@ spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
		SPDK_ERRLOG("offset 0x%x size mismatch: cmd %u, prop %u\n",
			    cmd->ofst, cmd->attrib.size, prop->size);
		response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	value = cmd->value.u64;
@@ -578,8 +583,10 @@ spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
	if (!prop->set_cb(ctrlr, value)) {
		SPDK_ERRLOG("prop set_cb failed\n");
		response->status.sc = SPDK_NVMF_FABRIC_SC_INVALID_PARAM;
		return;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}

	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

int
@@ -1151,3 +1158,49 @@ invalid_opcode:
	response->status.sc = SPDK_NVME_SC_INVALID_OPCODE;
	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

int
spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_qpair *qpair = req->qpair;
	struct spdk_nvmf_capsule_cmd *cap_hdr;

	cap_hdr = &req->cmd->nvmf_cmd;

	if (qpair->ctrlr == NULL) {
		/* No ctrlr established yet; the only valid command is Connect */
		if (cap_hdr->fctype == SPDK_NVMF_FABRIC_COMMAND_CONNECT) {
			return spdk_nvmf_ctrlr_connect(req);
		} else {
			SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Got fctype 0x%x, expected Connect\n",
				      cap_hdr->fctype);
			req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
			req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	} else if (qpair->type == QPAIR_TYPE_AQ) {
		/*
		 * Controller session is established, and this is an admin queue.
		 * Disallow Connect and allow other fabrics commands.
		 */
		switch (cap_hdr->fctype) {
		case SPDK_NVMF_FABRIC_COMMAND_PROPERTY_SET:
			return spdk_nvmf_property_set(req);
		case SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET:
			return spdk_nvmf_property_get(req);
		default:
			SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "unknown fctype 0x%02x\n",
				      cap_hdr->fctype);
			req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
			req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	} else {
		/* Controller session is established, and this is an I/O queue */
		/* For now, no I/O-specific Fabrics commands are implemented (other than Connect) */
		SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Unexpected I/O fctype 0x%x\n", cap_hdr->fctype);
		req->rsp->nvme_cpl.status.sct = SPDK_NVME_SCT_GENERIC;
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}
}
+1 −9
Original line number Diff line number Diff line
@@ -214,18 +214,10 @@ void spdk_nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt,
				      void *buffer, uint64_t offset,
				      uint32_t length);

void spdk_nvmf_property_get(struct spdk_nvmf_ctrlr *ctrlr,
			    struct spdk_nvmf_fabric_prop_get_cmd *cmd,
			    struct spdk_nvmf_fabric_prop_get_rsp *response);

void spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
			    struct spdk_nvmf_fabric_prop_set_cmd *cmd,
			    struct spdk_nvme_cpl *rsp);

void spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req);
struct spdk_nvmf_qpair *spdk_nvmf_ctrlr_get_qpair(struct spdk_nvmf_ctrlr *ctrlr, uint16_t qid);
int spdk_nvmf_ctrlr_poll(struct spdk_nvmf_ctrlr *ctrlr);
void spdk_nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr);
int spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req);
int spdk_nvmf_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req);
int spdk_nvmf_ctrlr_process_io_cmd(struct spdk_nvmf_request *req);
bool spdk_nvmf_ctrlr_dsm_supported(struct spdk_nvmf_ctrlr *ctrlr);
+1 −71
Original line number Diff line number Diff line
@@ -83,76 +83,6 @@ spdk_nvmf_request_complete(struct spdk_nvmf_request *req)
	return 0;
}

static spdk_nvmf_request_exec_status
nvmf_process_property_get(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_fabric_prop_get_rsp *response;
	struct spdk_nvmf_fabric_prop_get_cmd *cmd;

	cmd = &req->cmd->prop_get_cmd;
	response = &req->rsp->prop_get_rsp;

	spdk_nvmf_property_get(req->qpair->ctrlr, cmd, response);

	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static spdk_nvmf_request_exec_status
nvmf_process_property_set(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_fabric_prop_set_cmd *cmd;

	cmd = &req->cmd->prop_set_cmd;

	spdk_nvmf_property_set(req->qpair->ctrlr, cmd, &req->rsp->nvme_cpl);

	return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
}

static spdk_nvmf_request_exec_status
nvmf_process_fabrics_command(struct spdk_nvmf_request *req)
{
	struct spdk_nvmf_qpair *qpair = req->qpair;
	struct spdk_nvmf_capsule_cmd *cap_hdr;

	cap_hdr = &req->cmd->nvmf_cmd;

	if (qpair->ctrlr == NULL) {
		/* No ctrlr established yet; the only valid command is Connect */
		if (cap_hdr->fctype == SPDK_NVMF_FABRIC_COMMAND_CONNECT) {
			spdk_nvmf_ctrlr_connect(req);
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		} else {
			SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Got fctype 0x%x, expected Connect\n",
				      cap_hdr->fctype);
			req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	} else if (qpair->type == QPAIR_TYPE_AQ) {
		/*
		 * Controller session is established, and this is an admin queue.
		 * Disallow Connect and allow other fabrics commands.
		 */
		switch (cap_hdr->fctype) {
		case SPDK_NVMF_FABRIC_COMMAND_PROPERTY_SET:
			return nvmf_process_property_set(req);
		case SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET:
			return nvmf_process_property_get(req);
		default:
			SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "recv capsule header type invalid [%x]!\n",
				      cap_hdr->fctype);
			req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE;
			return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
		}
	} else {
		/* Controller session is established, and this is an I/O queue */
		/* For now, no I/O-specific Fabrics commands are implemented (other than Connect) */
		SPDK_DEBUGLOG(SPDK_TRACE_NVMF, "Unexpected I/O fctype 0x%x\n", cap_hdr->fctype);
		req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_INVALID_OPCODE;
		return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
	}
}

static void
nvmf_trace_command(union nvmf_h2c_msg *h2c_msg, enum spdk_nvmf_qpair_type qpair_type)
{
@@ -207,7 +137,7 @@ spdk_nvmf_request_exec_on_master(void *ctx)
	spdk_nvmf_request_exec_status status;

	if (cmd->opc == SPDK_NVME_OPC_FABRIC) {
		status = nvmf_process_fabrics_command(req);
		status = spdk_nvmf_ctrlr_process_fabrics_cmd(req);
	} else if (ctrlr == NULL || !ctrlr->vcprop.cc.bits.en) {
		/* Only Fabric commands are allowed when the controller is disabled */
		SPDK_ERRLOG("Non-Fabric command sent to disabled controller\n");
+24 −1
Original line number Diff line number Diff line
@@ -242,6 +242,27 @@ test_get_log_page(void)
	req.data = data;
}

static void
test_process_fabrics_cmd(void)
{
	struct	spdk_nvmf_request req = {};
	int	ret;
	struct	spdk_nvmf_qpair req_qpair = {};
	union	nvmf_h2c_msg  req_cmd = {};
	union	nvmf_c2h_msg   req_rsp = {};

	req.qpair = &req_qpair;
	req.cmd  = &req_cmd;
	req.rsp  = &req_rsp;
	req.qpair->ctrlr = NULL;

	/* No ctrlr and invalid command check */
	req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET;
	ret = spdk_nvmf_ctrlr_process_fabrics_cmd(&req);
	CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR);
	CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
}

int main(int argc, char **argv)
{
	CU_pSuite	suite = NULL;
@@ -258,7 +279,9 @@ int main(int argc, char **argv)
	}

	if (
		CU_add_test(suite, "get_log_page", test_get_log_page) == NULL) {
		CU_add_test(suite, "get_log_page", test_get_log_page) == NULL ||
		CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL
	) {
		CU_cleanup_registry();
		return CU_get_error();
	}
+5 −40
Original line number Diff line number Diff line
@@ -50,9 +50,10 @@ spdk_nvmf_transport_req_complete(struct spdk_nvmf_request *req)
	return 0;
}

void
spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
int
spdk_nvmf_ctrlr_process_fabrics_cmd(struct spdk_nvmf_request *req)
{
	return -1;
}

int
@@ -116,45 +117,9 @@ spdk_nvmf_ctrlr_disconnect(struct spdk_nvmf_qpair *qpair)
{
}

void
spdk_nvmf_property_get(struct spdk_nvmf_ctrlr *ctrlr,
		       struct spdk_nvmf_fabric_prop_get_cmd *cmd,
		       struct spdk_nvmf_fabric_prop_get_rsp *response)
{
}

void
spdk_nvmf_property_set(struct spdk_nvmf_ctrlr *ctrlr,
		       struct spdk_nvmf_fabric_prop_set_cmd *cmd,
		       struct spdk_nvme_cpl *rsp)
{
}

void
spdk_nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, void *buffer,
				 uint64_t offset, uint32_t length)
{
}

static void
test_nvmf_process_fabrics_cmd(void)
test_placeholder(void)
{
	struct	spdk_nvmf_request req = {};
	int	ret;
	struct	spdk_nvmf_qpair req_qpair = {};
	union	nvmf_h2c_msg  req_cmd = {};
	union	nvmf_c2h_msg   req_rsp = {};

	req.qpair = &req_qpair;
	req.cmd  = &req_cmd;
	req.rsp  = &req_rsp;
	req.qpair->ctrlr = NULL;

	/* No ctrlr and invalid command check */
	req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET;
	ret = nvmf_process_fabrics_command(&req);
	CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR);
	CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
}

int main(int argc, char **argv)
@@ -173,7 +138,7 @@ int main(int argc, char **argv)
	}

	if (
		CU_add_test(suite, "nvmf_process_fabrics_command", test_nvmf_process_fabrics_cmd) == NULL) {
		CU_add_test(suite, "placeholder", test_placeholder) == NULL) {
		CU_cleanup_registry();
		return CU_get_error();
	}