diff --git a/debian/ibverbs-providers.symbols b/debian/ibverbs-providers.symbols index cacf6442f..72361bd10 100644 --- a/debian/ibverbs-providers.symbols +++ b/debian/ibverbs-providers.symbols @@ -166,12 +166,14 @@ libefa.so.1 ibverbs-providers #MINVER# EFA_1.0@EFA_1.0 24 EFA_1.1@EFA_1.1 26 EFA_1.2@EFA_1.2 43 + EFA_1.3@EFA_1.3 50 efadv_create_driver_qp@EFA_1.0 24 efadv_create_qp_ex@EFA_1.1 26 efadv_query_device@EFA_1.1 26 efadv_query_ah@EFA_1.1 26 efadv_cq_from_ibv_cq_ex@EFA_1.2 43 efadv_create_cq@EFA_1.2 43 + efadv_query_mr@EFA_1.3 50 libmana.so.1 ibverbs-providers #MINVER# * Build-Depends-Package: libibverbs-dev MANA_1.0@MANA_1.0 41 diff --git a/kernel-headers/rdma/efa-abi.h b/kernel-headers/rdma/efa-abi.h index d94c32f28..701e2d567 100644 --- a/kernel-headers/rdma/efa-abi.h +++ b/kernel-headers/rdma/efa-abi.h @@ -1,12 +1,13 @@ /* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) */ /* - * Copyright 2018-2023 Amazon.com, Inc. or its affiliates. All rights reserved. + * Copyright 2018-2024 Amazon.com, Inc. or its affiliates. All rights reserved. */ #ifndef EFA_ABI_USER_H #define EFA_ABI_USER_H #include +#include /* * Increment this value if any changes that break userspace ABI @@ -134,4 +135,22 @@ struct efa_ibv_ex_query_device_resp { __u32 device_caps; }; +enum { + EFA_QUERY_MR_VALIDITY_RECV_IC_ID = 1 << 0, + EFA_QUERY_MR_VALIDITY_RDMA_READ_IC_ID = 1 << 1, + EFA_QUERY_MR_VALIDITY_RDMA_RECV_IC_ID = 1 << 2, +}; + +enum efa_query_mr_attrs { + EFA_IB_ATTR_QUERY_MR_HANDLE = (1U << UVERBS_ID_NS_SHIFT), + EFA_IB_ATTR_QUERY_MR_RESP_IC_ID_VALIDITY, + EFA_IB_ATTR_QUERY_MR_RESP_RECV_IC_ID, + EFA_IB_ATTR_QUERY_MR_RESP_RDMA_READ_IC_ID, + EFA_IB_ATTR_QUERY_MR_RESP_RDMA_RECV_IC_ID, +}; + +enum efa_mr_methods { + EFA_IB_METHOD_MR_QUERY = (1U << UVERBS_ID_NS_SHIFT), +}; + #endif /* EFA_ABI_USER_H */ diff --git a/providers/efa/CMakeLists.txt b/providers/efa/CMakeLists.txt index 618c8b7af..e999f3b77 100644 --- a/providers/efa/CMakeLists.txt +++ b/providers/efa/CMakeLists.txt @@ -3,7 +3,7 @@ if (ENABLE_LTTNG AND LTTNGUST_FOUND) endif() rdma_shared_provider(efa libefa.map - 1 1.2.${PACKAGE_VERSION} + 1 1.3.${PACKAGE_VERSION} ${TRACE_FILE} efa.c verbs.c diff --git a/providers/efa/efadv.h b/providers/efa/efadv.h index 845822a37..f7f9d43db 100644 --- a/providers/efa/efadv.h +++ b/providers/efa/efadv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ /* - * Copyright 2019-2023 Amazon.com, Inc. or its affiliates. All rights reserved. + * Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All rights reserved. */ #ifndef __EFADV_H__ @@ -94,6 +94,22 @@ static inline int efadv_wc_read_sgid(struct efadv_cq *efadv_cq, return efadv_cq->wc_read_sgid(efadv_cq, sgid); } +enum { + EFADV_MR_ATTR_VALIDITY_RECV_IC_ID = 1 << 0, + EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID = 1 << 1, + EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID = 1 << 2, +}; + +struct efadv_mr_attr { + uint64_t comp_mask; + uint16_t ic_id_validity; + uint16_t recv_ic_id; + uint16_t rdma_read_ic_id; + uint16_t rdma_recv_ic_id; +}; + +int efadv_query_mr(struct ibv_mr *ibvmr, struct efadv_mr_attr *attr, uint32_t inlen); + #ifdef __cplusplus } #endif diff --git a/providers/efa/libefa.map b/providers/efa/libefa.map index 0e7f96f27..eff647d18 100644 --- a/providers/efa/libefa.map +++ b/providers/efa/libefa.map @@ -19,3 +19,8 @@ EFA_1.2 { efadv_create_cq; efadv_wc_read_sgid; } EFA_1.1; + +EFA_1.3 { + global: + efadv_query_mr; +} EFA_1.2; diff --git a/providers/efa/man/CMakeLists.txt b/providers/efa/man/CMakeLists.txt index 335b6e9ef..e7ad126ed 100644 --- a/providers/efa/man/CMakeLists.txt +++ b/providers/efa/man/CMakeLists.txt @@ -4,4 +4,5 @@ rdma_man_pages( efadv_create_qp_ex.3.md efadv_query_ah.3.md efadv_query_device.3.md + efadv_query_mr.3.md ) diff --git a/providers/efa/man/efadv_query_mr.3.md b/providers/efa/man/efadv_query_mr.3.md new file mode 100644 index 000000000..24da994b8 --- /dev/null +++ b/providers/efa/man/efadv_query_mr.3.md @@ -0,0 +1,81 @@ +--- +layout: page +title: EFADV_QUERY_MR +section: 3 +tagline: Verbs +date: 2023-11-13 +header: "EFA Direct Verbs Manual" +footer: efa +--- + +# NAME + +efadv_query_mr - Query EFA specific Memory Region attributes + +# SYNOPSIS + +```c +#include + +int efadv_query_mr(struct ibv_mr *ibvmr, struct efadv_mr_attr *attr, uint32_t inlen); +``` + +# DESCRIPTION + +**efadv_query_mr()** queries device-specific Memory Region attributes. + +Compatibility is handled using the comp_mask and inlen fields. + +```c +struct efadv_mr_attr { + uint64_t comp_mask; + uint16_t ic_id_validity; + uint16_t recv_ic_id; + uint16_t rdma_read_ic_id; + uint16_t rdma_recv_ic_id; +}; +``` + +*inlen* +: In: Size of struct efadv_mr_attr. + +*comp_mask* +: Compatibility mask. + +*ic_id_validity* +: Validity mask of interconnect id fields: + + EFADV_MR_ATTR_VALIDITY_RECV_IC_ID: + recv_ic_id has a valid value. + + EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID: + rdma_read_ic_id has a valid value. + + EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID: + rdma_recv_ic_id has a valid value. + +*recv_ic_id* +: Physical interconnect used by the device to reach the MR for receive operation. + +*rdma_read_ic_id* +: Physical interconnect used by the device to reach the MR for RDMA read operation. + +*rdma_recv_ic_id* +: Physical interconnect used by the device to reach the MR for RDMA write receive. + +# RETURN VALUE + +**efadv_query_mr()** returns 0 on success, or the value of errno on failure +(which indicates the failure reason). + +# SEE ALSO + +**efadv**(7) + +# NOTES + +* Compatibility mask (comp_mask) is an out field and currently has no values. + +# AUTHORS + +Michael Margolin diff --git a/providers/efa/verbs.c b/providers/efa/verbs.c index 093e9eb21..dc7a3431c 100644 --- a/providers/efa/verbs.c +++ b/providers/efa/verbs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause /* - * Copyright 2019-2023 Amazon.com, Inc. or its affiliates. All rights reserved. + * Copyright 2019-2024 Amazon.com, Inc. or its affiliates. All rights reserved. */ #include @@ -279,6 +279,62 @@ struct ibv_mr *efa_reg_mr(struct ibv_pd *ibvpd, void *sva, size_t len, return &mr->vmr.ibv_mr; } +int efadv_query_mr(struct ibv_mr *ibvmr, struct efadv_mr_attr *attr, uint32_t inlen) +{ + uint16_t rdma_read_ic_id = 0; + uint16_t rdma_recv_ic_id = 0; + uint16_t ic_id_validity = 0; + uint16_t recv_ic_id = 0; + int err; + + DECLARE_COMMAND_BUFFER(cmd, + UVERBS_OBJECT_MR, + EFA_IB_METHOD_MR_QUERY, + 5); + + if (!is_efa_dev(ibvmr->context->device)) { + verbs_err(verbs_get_ctx(ibvmr->context), "Not an EFA device\n"); + return EOPNOTSUPP; + } + + if (!vext_field_avail(typeof(*attr), rdma_recv_ic_id, inlen)) { + verbs_err(verbs_get_ctx(ibvmr->context), "Compatibility issues\n"); + return EINVAL; + } + + memset(attr, 0, inlen); + fill_attr_in_obj(cmd, EFA_IB_ATTR_QUERY_MR_HANDLE, ibvmr->handle); + fill_attr_out(cmd, EFA_IB_ATTR_QUERY_MR_RESP_IC_ID_VALIDITY, + &ic_id_validity, sizeof(ic_id_validity)); + fill_attr_out(cmd, EFA_IB_ATTR_QUERY_MR_RESP_RECV_IC_ID, + &recv_ic_id, sizeof(recv_ic_id)); + fill_attr_out(cmd, EFA_IB_ATTR_QUERY_MR_RESP_RDMA_READ_IC_ID, + &rdma_read_ic_id, sizeof(rdma_read_ic_id)); + fill_attr_out(cmd, EFA_IB_ATTR_QUERY_MR_RESP_RDMA_RECV_IC_ID, + &rdma_recv_ic_id, sizeof(rdma_recv_ic_id)); + + err = execute_ioctl(ibvmr->context, cmd); + if (err) { + verbs_err(verbs_get_ctx(ibvmr->context), "Failed to query MR\n"); + return err; + } + + if (ic_id_validity & EFA_QUERY_MR_VALIDITY_RECV_IC_ID) { + attr->recv_ic_id = recv_ic_id; + attr->ic_id_validity |= EFADV_MR_ATTR_VALIDITY_RECV_IC_ID; + } + if (ic_id_validity & EFA_QUERY_MR_VALIDITY_RDMA_READ_IC_ID) { + attr->rdma_read_ic_id = rdma_read_ic_id; + attr->ic_id_validity |= EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID; + } + if (ic_id_validity & EFA_QUERY_MR_VALIDITY_RDMA_RECV_IC_ID) { + attr->rdma_recv_ic_id = rdma_recv_ic_id; + attr->ic_id_validity |= EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID; + } + + return 0; +} + int efa_dereg_mr(struct verbs_mr *vmr) { struct efa_mr *mr = container_of(vmr, struct efa_mr, vmr); diff --git a/pyverbs/providers/efa/efa_enums.pyx b/pyverbs/providers/efa/efa_enums.pyx index 9fe32a95f..b3432f146 100644 --- a/pyverbs/providers/efa/efa_enums.pyx +++ b/pyverbs/providers/efa/efa_enums.pyx @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) -# Copyright 2020-2023 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2020-2024 Amazon.com, Inc. or its affiliates. All rights reserved. #cython: language_level=3 @@ -15,3 +15,8 @@ cdef extern from 'infiniband/efadv.h': cpdef enum: EFADV_WC_EX_WITH_SGID + + cpdef enum: + EFADV_MR_ATTR_VALIDITY_RECV_IC_ID + EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID + EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID diff --git a/pyverbs/providers/efa/efadv.pxd b/pyverbs/providers/efa/efadv.pxd index 9fa488ac0..12e11f8ce 100644 --- a/pyverbs/providers/efa/efadv.pxd +++ b/pyverbs/providers/efa/efadv.pxd @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) -# Copyright 2020-2022 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2020-2024 Amazon.com, Inc. or its affiliates. All rights reserved. #cython: language_level=3 @@ -46,3 +46,7 @@ cdef class EfaCQ(CQEX): cdef class EfaDVCQInitAttr(PyverbsObject): cdef dv.efadv_cq_init_attr cq_init_attr + + +cdef class EfaDVMRAttr(PyverbsObject): + cdef dv.efadv_mr_attr mr_attr diff --git a/pyverbs/providers/efa/efadv.pyx b/pyverbs/providers/efa/efadv.pyx index 1cd8c6ced..bf8cdba4e 100644 --- a/pyverbs/providers/efa/efadv.pyx +++ b/pyverbs/providers/efa/efadv.pyx @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) -# Copyright 2020-2023 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2020-2024 Amazon.com, Inc. or its affiliates. All rights reserved. cimport pyverbs.providers.efa.efadv_enums as dve cimport pyverbs.providers.efa.libefa as dv @@ -11,6 +11,7 @@ import pyverbs.enums as e cimport pyverbs.libibverbs as v from pyverbs.pd cimport PD from pyverbs.qp cimport QP, QPEx, QPInitAttr, QPInitAttrEx +from pyverbs.mr cimport MR def dev_cap_to_str(flags): @@ -250,3 +251,54 @@ cdef class EfaCQ(CQEX): if err: return None return sgid + + +cdef class EfaDVMRAttr(PyverbsObject): + """ + Represents efadv_mr_attr struct, which exposes efa-specific MR attributes, + reported by efadv_query_mr. + """ + @property + def comp_mask(self): + return self.mr_attr.comp_mask + + @property + def ic_id_validity(self): + return self.mr_attr.ic_id_validity + + @property + def recv_ic_id(self): + return self.mr_attr.recv_ic_id + + @property + def rdma_read_ic_id(self): + return self.mr_attr.rdma_read_ic_id + + @property + def rdma_recv_ic_id(self): + return self.mr_attr.rdma_recv_ic_id + + def __str__(self): + print_format = '{:28}: {:<20}\n' + return print_format.format('comp_mask', self.mr_attr.comp_mask) + \ + print_format.format('Interconnect id validity', self.mr_attr.ic_id_validity) + \ + print_format.format('Receive interconnect id', self.mr_attr.recv_ic_id) + \ + print_format.format('RDMA read interconnect id', self.mr_attr.rdma_read_ic_id) + \ + print_format.format('RDMA receive interconnect id', self.mr_attr.rdma_recv_ic_id) + + +cdef class EfaMR(MR): + """ + Represents an MR with EFA specific properties + """ + def query(self): + """ + Queries the MR for device-specific attributes. + :return: An EfaDVMRAttr containing the attributes. + """ + mr_attr = EfaDVMRAttr() + rc = dv.efadv_query_mr(self.mr, &mr_attr.mr_attr, sizeof(mr_attr.mr_attr)) + if rc: + raise PyverbsRDMAError(f'Failed to query EFA MR', rc) + + return mr_attr diff --git a/pyverbs/providers/efa/efadv_enums.pxd b/pyverbs/providers/efa/efadv_enums.pxd index 9d65ade30..219f0db1d 100644 --- a/pyverbs/providers/efa/efadv_enums.pxd +++ b/pyverbs/providers/efa/efadv_enums.pxd @@ -16,3 +16,8 @@ cdef extern from 'infiniband/efadv.h': cpdef enum: EFADV_WC_EX_WITH_SGID + + cpdef enum: + EFADV_MR_ATTR_VALIDITY_RECV_IC_ID + EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID + EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID diff --git a/pyverbs/providers/efa/libefa.pxd b/pyverbs/providers/efa/libefa.pxd index 8736e1889..ca6471a84 100644 --- a/pyverbs/providers/efa/libefa.pxd +++ b/pyverbs/providers/efa/libefa.pxd @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) -# Copyright 2020-2022 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2020-2024 Amazon.com, Inc. or its affiliates. All rights reserved. from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t cimport pyverbs.libibverbs as v @@ -35,6 +35,13 @@ cdef extern from 'infiniband/efadv.h': cdef struct efadv_cq: uint64_t comp_mask; + cdef struct efadv_mr_attr: + uint64_t comp_mask; + uint16_t ic_id_validity; + uint16_t recv_ic_id; + uint16_t rdma_read_ic_id; + uint16_t rdma_recv_ic_id; + int efadv_query_device(v.ibv_context *ibvctx, efadv_device_attr *attrs, uint32_t inlen) int efadv_query_ah(v.ibv_ah *ibvah, efadv_ah_attr *attr, @@ -51,3 +58,4 @@ cdef extern from 'infiniband/efadv.h': uint32_t inlen) efadv_cq *efadv_cq_from_ibv_cq_ex(v.ibv_cq_ex *ibvcqx) int efadv_wc_read_sgid(efadv_cq *efadv_cq, v.ibv_gid *sgid) + int efadv_query_mr(v.ibv_mr *ibvmr, efadv_mr_attr *attr, uint32_t inlen) diff --git a/tests/test_efadv.py b/tests/test_efadv.py index 7a74a0773..901ddefe1 100644 --- a/tests/test_efadv.py +++ b/tests/test_efadv.py @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) -# Copyright 2020-2023 Amazon.com, Inc. or its affiliates. All rights reserved. +# Copyright 2020-2024 Amazon.com, Inc. or its affiliates. All rights reserved. """ Test module for efa direct-verbs. """ @@ -152,3 +152,24 @@ def test_dv_cq_ex_with_sgid(self): u.send(self.client, sg, e.IBV_WR_SEND, new_send=True, qp_idx=0, ah=ah_client) u.poll_cq_ex(self.client.cq) u.poll_cq_ex(self.server.cq, sgid=self.server.remote_gid) + + +class EfaMRTest(EfaAPITestCase): + """ + Test various functionalities of the EfaMR class. + """ + def test_efadv_query_mr(self): + with PD(self.ctx) as pd: + try: + mr = efa.EfaMR(pd, 16, e.IBV_ACCESS_LOCAL_WRITE) + mr_attrs = mr.query() + if self.config['verbosity']: + print(f'\n{mr_attrs}') + + assert(mr_attrs.ic_id_validity & ~(efa_e.EFADV_MR_ATTR_VALIDITY_RECV_IC_ID | + efa_e.EFADV_MR_ATTR_VALIDITY_RDMA_READ_IC_ID | + efa_e.EFADV_MR_ATTR_VALIDITY_RDMA_RECV_IC_ID) == 0) + except PyverbsRDMAError as ex: + if ex.error_code in [errno.EOPNOTSUPP, errno.ENOTTY, errno.EPROTONOSUPPORT]: + raise unittest.SkipTest(f'Query MR not supported, errno={ex.error_code}') + raise ex