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
