Skip to content
Permalink
Browse files
rdma_rxe: Stop passing AV from user space
This patch shows it is possible to replace the current
method used by rdma_rxe to handle UD transport where
user space creates and then passes an rxe_av *av to the
kernel driver as part of each rxe_send_wqe.

Here user space passes the handle created by the call to
ibv_create_ah in the send wqe. The kernel driver uses that
handle to get a pointer to the 'real' rxe_av that was
created in the kernel by the create ah verb.

To do this requires executing code in the driver that mimics
what is done in rdma_core to convert handles to objects.
This is not ideal but gets the job done. It would probably be
better for rdma_core to provide a service that can do this
for software drivers that have to do this.

The alternative (used by the MW code) is to create a driver
private index and pass that back from the create verb to
user space and then have user space use that in the send wqe.

I would like to avoid replicating work already being done by
rdma core by using the handle that already exists. I don't
know the relative performance of the lookup in rdma_core and
the red black tree used by rxe currently.

There is a matching change to provider/rxe.

Signed-off-by: Bob Pearson <rpearson@hpe.com>
  • Loading branch information
Bob Pearson authored and intel-lab-lkp committed Oct 16, 2020
1 parent 9ff9b0d commit f75a164cec539c591ee97d64a896cdebe56c2660
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 10 deletions.
@@ -436,6 +436,7 @@ struct ib_uobject *rdma_lookup_get_uobject(const struct uverbs_api_object *obj,
uverbs_uobject_put(uobj);
return ERR_PTR(ret);
}
EXPORT_SYMBOL(rdma_lookup_get_uobject);

static struct ib_uobject *
alloc_begin_idr_uobject(const struct uverbs_api_object *obj,
@@ -726,6 +727,7 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
/* Pairs with the kref obtained by type->lookup_get */
uverbs_uobject_put(uobj);
}
EXPORT_SYMBOL(rdma_lookup_put_uobject);

void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile)
{
@@ -33,6 +33,8 @@

#include "rxe.h"
#include "rxe_loc.h"
#include "../../core/uverbs.h"
#include "../../core/rdma_core.h"

void rxe_init_av(struct rdma_ah_attr *attr, struct rxe_av *av)
{
@@ -99,13 +101,50 @@ void rxe_av_fill_ip_info(struct rxe_av *av, struct rdma_ah_attr *attr)
av->network_type = rdma_gid_attr_network_type(sgid_attr);
}

static struct ib_ah *get_ah_from_handle(struct rxe_qp *qp, u32 handle)
{
struct ib_uverbs_file *ufile;
struct uverbs_api *uapi;
const struct uverbs_api_object *type;
struct ib_uobject *uobj;

ufile = qp->ibqp.uobject->uevent.uobject.ufile;
uapi = ufile->device->uapi;
type = uapi_get_object(uapi, UVERBS_OBJECT_AH);
if (IS_ERR(type))
return NULL;
uobj = rdma_lookup_get_uobject(type, ufile, (s64)handle,
UVERBS_LOOKUP_READ, NULL);
if (IS_ERR(uobj)) {
pr_warn("unable to lookup ah handle\n");
return NULL;
}

rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_READ);
return uobj->object;
}

struct rxe_av *rxe_get_av(struct rxe_pkt_info *pkt)
{
if (!pkt || !pkt->qp)
struct rxe_qp *qp = pkt->qp;
struct rxe_send_wqe *wqe = pkt->wqe;
u32 handle;
struct ib_ah *ibah;
struct rxe_ah *ah;

if (!pkt || !qp)
return NULL;

if (qp_type(pkt->qp) == IB_QPT_RC || qp_type(pkt->qp) == IB_QPT_UC)
return &pkt->qp->pri_av;
if (qp_type(qp) == IB_QPT_RC || qp_type(qp) == IB_QPT_UC)
return &qp->pri_av;

if (qp->is_user) {
handle = wqe->wr.wr.ud.ah_handle;
ibah = get_ah_from_handle(qp, handle);
} else {
ibah = wqe->wr.wr.ud.ah;
}

return (pkt->wqe) ? &pkt->wqe->av : NULL;
ah = to_rah(ibah);
return &ah->av;
}
@@ -407,6 +407,10 @@ static struct sk_buff *init_req_packet(struct rxe_qp *qp,

/* init skb */
av = rxe_get_av(pkt);
if (!av) {
pr_warn("unable to get av\n");
return NULL;
}
skb = rxe_init_packet(rxe, av, paylen, pkt);
if (unlikely(!skb))
return NULL;
@@ -530,6 +530,7 @@ static void init_send_wr(struct rxe_qp *qp, struct rxe_send_wr *wr,
if (qp_type(qp) == IB_QPT_UD ||
qp_type(qp) == IB_QPT_SMI ||
qp_type(qp) == IB_QPT_GSI) {
wr->wr.ud.ah = ud_wr(ibwr)->ah;
wr->wr.ud.remote_qpn = ud_wr(ibwr)->remote_qpn;
wr->wr.ud.remote_qkey = ud_wr(ibwr)->remote_qkey;
if (qp_type(qp) == IB_QPT_GSI)
@@ -586,11 +587,6 @@ static int init_send_wqe(struct rxe_qp *qp, const struct ib_send_wr *ibwr,

init_send_wr(qp, &wqe->wr, ibwr);

if (qp_type(qp) == IB_QPT_UD ||
qp_type(qp) == IB_QPT_SMI ||
qp_type(qp) == IB_QPT_GSI)
memcpy(&wqe->av, &to_rah(ud_wr(ibwr)->ah)->av, sizeof(wqe->av));

if (unlikely(ibwr->send_flags & IB_SEND_INLINE)) {
p = wqe->dma.inline_data;

@@ -89,6 +89,10 @@ struct rxe_send_wr {
__u32 reserved;
} atomic;
struct {
union {
__aligned_u64 ah_handle;
struct ib_ah *ah;
};
__u32 remote_qpn;
__u32 remote_qkey;
__u16 pkey_index;
@@ -132,7 +136,6 @@ struct rxe_dma_info {

struct rxe_send_wqe {
struct rxe_send_wr wr;
struct rxe_av av;
__u32 status;
__u32 state;
__aligned_u64 iova;

0 comments on commit f75a164

Please sign in to comment.