[openib-general] [PATCH 1/3] RDMA CM: fix resolve_addr() failing if bind_addr() does not bind to a device
Sean Hefty
sean.hefty at intel.com
Thu Mar 30 18:00:00 PST 2006
If the user calls rdma_bind_addr(), but specifies either a zero IP address,
or the loopback address, bind will succeed, but the cm_id will not attach
to an RDMA device. This will result in a failure if rdma_resolve_addr()
is called. Fix rdma_resolve_addr(), so that it handles this condition
properly.
To correct this, rdma_resolve_addr() calls rdma_bind_addr() if it has not
already been called by the user. A minor correction to rdma_bind_addr()
was made to better handle binding to a zero or loopback IP address.
Signed-off-by: Sean Hefty <sean.hefty at intel.com>
---
This fix should make it easier to assign port numbers to cm_id's, since
rdma_bind_addr() will be called for all cm_id's.
Index: cma.c
===================================================================
--- cma.c (revision 6063)
+++ cma.c (working copy)
@@ -443,14 +443,13 @@ int rdma_init_qp_attr(struct rdma_cm_id
}
EXPORT_SYMBOL(rdma_init_qp_attr);
-static inline int cma_any_addr(struct sockaddr *addr)
+static inline int cma_zero_addr(struct sockaddr *addr)
{
struct in6_addr *ip6;
- if (addr->sa_family == AF_INET) {
- __u32 s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
- return ZERONET(s_addr) || LOOPBACK(s_addr);
- } else {
+ if (addr->sa_family == AF_INET)
+ return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+ else {
ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
ip6->s6_addr32[3] | ip6->s6_addr32[4]) == 0;
@@ -462,6 +461,11 @@ static inline int cma_loopback_addr(stru
return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
}
+static inline int cma_any_addr(struct sockaddr *addr)
+{
+ return cma_zero_addr(addr) || cma_loopback_addr(addr);
+}
+
static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
u8 *ip_ver, __u16 *port,
union cma_ip_addr **src, union cma_ip_addr **dst)
@@ -1212,18 +1216,13 @@ static void addr_handler(int status, str
{
struct rdma_id_private *id_priv = context;
enum rdma_cm_event_type event;
- enum cma_state old_state;
atomic_inc(&id_priv->dev_remove);
- if (!id_priv->cma_dev) {
- old_state = CMA_IDLE;
- if (!status)
- status = cma_acquire_dev(id_priv);
- } else
- old_state = CMA_ADDR_BOUND;
+ if (!id_priv->cma_dev && !status)
+ status = cma_acquire_dev(id_priv);
if (status) {
- if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, old_state))
+ if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
goto out;
event = RDMA_CM_EVENT_ADDR_ERROR;
} else {
@@ -1246,27 +1245,30 @@ out:
cma_deref_id(id_priv);
}
-static int cma_resolve_loopback(struct rdma_id_private *id_priv,
- struct sockaddr *src_addr, enum cma_state state)
+static int cma_resolve_loopback(struct rdma_id_private *id_priv)
{
struct cma_work *work;
- struct rdma_dev_addr *dev_addr;
+ struct sockaddr_in *src_in, *dst_in;
int ret;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (!work)
return -ENOMEM;
- if (state == CMA_IDLE) {
+ if (!id_priv->cma_dev) {
ret = cma_bind_loopback(id_priv);
if (ret)
goto err;
- dev_addr = &id_priv->id.route.addr.dev_addr;
- ib_addr_set_dgid(dev_addr, ib_addr_get_sgid(dev_addr));
- if (!src_addr || cma_any_addr(src_addr))
- src_addr = &id_priv->id.route.addr.dst_addr;
- memcpy(&id_priv->id.route.addr.src_addr, src_addr,
- ip_addr_size(src_addr));
+ }
+
+ ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr,
+ ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr));
+
+ if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) {
+ src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
+ dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
+ src_in->sin_family = dst_in->sin_family;
+ src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
}
work->id = id_priv;
@@ -1281,29 +1283,42 @@ err:
return ret;
}
+static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+ struct sockaddr *dst_addr)
+{
+ struct sockaddr_in addr_in;
+
+ if (src_addr && src_addr->sa_family)
+ return rdma_bind_addr(id, src_addr);
+ else {
+ memset(&addr_in, 0, sizeof addr_in);
+ addr_in.sin_family = dst_addr->sa_family;
+ return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
+ }
+}
+
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
struct sockaddr *dst_addr, int timeout_ms)
{
struct rdma_id_private *id_priv;
- enum cma_state expected_state;
int ret;
id_priv = container_of(id, struct rdma_id_private, id);
- if (id_priv->cma_dev) {
- expected_state = CMA_ADDR_BOUND;
- src_addr = &id->route.addr.src_addr;
- } else
- expected_state = CMA_IDLE;
+ if (id_priv->state == CMA_IDLE) {
+ ret = cma_bind_addr(id, src_addr, dst_addr);
+ if (ret)
+ return ret;
+ }
- if (!cma_comp_exch(id_priv, expected_state, CMA_ADDR_QUERY))
+ if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
return -EINVAL;
atomic_inc(&id_priv->refcount);
memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
if (cma_loopback_addr(dst_addr))
- ret = cma_resolve_loopback(id_priv, src_addr, expected_state);
+ ret = cma_resolve_loopback(id_priv);
else
- ret = rdma_resolve_ip(src_addr, dst_addr,
+ ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr,
&id->route.addr.dev_addr,
timeout_ms, addr_handler, id_priv);
if (ret)
@@ -1311,7 +1326,7 @@ int rdma_resolve_addr(struct rdma_cm_id
return 0;
err:
- cma_comp_exch(id_priv, CMA_ADDR_QUERY, expected_state);
+ cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
cma_deref_id(id_priv);
return ret;
}
@@ -1330,11 +1345,9 @@ int rdma_bind_addr(struct rdma_cm_id *id
if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
return -EINVAL;
- if (cma_any_addr(addr)) {
+ if (cma_any_addr(addr))
ret = 0;
- } else if (cma_loopback_addr(addr)) {
- ret = cma_bind_loopback(id_priv);
- } else {
+ else {
dev_addr = &id->route.addr.dev_addr;
ret = rdma_translate_ip(addr, dev_addr);
if (!ret)
More information about the general
mailing list