Skip to content

Commit f17df3b

Browse files
Sean Heftyrolandd
authored andcommitted
RDMA/cma: Add support for AF_IB to rdma_resolve_addr()
Allow the user to specify the remote address using AF_IB format. When AF_IB is used, the remote address simply needs to be recorded, and no resolution using ARP is done. The local address may still need to be matched with a local IB device. Signed-off-by: Sean Hefty <[email protected]> Signed-off-by: Roland Dreier <[email protected]>
1 parent 4ae7152 commit f17df3b

File tree

1 file changed

+100
-6
lines changed
  • drivers/infiniband/core

1 file changed

+100
-6
lines changed

drivers/infiniband/core/cma.c

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,61 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
438438
return ret;
439439
}
440440

441+
/*
442+
* Select the source IB device and address to reach the destination IB address.
443+
*/
444+
static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
445+
{
446+
struct cma_device *cma_dev, *cur_dev;
447+
struct sockaddr_ib *addr;
448+
union ib_gid gid, sgid, *dgid;
449+
u16 pkey, index;
450+
u8 port, p;
451+
int i;
452+
453+
cma_dev = NULL;
454+
addr = (struct sockaddr_ib *) cma_dst_addr(id_priv);
455+
dgid = (union ib_gid *) &addr->sib_addr;
456+
pkey = ntohs(addr->sib_pkey);
457+
458+
list_for_each_entry(cur_dev, &dev_list, list) {
459+
if (rdma_node_get_transport(cur_dev->device->node_type) != RDMA_TRANSPORT_IB)
460+
continue;
461+
462+
for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
463+
if (ib_find_cached_pkey(cur_dev->device, p, pkey, &index))
464+
continue;
465+
466+
for (i = 0; !ib_get_cached_gid(cur_dev->device, p, i, &gid); i++) {
467+
if (!memcmp(&gid, dgid, sizeof(gid))) {
468+
cma_dev = cur_dev;
469+
sgid = gid;
470+
port = p;
471+
goto found;
472+
}
473+
474+
if (!cma_dev && (gid.global.subnet_prefix ==
475+
dgid->global.subnet_prefix)) {
476+
cma_dev = cur_dev;
477+
sgid = gid;
478+
port = p;
479+
}
480+
}
481+
}
482+
}
483+
484+
if (!cma_dev)
485+
return -ENODEV;
486+
487+
found:
488+
cma_attach_to_dev(id_priv, cma_dev);
489+
id_priv->id.port_num = port;
490+
addr = (struct sockaddr_ib *) cma_src_addr(id_priv);
491+
memcpy(&addr->sib_addr, &sgid, sizeof sgid);
492+
cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr);
493+
return 0;
494+
}
495+
441496
static void cma_deref_id(struct rdma_id_private *id_priv)
442497
{
443498
if (atomic_dec_and_test(&id_priv->refcount))
@@ -2101,14 +2156,48 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv)
21012156
return ret;
21022157
}
21032158

2159+
static int cma_resolve_ib_addr(struct rdma_id_private *id_priv)
2160+
{
2161+
struct cma_work *work;
2162+
int ret;
2163+
2164+
work = kzalloc(sizeof *work, GFP_KERNEL);
2165+
if (!work)
2166+
return -ENOMEM;
2167+
2168+
if (!id_priv->cma_dev) {
2169+
ret = cma_resolve_ib_dev(id_priv);
2170+
if (ret)
2171+
goto err;
2172+
}
2173+
2174+
rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, (union ib_gid *)
2175+
&(((struct sockaddr_ib *) &id_priv->id.route.addr.dst_addr)->sib_addr));
2176+
2177+
work->id = id_priv;
2178+
INIT_WORK(&work->work, cma_work_handler);
2179+
work->old_state = RDMA_CM_ADDR_QUERY;
2180+
work->new_state = RDMA_CM_ADDR_RESOLVED;
2181+
work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
2182+
queue_work(cma_wq, &work->work);
2183+
return 0;
2184+
err:
2185+
kfree(work);
2186+
return ret;
2187+
}
2188+
21042189
static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
21052190
struct sockaddr *dst_addr)
21062191
{
21072192
if (!src_addr || !src_addr->sa_family) {
21082193
src_addr = (struct sockaddr *) &id->route.addr.src_addr;
2109-
if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
2194+
src_addr->sa_family = dst_addr->sa_family;
2195+
if (dst_addr->sa_family == AF_INET6) {
21102196
((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
21112197
((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
2198+
} else if (dst_addr->sa_family == AF_IB) {
2199+
((struct sockaddr_ib *) src_addr)->sib_pkey =
2200+
((struct sockaddr_ib *) dst_addr)->sib_pkey;
21122201
}
21132202
}
21142203
return rdma_bind_addr(id, src_addr);
@@ -2135,12 +2224,17 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
21352224

21362225
atomic_inc(&id_priv->refcount);
21372226
memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
2138-
if (cma_any_addr(dst_addr))
2227+
if (cma_any_addr(dst_addr)) {
21392228
ret = cma_resolve_loopback(id_priv);
2140-
else
2141-
ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv),
2142-
dst_addr, &id->route.addr.dev_addr,
2143-
timeout_ms, addr_handler, id_priv);
2229+
} else {
2230+
if (dst_addr->sa_family == AF_IB) {
2231+
ret = cma_resolve_ib_addr(id_priv);
2232+
} else {
2233+
ret = rdma_resolve_ip(&addr_client, cma_src_addr(id_priv),
2234+
dst_addr, &id->route.addr.dev_addr,
2235+
timeout_ms, addr_handler, id_priv);
2236+
}
2237+
}
21442238
if (ret)
21452239
goto err;
21462240

0 commit comments

Comments
 (0)