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:
parent
3184884f9d
commit
16b8519660
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user