| From 9dea9a2ff61c5efb4d4937ae23b14babd25a5547 Mon Sep 17 00:00:00 2001 |
| From: Tatyana Nikolova <tatyana.e.nikolova@intel.com> |
| Date: Mon, 12 Mar 2018 17:14:02 -0500 |
| Subject: RDMA/core: Do not use invalid destination in determining port reuse |
| |
| From: Tatyana Nikolova <tatyana.e.nikolova@intel.com> |
| |
| commit 9dea9a2ff61c5efb4d4937ae23b14babd25a5547 upstream. |
| |
| cma_port_is_unique() allows local port reuse if the quad (source |
| address and port, destination address and port) for this connection |
| is unique. However, if the destination info is zero or unspecified, it |
| can't make a correct decision but still allows port reuse. For example, |
| sometimes rdma_bind_addr() is called with unspecified destination and |
| reusing the port can lead to creating a connection with a duplicate quad, |
| after the destination is resolved. The issue manifests when MPI scale-up |
| tests hang after the duplicate quad is used. |
| |
| Set the destination address family and add checks for zero destination |
| address and port to prevent source port reuse based on invalid destination. |
| |
| Fixes: 19b752a19dce ("IB/cma: Allow port reuse for rdma_id") |
| Reviewed-by: Sean Hefty <sean.hefty@intel.com> |
| Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com> |
| Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com> |
| Signed-off-by: Doug Ledford <dledford@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/core/cma.c | 12 +++++++----- |
| 1 file changed, 7 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/infiniband/core/cma.c |
| +++ b/drivers/infiniband/core/cma.c |
| @@ -3017,7 +3017,8 @@ static int cma_port_is_unique(struct rdm |
| continue; |
| |
| /* different dest port -> unique */ |
| - if (!cma_any_port(cur_daddr) && |
| + if (!cma_any_port(daddr) && |
| + !cma_any_port(cur_daddr) && |
| (dport != cur_dport)) |
| continue; |
| |
| @@ -3028,7 +3029,8 @@ static int cma_port_is_unique(struct rdm |
| continue; |
| |
| /* different dst address -> unique */ |
| - if (!cma_any_addr(cur_daddr) && |
| + if (!cma_any_addr(daddr) && |
| + !cma_any_addr(cur_daddr) && |
| cma_addr_cmp(daddr, cur_daddr)) |
| continue; |
| |
| @@ -3326,13 +3328,13 @@ int rdma_bind_addr(struct rdma_cm_id *id |
| } |
| #endif |
| } |
| + daddr = cma_dst_addr(id_priv); |
| + daddr->sa_family = addr->sa_family; |
| + |
| ret = cma_get_port(id_priv); |
| if (ret) |
| goto err2; |
| |
| - daddr = cma_dst_addr(id_priv); |
| - daddr->sa_family = addr->sa_family; |
| - |
| return 0; |
| err2: |
| if (id_priv->cma_dev) |