aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2009-11-19 16:26:06 -0500
committerRoland Dreier <rolandd@cisco.com>2009-11-19 16:26:06 -0500
commit6f8372b69c3198e06cecb1df2cb9682d0c55e657 (patch)
tree4cd9a39fd782bc973b0394f779572ca72737f55c /drivers/infiniband
parentc4315d85f9b76834289fd503796c01b8311c4b84 (diff)
RDMA/cm: fix loopback address support
The RDMA CM is intended to support the use of a loopback address when establishing a connection; however, the behavior of the CM when loopback addresses are used is confusing and does not always work, depending on whether loopback was specified by the server, the client, or both. The defined behavior of rdma_bind_addr is to associate an RDMA device with an rdma_cm_id, as long as the user specified a non- zero address. (ie they weren't just trying to reserve a port) Currently, if the loopback address is passed to rdam_bind_addr, no device is associated with the rdma_cm_id. Fix this. If a loopback address is specified by the client as the destination address for a connection, it will fail to establish a connection. This is true even if the server is listing across all addresses or on the loopback address itself. The issue is that the server tries to translate the IP address carried in the REQ message to a local net_device address, which fails. The translation is not needed in this case, since the REQ carries the actual HW address that should be used. Finally, cleanup loopback support to be more transport neutral. Replace separate calls to get/set the sgid and dgid from the device address to a single call that behaves correctly depending on the format of the device address. And support both IPv4 and IPv6 address formats. Signed-off-by: Sean Hefty <sean.hefty@intel.com> [ Fixed RDS build by s/ib_addr_get/rdma_addr_get/ - Roland ] Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/cma.c77
-rw-r--r--drivers/infiniband/core/ucma.c8
2 files changed, 47 insertions, 38 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index b305b5c17f8..38867a46d39 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -330,17 +330,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
330 union ib_gid gid; 330 union ib_gid gid;
331 int ret = -ENODEV; 331 int ret = -ENODEV;
332 332
333 switch (dev_addr->dev_type) { 333 rdma_addr_get_sgid(dev_addr, &gid);
334 case ARPHRD_INFINIBAND:
335 ib_addr_get_sgid(dev_addr, &gid);
336 break;
337 case ARPHRD_ETHER:
338 iw_addr_get_sgid(dev_addr, &gid);
339 break;
340 default:
341 return -ENODEV;
342 }
343
344 list_for_each_entry(cma_dev, &dev_list, list) { 334 list_for_each_entry(cma_dev, &dev_list, list) {
345 ret = ib_find_cached_gid(cma_dev->device, &gid, 335 ret = ib_find_cached_gid(cma_dev->device, &gid,
346 &id_priv->id.port_num, NULL); 336 &id_priv->id.port_num, NULL);
@@ -1032,11 +1022,17 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
1032 if (rt->num_paths == 2) 1022 if (rt->num_paths == 2)
1033 rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; 1023 rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
1034 1024
1035 ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); 1025 if (cma_any_addr((struct sockaddr *) &rt->addr.src_addr)) {
1036 ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, 1026 rt->addr.dev_addr.dev_type = ARPHRD_INFINIBAND;
1037 &id->route.addr.dev_addr); 1027 rdma_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
1038 if (ret) 1028 ib_addr_set_pkey(&rt->addr.dev_addr, rt->path_rec[0].pkey);
1039 goto destroy_id; 1029 } else {
1030 ret = rdma_translate_ip((struct sockaddr *) &rt->addr.src_addr,
1031 &rt->addr.dev_addr);
1032 if (ret)
1033 goto destroy_id;
1034 }
1035 rdma_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
1040 1036
1041 id_priv = container_of(id, struct rdma_id_private, id); 1037 id_priv = container_of(id, struct rdma_id_private, id);
1042 id_priv->state = CMA_CONNECT; 1038 id_priv->state = CMA_CONNECT;
@@ -1071,10 +1067,12 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
1071 cma_save_net_info(&id->route.addr, &listen_id->route.addr, 1067 cma_save_net_info(&id->route.addr, &listen_id->route.addr,
1072 ip_ver, port, src, dst); 1068 ip_ver, port, src, dst);
1073 1069
1074 ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr, 1070 if (!cma_any_addr((struct sockaddr *) &id->route.addr.src_addr)) {
1075 &id->route.addr.dev_addr); 1071 ret = rdma_translate_ip((struct sockaddr *) &id->route.addr.src_addr,
1076 if (ret) 1072 &id->route.addr.dev_addr);
1077 goto err; 1073 if (ret)
1074 goto err;
1075 }
1078 1076
1079 id_priv = container_of(id, struct rdma_id_private, id); 1077 id_priv = container_of(id, struct rdma_id_private, id);
1080 id_priv->state = CMA_CONNECT; 1078 id_priv->state = CMA_CONNECT;
@@ -1565,8 +1563,8 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
1565 struct sockaddr_in6 *sin6; 1563 struct sockaddr_in6 *sin6;
1566 1564
1567 memset(&path_rec, 0, sizeof path_rec); 1565 memset(&path_rec, 0, sizeof path_rec);
1568 ib_addr_get_sgid(&addr->dev_addr, &path_rec.sgid); 1566 rdma_addr_get_sgid(&addr->dev_addr, &path_rec.sgid);
1569 ib_addr_get_dgid(&addr->dev_addr, &path_rec.dgid); 1567 rdma_addr_get_dgid(&addr->dev_addr, &path_rec.dgid);
1570 path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr)); 1568 path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(&addr->dev_addr));
1571 path_rec.numb_path = 1; 1569 path_rec.numb_path = 1;
1572 path_rec.reversible = 1; 1570 path_rec.reversible = 1;
@@ -1781,7 +1779,11 @@ port_found:
1781 if (ret) 1779 if (ret)
1782 goto out; 1780 goto out;
1783 1781
1784 ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); 1782 id_priv->id.route.addr.dev_addr.dev_type =
1783 (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ?
1784 ARPHRD_INFINIBAND : ARPHRD_ETHER;
1785
1786 rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
1785 ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); 1787 ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
1786 id_priv->id.port_num = p; 1788 id_priv->id.port_num = p;
1787 cma_attach_to_dev(id_priv, cma_dev); 1789 cma_attach_to_dev(id_priv, cma_dev);
@@ -1839,7 +1841,7 @@ out:
1839static int cma_resolve_loopback(struct rdma_id_private *id_priv) 1841static int cma_resolve_loopback(struct rdma_id_private *id_priv)
1840{ 1842{
1841 struct cma_work *work; 1843 struct cma_work *work;
1842 struct sockaddr_in *src_in, *dst_in; 1844 struct sockaddr *src, *dst;
1843 union ib_gid gid; 1845 union ib_gid gid;
1844 int ret; 1846 int ret;
1845 1847
@@ -1853,14 +1855,19 @@ static int cma_resolve_loopback(struct rdma_id_private *id_priv)
1853 goto err; 1855 goto err;
1854 } 1856 }
1855 1857
1856 ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); 1858 rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
1857 ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); 1859 rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
1858 1860
1859 if (cma_zero_addr((struct sockaddr *) &id_priv->id.route.addr.src_addr)) { 1861 src = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
1860 src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; 1862 if (cma_zero_addr(src)) {
1861 dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr; 1863 dst = (struct sockaddr *) &id_priv->id.route.addr.dst_addr;
1862 src_in->sin_family = dst_in->sin_family; 1864 if ((src->sa_family = dst->sa_family) == AF_INET) {
1863 src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr; 1865 ((struct sockaddr_in *) src)->sin_addr.s_addr =
1866 ((struct sockaddr_in *) dst)->sin_addr.s_addr;
1867 } else {
1868 ipv6_addr_copy(&((struct sockaddr_in6 *) src)->sin6_addr,
1869 &((struct sockaddr_in6 *) dst)->sin6_addr);
1870 }
1864 } 1871 }
1865 1872
1866 work->id = id_priv; 1873 work->id = id_priv;
@@ -2089,7 +2096,9 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2089 if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) 2096 if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
2090 return -EINVAL; 2097 return -EINVAL;
2091 2098
2092 if (!cma_any_addr(addr)) { 2099 if (cma_loopback_addr(addr)) {
2100 ret = cma_bind_loopback(id_priv);
2101 } else if (!cma_zero_addr(addr)) {
2093 ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); 2102 ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
2094 if (ret) 2103 if (ret)
2095 goto err1; 2104 goto err1;
@@ -2108,7 +2117,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2108 2117
2109 return 0; 2118 return 0;
2110err2: 2119err2:
2111 if (!cma_any_addr(addr)) { 2120 if (id_priv->cma_dev) {
2112 mutex_lock(&lock); 2121 mutex_lock(&lock);
2113 cma_detach_from_dev(id_priv); 2122 cma_detach_from_dev(id_priv);
2114 mutex_unlock(&lock); 2123 mutex_unlock(&lock);
@@ -2721,7 +2730,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
2721 cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid); 2730 cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
2722 if (id_priv->id.ps == RDMA_PS_UDP) 2731 if (id_priv->id.ps == RDMA_PS_UDP)
2723 rec.qkey = cpu_to_be32(RDMA_UDP_QKEY); 2732 rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
2724 ib_addr_get_sgid(dev_addr, &rec.port_gid); 2733 rdma_addr_get_sgid(dev_addr, &rec.port_gid);
2725 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); 2734 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
2726 rec.join_state = 1; 2735 rec.join_state = 1;
2727 2736
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index f1cbd26a9de..b2e16c332d5 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -563,10 +563,10 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
563 switch (route->num_paths) { 563 switch (route->num_paths) {
564 case 0: 564 case 0:
565 dev_addr = &route->addr.dev_addr; 565 dev_addr = &route->addr.dev_addr;
566 ib_addr_get_dgid(dev_addr, 566 rdma_addr_get_dgid(dev_addr,
567 (union ib_gid *) &resp->ib_route[0].dgid); 567 (union ib_gid *) &resp->ib_route[0].dgid);
568 ib_addr_get_sgid(dev_addr, 568 rdma_addr_get_sgid(dev_addr,
569 (union ib_gid *) &resp->ib_route[0].sgid); 569 (union ib_gid *) &resp->ib_route[0].sgid);
570 resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); 570 resp->ib_route[0].pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
571 break; 571 break;
572 case 2: 572 case 2: