From ebca5ecc8a85991ff8f4d29bbd2cade382995055 Mon Sep 17 00:00:00 2001 From: Jessie Yang Date: Fri, 13 Dec 2024 15:57:51 -0800 Subject: [PATCH] prov/efa: Add unit tests for efa_rma Signed-off-by: Jessie Yang --- prov/efa/Makefile.include | 3 +- prov/efa/test/efa_unit_test_common.c | 16 ++ prov/efa/test/efa_unit_test_mocks.c | 15 ++ prov/efa/test/efa_unit_test_mocks.h | 7 + prov/efa/test/efa_unit_test_rma.c | 273 +++++++++++++++++++++++++++ prov/efa/test/efa_unit_tests.c | 9 + prov/efa/test/efa_unit_tests.h | 15 ++ 7 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 prov/efa/test/efa_unit_test_rma.c diff --git a/prov/efa/Makefile.include b/prov/efa/Makefile.include index 6be0ad452f2..980f3430644 100644 --- a/prov/efa/Makefile.include +++ b/prov/efa/Makefile.include @@ -149,7 +149,8 @@ nodist_prov_efa_test_efa_unit_test_SOURCES = \ prov/efa/test/efa_unit_test_mr.c \ prov/efa/test/efa_unit_test_rdm_peer.c \ prov/efa/test/efa_unit_test_pke.c \ - prov/efa/test/efa_unit_test_msg.c + prov/efa/test/efa_unit_test_msg.c \ + prov/efa/test/efa_unit_test_rma.c efa_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/prov/efa/test $(cmocka_CPPFLAGS) diff --git a/prov/efa/test/efa_unit_test_common.c b/prov/efa/test/efa_unit_test_common.c index 772bd0608c9..47cae69f20b 100644 --- a/prov/efa/test/efa_unit_test_common.c +++ b/prov/efa/test/efa_unit_test_common.c @@ -35,6 +35,22 @@ void efa_unit_test_construct_tmsg(struct fi_msg_tagged *tmsg, struct iovec *iov, tmsg->ignore = ignore; } +void efa_unit_test_construct_msg_rma(struct fi_msg_rma *msg, struct iovec *iov, + void **desc, size_t iov_count, + fi_addr_t addr, struct fi_rma_iov *rma_iov, + size_t rma_iov_count, void *context, + uint64_t data) +{ + msg->msg_iov = iov; + msg->desc = desc; + msg->iov_count = iov_count; + msg->addr = addr; + msg->rma_iov = rma_iov; + msg->rma_iov_count = rma_iov_count; + msg->context = context; + msg->data = data; +} + struct fi_info *efa_unit_test_alloc_hints(enum fi_ep_type ep_type) { struct fi_info *hints; diff --git a/prov/efa/test/efa_unit_test_mocks.c b/prov/efa/test/efa_unit_test_mocks.c index 20dd538602c..d05ded33e0f 100644 --- a/prov/efa/test/efa_unit_test_mocks.c +++ b/prov/efa/test/efa_unit_test_mocks.c @@ -219,6 +219,21 @@ int efa_mock_ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, return mock(); } +void efa_mock_ibv_wr_rdma_read_save_wr(struct ibv_qp_ex *qp, uint32_t rkey, + uint64_t remote_addr) +{ + g_ibv_submitted_wr_id_vec[g_ibv_submitted_wr_id_cnt] = (void *)qp->wr_id; + g_ibv_submitted_wr_id_cnt++; +} + +void efa_mock_ibv_wr_rdma_write_imm_save_wr(struct ibv_qp_ex *qp, uint32_t rkey, + uint64_t remote_addr, + __be32 imm_data) +{ + g_ibv_submitted_wr_id_vec[g_ibv_submitted_wr_id_cnt] = (void *) qp->wr_id; + g_ibv_submitted_wr_id_cnt++; +} + struct efa_unit_test_mocks g_efa_unit_test_mocks = { .local_host_id = 0, .peer_host_id = 0, diff --git a/prov/efa/test/efa_unit_test_mocks.h b/prov/efa/test/efa_unit_test_mocks.h index 7143869a2fa..3c256a24075 100644 --- a/prov/efa/test/efa_unit_test_mocks.h +++ b/prov/efa/test/efa_unit_test_mocks.h @@ -98,6 +98,13 @@ bool efa_mock_efa_device_support_unsolicited_write_recv(void); int efa_mock_ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr); +void efa_mock_ibv_wr_rdma_read_save_wr(struct ibv_qp_ex *qp, uint32_t rkey, + uint64_t remote_addr); + +void efa_mock_ibv_wr_rdma_write_imm_save_wr(struct ibv_qp_ex *qp, uint32_t rkey, + uint64_t remote_addr, + __be32 imm_data); + struct efa_unit_test_mocks { uint64_t local_host_id; diff --git a/prov/efa/test/efa_unit_test_rma.c b/prov/efa/test/efa_unit_test_rma.c new file mode 100644 index 00000000000..40be70ec219 --- /dev/null +++ b/prov/efa/test/efa_unit_test_rma.c @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0-only */ +/* SPDX-FileCopyrightText: Copyright Amazon.com, Inc. or its affiliates. All + * rights reserved. */ + +#include "efa_unit_tests.h" +#include "ofi_util.h" + +extern struct fi_ops_rma efa_rma_ops; + +static void test_efa_rma_prep(struct efa_resource *resource, fi_addr_t *addr) +{ + struct ibv_qp_ex *ibv_qpx; + struct efa_ep_addr raw_addr; + struct efa_base_ep *base_ep; + size_t raw_addr_len = sizeof(raw_addr); + int ret; + + efa_unit_test_resource_construct(resource, FI_EP_RDM); + resource->ep->rma = &efa_rma_ops; + + base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); + ibv_qpx = base_ep->qp->ibv_qp_ex; + ibv_qpx->wr_start = &efa_mock_ibv_wr_start_no_op; + /* this mock will save the send work request (wr) in a global list */ + ibv_qpx->wr_rdma_read = &efa_mock_ibv_wr_rdma_read_save_wr; + ibv_qpx->wr_rdma_write = &efa_mock_ibv_wr_rdma_write_save_wr; + ibv_qpx->wr_rdma_write_imm = &efa_mock_ibv_wr_rdma_write_imm_save_wr; + ibv_qpx->wr_set_inline_data_list = + &efa_mock_ibv_wr_set_inline_data_list_no_op; + ibv_qpx->wr_set_sge_list = &efa_mock_ibv_wr_set_sge_list_no_op; + ibv_qpx->wr_set_ud_addr = &efa_mock_ibv_wr_set_ud_addr_no_op; + ibv_qpx->wr_complete = &efa_mock_ibv_wr_complete_no_op; + + ret = fi_getname(&resource->ep->fid, &raw_addr, &raw_addr_len); + assert_int_equal(ret, 0); + raw_addr.qpn = 1; + raw_addr.qkey = 0x1234; + ret = fi_av_insert(resource->av, &raw_addr, 1, addr, 0 /* flags */, + NULL /* context */); + assert_int_equal(ret, 1); +} + +void test_efa_rma_read(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + fi_addr_t src_addr; + void *desc; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &src_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(local_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_read(resource->ep, local_buff.buff, local_buff.size, desc, + src_addr, remote_addr, remote_key, NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_readv(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + struct iovec iov; + fi_addr_t src_addr; + void *desc; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &src_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + iov.iov_base = local_buff.buff; + iov.iov_len = local_buff.size; + desc = fi_mr_desc(local_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_readv(resource->ep, &iov, &desc, 1, src_addr, remote_addr, + remote_key, NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_readmsg(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + struct iovec iov; + struct fi_msg_rma msg = {0}; + struct fi_rma_iov rma_iov; + fi_addr_t src_addr; + void *desc; + int ret; + + test_efa_rma_prep(resource, &src_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + iov.iov_base = local_buff.buff; + iov.iov_len = local_buff.size; + desc = fi_mr_desc(local_buff.mr); + rma_iov.len = local_buff.size; + rma_iov.addr = 0x87654321; + rma_iov.key = 123456; + efa_unit_test_construct_msg_rma(&msg, &iov, &desc, 1, src_addr, + &rma_iov, 1, NULL, 0); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_readmsg(resource->ep, &msg, 0); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_write(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + fi_addr_t dest_addr; + void *desc; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(local_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_write(resource->ep, local_buff.buff, local_buff.size, desc, + dest_addr, remote_addr, remote_key, NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_writev(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + struct iovec iov; + fi_addr_t dest_addr; + void *desc; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + iov.iov_base = local_buff.buff; + iov.iov_len = local_buff.size; + desc = fi_mr_desc(local_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_writev(resource->ep, &iov, &desc, 1, dest_addr, remote_addr, + remote_key, NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_writemsg(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + struct iovec iov; + struct fi_msg_rma msg = {0}; + struct fi_rma_iov rma_iov; + fi_addr_t dest_addr; + void *desc; + int ret; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + iov.iov_base = local_buff.buff; + iov.iov_len = local_buff.size; + desc = fi_mr_desc(local_buff.mr); + rma_iov.len = local_buff.size; + rma_iov.addr = 0x87654321; + rma_iov.key = 123456; + efa_unit_test_construct_msg_rma(&msg, &iov, &desc, 1, dest_addr, &rma_iov, + 1, NULL, 0); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_writemsg(resource->ep, &msg, 0); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_writedata(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + fi_addr_t dest_addr; + void *desc; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(local_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_writedata(resource->ep, local_buff.buff, local_buff.size, desc, + 0, dest_addr, remote_addr, remote_key, + NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_inject_write(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + fi_addr_t dest_addr; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 32 /* buff_size */); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_inject_write(resource->ep, local_buff.buff, local_buff.size, + dest_addr, remote_addr, remote_key); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} + +void test_efa_rma_inject_writedata(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff local_buff; + fi_addr_t dest_addr; + int ret; + uint64_t remote_addr = 0x87654321; + uint64_t remote_key = 123456; + + test_efa_rma_prep(resource, &dest_addr); + efa_unit_test_buff_construct(&local_buff, resource, 32 /* buff_size */); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_inject_writedata(resource->ep, local_buff.buff, + local_buff.size, 0, dest_addr, remote_addr, + remote_key); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&local_buff); +} diff --git a/prov/efa/test/efa_unit_tests.c b/prov/efa/test/efa_unit_tests.c index 1bdcda622a2..8330e650f5f 100644 --- a/prov/efa/test/efa_unit_tests.c +++ b/prov/efa/test/efa_unit_tests.c @@ -217,6 +217,15 @@ int main(void) cmocka_unit_test_setup_teardown(test_efa_msg_fi_senddata, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_msg_fi_inject, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_msg_fi_injectdata, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_read, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_readv, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_readmsg, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_write, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_writev, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_writemsg, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_writedata, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_inject_write, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_rma_inject_writedata, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), }; cmocka_set_message_output(CM_OUTPUT_XML); diff --git a/prov/efa/test/efa_unit_tests.h b/prov/efa/test/efa_unit_tests.h index 1a75a5cbfcf..246dd563a42 100644 --- a/prov/efa/test/efa_unit_tests.h +++ b/prov/efa/test/efa_unit_tests.h @@ -60,6 +60,12 @@ void efa_unit_test_construct_tmsg(struct fi_msg_tagged *tmsg, struct iovec *iov, void **desc, uint64_t tag, uint64_t ignore); +void efa_unit_test_construct_msg_rma(struct fi_msg_rma *msg, struct iovec *iov, + void **desc, size_t iov_count, + fi_addr_t addr, struct fi_rma_iov *rma_iov, + size_t rma_iov_count, void *context, + uint64_t data); + void new_temp_file(char *template, size_t len); struct efa_unit_test_buff { @@ -231,6 +237,15 @@ void test_efa_msg_fi_sendmsg(); void test_efa_msg_fi_senddata(); void test_efa_msg_fi_inject(); void test_efa_msg_fi_injectdata(); +void test_efa_rma_read(); +void test_efa_rma_readv(); +void test_efa_rma_readmsg(); +void test_efa_rma_write(); +void test_efa_rma_writev(); +void test_efa_rma_writemsg(); +void test_efa_rma_writedata(); +void test_efa_rma_inject_write(); +void test_efa_rma_inject_writedata(); static inline int efa_unit_test_get_dlist_length(struct dlist_entry *head)