diff --git a/prov/efa/src/efa_msg.c b/prov/efa/src/efa_msg.c index da43eabfe1e..4957222ae17 100644 --- a/prov/efa/src/efa_msg.c +++ b/prov/efa/src/efa_msg.c @@ -213,7 +213,7 @@ static inline ssize_t efa_post_send(struct efa_base_ep *base_ep, const struct fi struct efa_direct_ope *direct_ope; size_t len, i; size_t iov_count = msg->iov_count; - bool use_inline; + bool use_inline, len_fits_inline, is_hmem; int ret = 0; uintptr_t wr_id; @@ -257,10 +257,6 @@ static inline ssize_t efa_post_send(struct efa_base_ep *base_ep, const struct fi wr_id = (uintptr_t) efa_ctx; } - /* Determine if we should use inline data */ - use_inline = (len <= base_ep->domain->device->efa_attr.inline_buf_size && - (!msg->desc || !efa_mr_is_hmem(msg->desc[0]))); - /* Handle 0-byte send with inline path and 0 SGEs */ if (len == 0) { iov_count = 0; @@ -268,7 +264,11 @@ static inline ssize_t efa_post_send(struct efa_base_ep *base_ep, const struct fi goto post; } - if (use_inline) { + /* Determine if we should use inline data */ + len_fits_inline = len <= base_ep->domain->device->efa_attr.inline_buf_size; + is_hmem = msg->desc && efa_mr_is_hmem(msg->desc[0]); + if (len_fits_inline && !is_hmem) { + use_inline = true; /* Prepare inline data list */ for (i = 0; i < msg->iov_count; i++) { inline_data_list[i].addr = msg->msg_iov[i].iov_base; @@ -281,6 +281,21 @@ static inline ssize_t efa_post_send(struct efa_base_ep *base_ep, const struct fi } } } else { + use_inline = false; + if (flags & FI_INJECT) { + if (!len_fits_inline) + EFA_WARN(FI_LOG_EP_DATA, + "FI_INJECT is requested but message " + "size of %zu exceeds efa-direct " + "inject_msg_size of %zu.\n", len, + base_ep->inject_msg_size); + if (is_hmem) + EFA_WARN(FI_LOG_EP_DATA, + "FI_INJECT is not supported for " + "FI_HMEM memory.\n"); + ret = -FI_EOPNOTSUPP; + goto out_err; + } /* Prepare SGE list */ for (i = 0; i < msg->iov_count; i++) { /* Set TX buffer desc from SGE */ @@ -369,9 +384,6 @@ static ssize_t efa_ep_msg_inject(struct fid_ep *ep_fid, const void *buf, size_t struct fi_msg msg; struct iovec iov; - /* For non-dgram endpoints, msg_prefix_size is 0 */ - assert(len <= base_ep->domain->device->efa_attr.inline_buf_size + base_ep->info->ep_attr->msg_prefix_size); - EFA_SETUP_IOV(iov, buf, len); EFA_SETUP_MSG(msg, &iov, NULL, 1, dest_addr, NULL, 0); @@ -386,9 +398,6 @@ static ssize_t efa_ep_msg_injectdata(struct fid_ep *ep_fid, const void *buf, struct fi_msg msg; struct iovec iov; - /* For non-dgram endpoints, msg_prefix_size is 0 */ - assert(len <= base_ep->domain->device->efa_attr.inline_buf_size + base_ep->info->ep_attr->msg_prefix_size); - EFA_SETUP_IOV(iov, buf, len); EFA_SETUP_MSG(msg, &iov, NULL, 1, dest_addr, NULL, data); diff --git a/prov/efa/test/efa_unit_test_data_path_direct.c b/prov/efa/test/efa_unit_test_data_path_direct.c index 3a5ceca1c85..2ea2e209fdc 100644 --- a/prov/efa/test/efa_unit_test_data_path_direct.c +++ b/prov/efa/test/efa_unit_test_data_path_direct.c @@ -87,9 +87,6 @@ void test_efa_data_path_direct_qp_gen_initialization(struct efa_resource **state base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); qp = base_ep->qp; - /* gen should be non-zero after first QP creation */ - assert_int_not_equal(qp->data_path_direct_qp.gen, 0); - sq_wq = &qp->data_path_direct_qp.sq.wq; rq_wq = &qp->data_path_direct_qp.rq.wq; diff --git a/prov/efa/test/efa_unit_test_msg.c b/prov/efa/test/efa_unit_test_msg.c index 950eb318e97..002a667283b 100644 --- a/prov/efa/test/efa_unit_test_msg.c +++ b/prov/efa/test/efa_unit_test_msg.c @@ -112,7 +112,7 @@ static void test_efa_msg_send_prep(struct efa_resource *resource, g_efa_unit_test_mocks.efa_qp_post_recv = &efa_mock_efa_qp_post_recv_return_mock; /* Mock general QP post send function to save work request IDs */ g_efa_unit_test_mocks.efa_qp_post_send = &efa_mock_efa_qp_post_send_return_mock; - will_return_int_always(efa_mock_efa_qp_post_send_return_mock, 0); + will_return_int_maybe(efa_mock_efa_qp_post_send_return_mock, 0); } void test_efa_msg_fi_send(struct efa_resource **state) @@ -358,3 +358,100 @@ void test_efa_msg_send_0_byte_with_inject_flag(struct efa_resource **state) assert_int_equal(ret, 0); assert_int_equal(g_ibv_submitted_wr_id_cnt, 1); } + +/** + * @brief Verify that fi_sendmsg with FI_INJECT and HMEM desc returns -FI_EOPNOTSUPP + */ +void test_efa_msg_sendmsg_inject_with_hmem_fails(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + struct efa_mr *efa_mr; + struct iovec iov; + void *desc; + int ret; + fi_addr_t addr; + struct fi_msg msg = {0}; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 32); + + desc = fi_mr_desc(send_buff.mr); + efa_mr = (struct efa_mr *)desc; + efa_mr->iface = FI_HMEM_CUDA; + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + + efa_unit_test_construct_msg(&msg, &iov, 1, addr, NULL, 0, &desc); + + ret = fi_sendmsg(resource->ep, &msg, FI_INJECT); + assert_int_equal(ret, -FI_EOPNOTSUPP); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + + efa_unit_test_buff_destruct(&send_buff); +} + +/** + * @brief Verify that fi_sendmsg with FI_INJECT and message larger than + * inline_buf_size returns -FI_EOPNOTSUPP + */ +void test_efa_msg_sendmsg_inject_with_large_msg_fails(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_unit_test_buff send_buff; + struct efa_base_ep *base_ep; + struct iovec iov; + void *desc; + int ret; + fi_addr_t addr; + struct fi_msg msg = {0}; + size_t buf_size; + + test_efa_msg_send_prep(resource, &addr); + + base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); + buf_size = base_ep->domain->device->efa_attr.inline_buf_size + + base_ep->info->ep_attr->msg_prefix_size + 1; + + efa_unit_test_buff_construct(&send_buff, resource, buf_size); + + desc = fi_mr_desc(send_buff.mr); + + iov.iov_base = send_buff.buff; + iov.iov_len = send_buff.size; + + efa_unit_test_construct_msg(&msg, &iov, 1, addr, NULL, 0, &desc); + + ret = fi_sendmsg(resource->ep, &msg, FI_INJECT); + assert_int_equal(ret, -FI_EOPNOTSUPP); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + + efa_unit_test_buff_destruct(&send_buff); +} + +/** + * @brief Verify that fi_inject with message larger than + * inline_buf_size returns -FI_EOPNOTSUPP + */ +void test_efa_msg_inject_with_large_msg_fails(struct efa_resource **state) +{ + struct efa_resource *resource = *state; + struct efa_base_ep *base_ep; + struct efa_unit_test_buff send_buff; + fi_addr_t addr; + size_t buf_size; + int ret; + + test_efa_msg_send_prep(resource, &addr); + efa_unit_test_buff_construct(&send_buff, resource, 32); + base_ep = container_of(resource->ep, struct efa_base_ep, util_ep.ep_fid); + buf_size = base_ep->domain->device->efa_attr.inline_buf_size + + base_ep->info->ep_attr->msg_prefix_size + 1; + + ret = fi_inject(resource->ep, send_buff.buff, buf_size, addr); + assert_int_equal(ret, -FI_EOPNOTSUPP); + assert_int_equal(g_ibv_submitted_wr_id_cnt, 0); + + 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 ecb4dd9e395..dfbd498a5c8 100644 --- a/prov/efa/test/efa_unit_tests.c +++ b/prov/efa/test/efa_unit_tests.c @@ -456,6 +456,9 @@ int main(void) cmocka_unit_test_setup_teardown(test_efa_msg_inject_0_byte, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_msg_injectdata_0_byte, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_msg_send_0_byte_with_inject_flag, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_sendmsg_inject_with_hmem_fails, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_sendmsg_inject_with_large_msg_fails, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), + cmocka_unit_test_setup_teardown(test_efa_msg_inject_with_large_msg_fails, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_msg_send_0_byte_no_shm, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_msg_sendv_0_byte_no_shm, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), cmocka_unit_test_setup_teardown(test_efa_rdm_msg_sendmsg_0_byte_no_shm, efa_unit_test_mocks_setup, efa_unit_test_mocks_teardown), diff --git a/prov/efa/test/efa_unit_tests.h b/prov/efa/test/efa_unit_tests.h index f10f9b24f49..437d8ead69e 100644 --- a/prov/efa/test/efa_unit_tests.h +++ b/prov/efa/test/efa_unit_tests.h @@ -410,6 +410,9 @@ void test_efa_msg_senddata_0_byte(); void test_efa_msg_inject_0_byte(); void test_efa_msg_injectdata_0_byte(); void test_efa_msg_send_0_byte_with_inject_flag(); +void test_efa_msg_sendmsg_inject_with_hmem_fails(); +void test_efa_msg_sendmsg_inject_with_large_msg_fails(); +void test_efa_msg_inject_with_large_msg_fails(); void test_efa_rdm_msg_send_0_byte_with_inject_flag(); void test_efa_rdm_msg_send_0_byte_no_shm(); void test_efa_rdm_msg_sendv_0_byte_no_shm();