diff --git a/prov/efa/Makefile.include b/prov/efa/Makefile.include index 81e0fab0aed..6be0ad452f2 100644 --- a/prov/efa/Makefile.include +++ b/prov/efa/Makefile.include @@ -148,7 +148,8 @@ nodist_prov_efa_test_efa_unit_test_SOURCES = \ prov/efa/test/efa_unit_test_runt.c \ 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_pke.c \ + prov/efa/test/efa_unit_test_msg.c efa_CPPFLAGS += -I$(top_srcdir)/include -I$(top_srcdir)/prov/efa/test $(cmocka_CPPFLAGS) diff --git a/prov/efa/test/efa_unit_test_mocks.c b/prov/efa/test/efa_unit_test_mocks.c index 75dd2bad732..20dd538602c 100644 --- a/prov/efa/test/efa_unit_test_mocks.c +++ b/prov/efa/test/efa_unit_test_mocks.c @@ -88,6 +88,12 @@ void efa_mock_ibv_wr_send_verify_handshake_pkt_local_host_id_and_save_wr(struct return efa_mock_ibv_wr_send_save_wr(qp); } +void efa_mock_ibv_wr_send_imm_save_wr(struct ibv_qp_ex *qp, __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++; +} + void efa_mock_ibv_wr_set_inline_data_list_no_op(struct ibv_qp_ex *qp, size_t num_buf, const struct ibv_data_buf *buf_list) @@ -207,6 +213,12 @@ bool efa_mock_efa_device_support_unsolicited_write_recv() return mock(); } +int efa_mock_ibv_post_recv(struct ibv_qp *qp, struct ibv_recv_wr *wr, + struct ibv_recv_wr **bad_wr) +{ + return mock(); +} + 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 3e764c91fb1..7143869a2fa 100644 --- a/prov/efa/test/efa_unit_test_mocks.h +++ b/prov/efa/test/efa_unit_test_mocks.h @@ -74,6 +74,8 @@ uint32_t efa_mock_ibv_read_wc_flags_return_mock(struct ibv_cq_ex *current); bool efa_mock_efadv_wc_is_unsolicited(struct efadv_cq *efadv_cq); +void efa_mock_ibv_wr_send_imm_save_wr(struct ibv_qp_ex *qp, __be32 imm_data); + ssize_t __real_ofi_copy_from_hmem_iov(void *dest, size_t size, enum fi_hmem_iface hmem_iface, uint64_t device, const struct iovec *hmem_iov, @@ -93,6 +95,9 @@ int efa_mock_efa_rdm_pke_read_return_mock(struct efa_rdm_ope *ope); 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); + struct efa_unit_test_mocks { uint64_t local_host_id; diff --git a/prov/efa/test/efa_unit_test_msg.c b/prov/efa/test/efa_unit_test_msg.c new file mode 100644 index 00000000000..81781aeb6d6 --- /dev/null +++ b/prov/efa/test/efa_unit_test_msg.c @@ -0,0 +1,267 @@ +/* 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_msg efa_msg_ops; + +static void test_efa_msg_recv_prep(struct efa_resource *resource, + fi_addr_t *addr) +{ + struct ibv_qp *ibv_qp; + 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->msg = &efa_msg_ops; + + base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); + ibv_qp = base_ep->qp->ibv_qp; + ibv_qp->context->ops.post_recv = &efa_mock_ibv_post_recv; + will_return(efa_mock_ibv_post_recv, 0); + + 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_msg_fi_recv(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + int ret; + void *desc; + + test_efa_msg_recv_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(send_buff.mr); + + ret = fi_recv(resource->ep, send_buff.buff, send_buff.size, desc, addr, + NULL /* context */); + assert_int_equal(ret, 0); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_recvv(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + struct iovec iov; + fi_addr_t addr; + int ret; + void *desc; + + test_efa_msg_recv_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + desc = fi_mr_desc(send_buff.mr); + + ret = fi_recvv(resource->ep, &iov, &desc, 1, addr, NULL /* context */); + assert_int_equal(ret, 0); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_recvmsg(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + int ret; + void *desc; + struct iovec iov; + struct fi_msg msg = {0}; + + test_efa_msg_recv_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + desc = fi_mr_desc(send_buff.mr); + efa_unit_test_construct_msg(&msg, &iov, 1, addr, NULL, 0, &desc); + + ret = fi_recvmsg(resource->ep, &msg, 0); + assert_int_equal(ret, 0); + + efa_unit_test_buff_destruct(&send_buff); +} + +static void test_efa_msg_send_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->msg = &efa_msg_ops; + + base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); + ibv_qpx = base_ep->qp->ibv_qp_ex; + + 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); + + 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_send = &efa_mock_ibv_wr_send_save_wr; + ibv_qpx->wr_send_imm = &efa_mock_ibv_wr_send_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; +} + +void test_efa_msg_fi_send(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + void *desc; + int ret; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(send_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_send(resource->ep, send_buff.buff, send_buff.size, desc, addr, + NULL /* context */); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_sendv(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + struct iovec iov; + void *desc; + int ret; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + desc = fi_mr_desc(send_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_sendv(resource->ep, &iov, &desc, 1, addr, NULL); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_sendmsg(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + struct iovec iov; + void *desc; + int ret; + struct fi_msg msg = {0}; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + desc = fi_mr_desc(send_buff.mr); + + efa_unit_test_construct_msg(&msg, &iov, 1, addr, NULL, 0, &desc); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_sendmsg(resource->ep, &msg, 0); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_senddata(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + void *desc; + int ret; + uint64_t data = 0x1234567890ABCDEF; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 4096 /* buff_size */); + + desc = fi_mr_desc(send_buff.mr); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_senddata(resource->ep, send_buff.buff, send_buff.size, desc, + data, addr, NULL); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_inject(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + int ret; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 32); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_inject(resource->ep, send_buff.buff, send_buff.size, addr); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} + +void test_efa_msg_fi_injectdata(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + int ret; + uint64_t data = 0x1234567890ABCDEF; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 32); + + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + ret = fi_injectdata(resource->ep, send_buff.buff, send_buff.size, data, + addr); + assert_int_equal(ret, 0); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); + + efa_unit_test_buff_destruct(&send_buff); +} diff --git a/prov/efa/test/efa_unit_tests.c b/prov/efa/test/efa_unit_tests.c index 2ada3f5d820..1bdcda622a2 100644 --- a/prov/efa/test/efa_unit_tests.c +++ b/prov/efa/test/efa_unit_tests.c @@ -208,6 +208,15 @@ int main(void) cmocka_unit_test_setup_teardown(test_efa_rdm_peer_keep_pke_in_overflow_list, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_peer_append_overflow_pke_to_recvwin, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_pke_handle_longcts_rtm_send_completion, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_recv, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_recvv, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_recvmsg, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_send, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_sendv, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_fi_sendmsg, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + 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_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 96958b0255f..1a75a5cbfcf 100644 --- a/prov/efa/test/efa_unit_tests.h +++ b/prov/efa/test/efa_unit_tests.h @@ -222,6 +222,15 @@ void test_efa_rdm_peer_move_overflow_pke_to_recvwin(); void test_efa_rdm_peer_keep_pke_in_overflow_list(); void test_efa_rdm_peer_append_overflow_pke_to_recvwin(); void test_efa_rdm_pke_handle_longcts_rtm_send_completion(); +void test_efa_msg_fi_recv(); +void test_efa_msg_fi_recvv(); +void test_efa_msg_fi_recvmsg(); +void test_efa_msg_fi_send(); +void test_efa_msg_fi_sendv(); +void test_efa_msg_fi_sendmsg(); +void test_efa_msg_fi_senddata(); +void test_efa_msg_fi_inject(); +void test_efa_msg_fi_injectdata(); static inline int efa_unit_test_get_dlist_length(struct dlist_entry *head)