diff --git a/lib/nvmf/direct.c b/lib/nvmf/direct.c index c2631fafb0..7f51f60653 100644 --- a/lib/nvmf/direct.c +++ b/lib/nvmf/direct.c @@ -157,6 +157,8 @@ nvmf_direct_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req) response->cdw0 = ((nr_io_queues - 1) << 16) | (nr_io_queues - 1); return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + case SPDK_NVME_FEAT_HOST_IDENTIFIER: + return spdk_nvmf_session_get_features_host_identifier(req); default: goto passthrough; } @@ -177,6 +179,8 @@ nvmf_direct_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req) (nr_io_queues - 1); } return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + case SPDK_NVME_FEAT_HOST_IDENTIFIER: + return spdk_nvmf_session_set_features_host_identifier(req); default: goto passthrough; } diff --git a/lib/nvmf/session.c b/lib/nvmf/session.c index d0adf44355..d37c3d7296 100644 --- a/lib/nvmf/session.c +++ b/lib/nvmf/session.c @@ -262,6 +262,8 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn, session->subsys = subsystem; session->max_connections_allowed = g_nvmf_tgt.max_queues_per_session; + memcpy(session->hostid, data->hostid, sizeof(session->hostid)); + if (conn->transport->session_add_conn(session, conn)) { rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR; conn->transport->session_fini(session); @@ -580,3 +582,38 @@ spdk_nvmf_session_poll(struct spdk_nvmf_session *session) return 0; } + +int +spdk_nvmf_session_set_features_host_identifier(struct spdk_nvmf_request *req) +{ + struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; + + SPDK_ERRLOG("Set Features - Host Identifier not allowed\n"); + response->status.sc = SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; +} + +int +spdk_nvmf_session_get_features_host_identifier(struct spdk_nvmf_request *req) +{ + struct spdk_nvmf_session *session = req->conn->sess; + struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd; + struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl; + + SPDK_TRACELOG(SPDK_TRACE_NVMF, "Get Features - Host Identifier\n"); + if (!(cmd->cdw11 & 1)) { + /* NVMe over Fabrics requires EXHID=1 (128-bit/16-byte host ID) */ + SPDK_ERRLOG("Get Features - Host Identifier with EXHID=0 not allowed\n"); + response->status.sc = SPDK_NVME_SC_INVALID_FIELD; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + if (req->data == NULL || req->length < sizeof(session->hostid)) { + SPDK_ERRLOG("Invalid data buffer for Get Features - Host Identifier\n"); + response->status.sc = SPDK_NVME_SC_INVALID_FIELD; + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + } + + memcpy(req->data, session->hostid, sizeof(session->hostid)); + return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; +} diff --git a/lib/nvmf/session.h b/lib/nvmf/session.h index cf3f60d2e9..14e892c635 100644 --- a/lib/nvmf/session.h +++ b/lib/nvmf/session.h @@ -44,6 +44,7 @@ #define MAX_SESSION_IO_QUEUES 64 struct spdk_nvmf_transport; +struct spdk_nvmf_request; enum conn_type { CONN_TYPE_AQ = 0, @@ -90,6 +91,7 @@ struct spdk_nvmf_session { uint8_t fw_activation_notice : 1; } bits; } async_event_config; + uint8_t hostid[16]; const struct spdk_nvmf_transport *transport; TAILQ_ENTRY(spdk_nvmf_session) link; @@ -114,4 +116,7 @@ int spdk_nvmf_session_poll(struct spdk_nvmf_session *session); void spdk_nvmf_session_destruct(struct spdk_nvmf_session *session); +int spdk_nvmf_session_set_features_host_identifier(struct spdk_nvmf_request *req); +int spdk_nvmf_session_get_features_host_identifier(struct spdk_nvmf_request *req); + #endif diff --git a/lib/nvmf/virtual.c b/lib/nvmf/virtual.c index 99164b50d9..7871d95965 100644 --- a/lib/nvmf/virtual.c +++ b/lib/nvmf/virtual.c @@ -293,6 +293,8 @@ nvmf_virtual_ctrlr_get_features(struct spdk_nvmf_request *req) SPDK_TRACELOG(SPDK_TRACE_NVMF, "Get Features - Async Event Configuration\n"); response->cdw0 = session->async_event_config.raw; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + case SPDK_NVME_FEAT_HOST_IDENTIFIER: + return spdk_nvmf_session_get_features_host_identifier(req); default: SPDK_ERRLOG("Get Features command with unsupported feature ID 0x%02x\n", feature); response->status.sc = SPDK_NVME_SC_INVALID_FIELD; @@ -338,6 +340,8 @@ nvmf_virtual_ctrlr_set_features(struct spdk_nvmf_request *req) cmd->cdw11); session->async_event_config.raw = cmd->cdw11; return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; + case SPDK_NVME_FEAT_HOST_IDENTIFIER: + return spdk_nvmf_session_set_features_host_identifier(req); default: SPDK_ERRLOG("Set Features command with unsupported feature ID 0x%02x\n", feature); response->status.sc = SPDK_NVME_SC_INVALID_FIELD;