Current iWARP implementations make use of the TCP port space for iWARP
connections without synchornizing with the host TCP stack.  This can
lead to both host TCP and offloaded iWARP connections for the iWARP
interface to use the same TCP port.  The combined traffic will result
in undesirable behaviors from connection failures to resets.

This patch resolves the issue by allocating a kernel socket consuming
the TCP port for the iWARP connection upon connection creation and
freeing the socket once the iWARP connection is destroyed.

This functionality is needed for iWARP adapters that are both a L2 and
offload iWARP device.  Applications can create and use host TCP and
iWARP connections over the same interface without additional
administrative overhead and complication needed to manage TCP port space
manually.

Signed-off-by: Steve Wise <[email protected]>
Signed-off-by: Faisal Latif <[email protected]>
Signed-off-by: Chien Tung <[email protected]>
---
V2 changes:

*  Fix compilation warning in cma_0100_unified_tcp_ports.patch

   Signed-off-by: Vladimir Sokolovsky <[email protected]>

  -                     ip_addr_size(&id_priv->id.route.addr.src_addr));
  +                     ip_addr_size((struct sockaddr *) 
&id_priv->id.route.addr.src_addr));


*  IB/core: fix build warning

   Eliminates the following build warning:

      CC [M]  ./drivers/infiniband/core/cma.o
    ./drivers/infiniband/core/cma.c: In function 'cma_get_tcp_port':
    ./drivers/infiniband/core/cma.c:2076: warning: passing argument 1 of 
'ip_addr_size' from incompatible pointer type

    Signed-off-by: John Gregor <[email protected]>
    Signed-off-by: Yannick Cote <[email protected]>

  -     size = ip_addr_size(&id_priv->id.route.addr.src_addr);
  +     size = ip_addr_size((struct sockaddr *) 
&id_priv->id.route.addr.src_addr);

* Add getname

  Signed-off-by: Faisal Latif <[email protected]>

* Change default unify_tcp_port_space to 1

  Signed-off-by: Chien Tung <[email protected]>

 drivers/infiniband/core/cma.c |   46 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b930b81..d5855f9 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -56,6 +56,11 @@ MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("Generic RDMA CM Agent");
 MODULE_LICENSE("Dual BSD/GPL");
 
+int unify_tcp_port_space = 1;
+module_param(unify_tcp_port_space, int, 0644);
+MODULE_PARM_DESC(unify_tcp_port_space, "Unify the host TCP and RDMA port "
+                "space allocation (default=1)");
+
 #define CMA_CM_RESPONSE_TIMEOUT 20
 #define CMA_MAX_CM_RETRIES 15
 #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
@@ -118,6 +123,7 @@ struct rdma_id_private {
        struct rdma_cm_id       id;
 
        struct rdma_bind_list   *bind_list;
+       struct socket           *sock;
        struct hlist_node       node;
        struct list_head        list; /* listen_any_list or cma_device.list */
        struct list_head        listen_list; /* per device listens */
@@ -806,6 +812,8 @@ static void cma_release_port(struct rdma_id_private 
*id_priv)
                kfree(bind_list);
        }
        mutex_unlock(&lock);
+       if (id_priv->sock)
+               sock_release(id_priv->sock);
 }
 
 static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
@@ -2035,6 +2043,37 @@ static int cma_use_port(struct idr *ps, struct 
rdma_id_private *id_priv)
        return 0;
 }
 
+static int cma_get_tcp_port(struct rdma_id_private *id_priv)
+{
+       int ret;
+       int size;
+       struct socket *sock;
+
+       ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
+       if (ret)
+               return ret;
+
+       size = ip_addr_size((struct sockaddr *) 
&id_priv->id.route.addr.src_addr);
+
+       ret = sock->ops->bind(sock,
+                       (struct sockaddr *) &id_priv->id.route.addr.src_addr,
+                       size);
+       if (ret)
+               goto err;
+
+       ret = sock->ops->getname(sock,
+                       (struct sockaddr *) &id_priv->id.route.addr.src_addr,
+                       &size, 0);
+       if (ret)
+               goto err;
+
+       id_priv->sock = sock;
+       return 0;
+err:
+       sock_release(sock);
+       return ret;
+}
+
 static int cma_get_port(struct rdma_id_private *id_priv)
 {
        struct idr *ps;
@@ -2046,6 +2085,11 @@ static int cma_get_port(struct rdma_id_private *id_priv)
                break;
        case RDMA_PS_TCP:
                ps = &tcp_ps;
+               if (unify_tcp_port_space) {
+                       ret = cma_get_tcp_port(id_priv);
+                       if (ret)
+                               goto out;
+               }
                break;
        case RDMA_PS_UDP:
                ps = &udp_ps;
@@ -2063,7 +2107,7 @@ static int cma_get_port(struct rdma_id_private *id_priv)
        else
                ret = cma_use_port(ps, id_priv);
        mutex_unlock(&lock);
-
+out:
        return ret;
 }
 
-- 
1.6.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to