nvmf/tcp: Add unit test to test SGL handling in C2H and H2C

This patch adds UT code to test nvmf_tcp_send_c2h_data,
nvmf_tcp_calc_c2h_data_pdu_num, and nvmf_tcp_h2c_data_hdr_handle,
and verifies if the last changes works expectedly.

Change-Id: Idba21a4739635b7828049f1d71c3bc1595deaab0
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455626
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ziye Yang <ziye.yang@intel.com>
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2019-05-24 14:14:59 +09:00 committed by Darek Stojaczyk
parent 3184884f9d
commit 16b8519660

View File

@ -374,6 +374,174 @@ test_nvmf_tcp_poll_group_create(void)
spdk_thread_destroy(thread);
}
static void
test_nvmf_tcp_send_c2h_data(void)
{
struct spdk_thread *thread;
struct spdk_nvmf_tcp_transport ttransport = {};
struct spdk_nvmf_tcp_qpair tqpair = {};
struct spdk_nvmf_tcp_req tcp_req = {};
struct nvme_tcp_pdu pdu = {};
struct spdk_nvme_tcp_c2h_data_hdr *c2h_data;
thread = spdk_thread_create(NULL, NULL);
SPDK_CU_ASSERT_FATAL(thread != NULL);
spdk_set_thread(thread);
tqpair.qpair.transport = &ttransport.transport;
TAILQ_INIT(&tqpair.free_queue);
TAILQ_INIT(&tqpair.send_queue);
TAILQ_INIT(&tqpair.queued_c2h_data_tcp_req);
/* Set qpair state to make unrelated operations NOP */
tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
TAILQ_INSERT_TAIL(&tqpair.free_queue, &pdu, tailq);
tqpair.free_pdu_num++;
tcp_req.req.cmd = (union nvmf_h2c_msg *)&tcp_req.cmd;
tcp_req.req.iov[0].iov_base = (void *)0xDEADBEEF;
tcp_req.req.iov[0].iov_len = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE;
tcp_req.req.iov[1].iov_base = (void *)0xFEEDBEEF;
tcp_req.req.iov[1].iov_len = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE;
tcp_req.req.iov[2].iov_base = (void *)0xC0FFEE;
tcp_req.req.iov[2].iov_len = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE;
tcp_req.req.iovcnt = 3;
tcp_req.req.length = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE * 3;
CU_ASSERT(spdk_nvmf_tcp_calc_c2h_data_pdu_num(&tcp_req) == 3);
TAILQ_INSERT_TAIL(&tqpair.queued_c2h_data_tcp_req, &tcp_req, link);
tcp_req.c2h_data_offset = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2;
/* 1st C2H */
spdk_nvmf_tcp_send_c2h_data(&tqpair, &tcp_req);
CU_ASSERT(TAILQ_FIRST(&tqpair.send_queue) == &pdu);
TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
TAILQ_INSERT_TAIL(&tqpair.free_queue, &pdu, tailq);
tqpair.free_pdu_num++;
c2h_data = &pdu.hdr.c2h_data;
CU_ASSERT(c2h_data->datao == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(c2h_data->datal = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE);
CU_ASSERT(c2h_data->common.plen == sizeof(*c2h_data) + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE);
CU_ASSERT(!(c2h_data->common.flags & SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU));
CU_ASSERT(pdu.data_iovcnt == 2);
CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xDEADBEEF + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(pdu.data_iov[0].iov_len == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT((uint64_t)pdu.data_iov[1].iov_base == 0xFEEDBEEF);
CU_ASSERT(pdu.data_iov[1].iov_len == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(tcp_req.c2h_data_offset == (NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2) * 3);
CU_ASSERT(TAILQ_FIRST(&tqpair.queued_c2h_data_tcp_req) == &tcp_req);
/* 2nd C2H */
spdk_nvmf_tcp_send_c2h_data(&tqpair, &tcp_req);
CU_ASSERT(TAILQ_FIRST(&tqpair.send_queue) == &pdu);
TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
TAILQ_INSERT_TAIL(&tqpair.free_queue, &pdu, tailq);
tqpair.free_pdu_num++;
c2h_data = &pdu.hdr.c2h_data;
CU_ASSERT(c2h_data->datao == (NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2) * 3);
CU_ASSERT(c2h_data->datal = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE);
CU_ASSERT(c2h_data->common.plen == sizeof(*c2h_data) + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE);
CU_ASSERT(!(c2h_data->common.flags & SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU));
CU_ASSERT(pdu.data_iovcnt == 2);
CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xFEEDBEEF + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(pdu.data_iov[0].iov_len == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT((uint64_t)pdu.data_iov[1].iov_base == 0xC0FFEE);
CU_ASSERT(pdu.data_iov[1].iov_len == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(tcp_req.c2h_data_offset == (NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2) * 5);
CU_ASSERT(TAILQ_FIRST(&tqpair.queued_c2h_data_tcp_req) == &tcp_req);
/* 3rd C2H */
spdk_nvmf_tcp_send_c2h_data(&tqpair, &tcp_req);
CU_ASSERT(TAILQ_FIRST(&tqpair.send_queue) == &pdu);
TAILQ_REMOVE(&tqpair.send_queue, &pdu, tailq);
CU_ASSERT(TAILQ_EMPTY(&tqpair.send_queue));
c2h_data = &pdu.hdr.c2h_data;
CU_ASSERT(c2h_data->datao == (NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2) * 5);
CU_ASSERT(c2h_data->datal = NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(c2h_data->common.plen == sizeof(*c2h_data) + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(c2h_data->common.flags & SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU);
CU_ASSERT(pdu.data_iovcnt == 1);
CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xC0FFEE + NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(pdu.data_iov[0].iov_len == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE / 2);
CU_ASSERT(tcp_req.c2h_data_offset == NVMF_TCP_PDU_MAX_C2H_DATA_SIZE * 3);
CU_ASSERT(tqpair.c2h_data_pdu_cnt == 3);
CU_ASSERT(TAILQ_EMPTY(&tqpair.queued_c2h_data_tcp_req));
spdk_poller_unregister(&tqpair.flush_poller);
spdk_thread_exit(thread);
spdk_thread_destroy(thread);
}
static void
test_nvmf_tcp_h2c_data_hdr_handle(void)
{
struct spdk_nvmf_tcp_transport ttransport = {};
struct spdk_nvmf_tcp_qpair tqpair = {};
struct nvme_tcp_pdu pdu = {};
struct spdk_nvmf_tcp_req tcp_req = {};
struct spdk_nvme_tcp_h2c_data_hdr *h2c_data;
TAILQ_INIT(&tqpair.state_queue[TCP_REQUEST_STATE_TRANSFERRING_HOST_TO_CONTROLLER]);
tqpair.maxh2cdata = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE;
/* Set qpair state to make unrelated operations NOP */
tqpair.state = NVME_TCP_QPAIR_STATE_RUNNING;
tqpair.recv_state = NVME_TCP_PDU_RECV_STATE_ERROR;
tcp_req.req.iov[0].iov_base = (void *)0xDEADBEEF;
tcp_req.req.iov[0].iov_len = (NVMF_TCP_PDU_MAX_H2C_DATA_SIZE / 2) * 5;
tcp_req.req.iov[1].iov_base = (void *)0xFEEDBEEF;
tcp_req.req.iov[1].iov_len = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE / 2;
tcp_req.req.iovcnt = 2;
tcp_req.req.length = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE * 3;
tcp_req.req.cmd = (union nvmf_h2c_msg *)&tcp_req.cmd;
tcp_req.req.cmd->nvme_cmd.cid = 1;
tcp_req.req.length = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE * 3;
tcp_req.ttag = 2;
tcp_req.next_expected_r2t_offset = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE * 2;
TAILQ_INSERT_TAIL(&tqpair.state_queue[TCP_REQUEST_STATE_TRANSFERRING_HOST_TO_CONTROLLER],
&tcp_req, state_link);
h2c_data = &pdu.hdr.h2c_data;
h2c_data->cccid = 1;
h2c_data->ttag = 2;
h2c_data->datao = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE * 2;
h2c_data->datal = NVMF_TCP_PDU_MAX_H2C_DATA_SIZE;
spdk_nvmf_tcp_h2c_data_hdr_handle(&ttransport, &tqpair, &pdu);
CU_ASSERT(pdu.data_iovcnt == 2);
CU_ASSERT((uint64_t)pdu.data_iov[0].iov_base == 0xDEADBEEF + NVMF_TCP_PDU_MAX_H2C_DATA_SIZE * 2);
CU_ASSERT(pdu.data_iov[0].iov_len == NVMF_TCP_PDU_MAX_H2C_DATA_SIZE / 2);
CU_ASSERT((uint64_t)pdu.data_iov[1].iov_base == 0xFEEDBEEF);
CU_ASSERT(pdu.data_iov[1].iov_len == NVMF_TCP_PDU_MAX_H2C_DATA_SIZE / 2);
CU_ASSERT(TAILQ_FIRST(&tqpair.state_queue[TCP_REQUEST_STATE_TRANSFERRING_HOST_TO_CONTROLLER]) ==
&tcp_req);
TAILQ_REMOVE(&tqpair.state_queue[TCP_REQUEST_STATE_TRANSFERRING_HOST_TO_CONTROLLER],
&tcp_req, state_link);
}
int main(int argc, char **argv)
{
CU_pSuite suite = NULL;
@ -392,7 +560,9 @@ int main(int argc, char **argv)
if (
CU_add_test(suite, "nvmf_tcp_create", test_nvmf_tcp_create) == NULL ||
CU_add_test(suite, "nvmf_tcp_destroy", test_nvmf_tcp_destroy) == NULL ||
CU_add_test(suite, "nvmf_tcp_poll_group_create", test_nvmf_tcp_poll_group_create) == NULL
CU_add_test(suite, "nvmf_tcp_poll_group_create", test_nvmf_tcp_poll_group_create) == NULL ||
CU_add_test(suite, "nvmf_tcp_send_c2h_data", test_nvmf_tcp_send_c2h_data) == NULL ||
CU_add_test(suite, "nvmf_tcp_h2c_data_hdr_handle", test_nvmf_tcp_h2c_data_hdr_handle) == NULL
) {
CU_cleanup_registry();
return CU_get_error();