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 <[EMAIL PROTECTED]>

---

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)

_______________________________________________
openib-general mailing list
[email protected]
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to