aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/cma.c
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2009-11-19 19:46:25 -0500
committerRoland Dreier <rolandd@cisco.com>2009-11-19 19:46:25 -0500
commitd14714df61681cfecf945a58436edf197327e87f (patch)
tree1dc232e98f17c531d75b0646ea519264e49a63b1 /drivers/infiniband/core/cma.c
parent923c100ef019bf15fb89b6fa3d3ad0485d25d59b (diff)
IB/addr: Fix IPv6 routing lookup
Include link scope as part of address resolution. Combine local and remote address resolution into a single, simpler code path. Fix error checking in the IPv6 routing lookups. Based on work from: David Wilder <dwilder@us.ibm.com> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Sean Hefty <sean.hefty@intel.com> [ Fix up cma_check_linklocal() for !IPV6 case. - Roland ] Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/cma.c')
-rw-r--r--drivers/infiniband/core/cma.c47
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 38867a46d39e..fbdd73106000 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1472,15 +1472,6 @@ static void cma_listen_on_all(struct rdma_id_private *id_priv)
1472 mutex_unlock(&lock); 1472 mutex_unlock(&lock);
1473} 1473}
1474 1474
1475static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
1476{
1477 struct sockaddr_storage addr_in;
1478
1479 memset(&addr_in, 0, sizeof addr_in);
1480 addr_in.ss_family = af;
1481 return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
1482}
1483
1484int rdma_listen(struct rdma_cm_id *id, int backlog) 1475int rdma_listen(struct rdma_cm_id *id, int backlog)
1485{ 1476{
1486 struct rdma_id_private *id_priv; 1477 struct rdma_id_private *id_priv;
@@ -1488,7 +1479,8 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
1488 1479
1489 id_priv = container_of(id, struct rdma_id_private, id); 1480 id_priv = container_of(id, struct rdma_id_private, id);
1490 if (id_priv->state == CMA_IDLE) { 1481 if (id_priv->state == CMA_IDLE) {
1491 ret = cma_bind_any(id, AF_INET); 1482 ((struct sockaddr *) &id->route.addr.src_addr)->sa_family = AF_INET;
1483 ret = rdma_bind_addr(id, (struct sockaddr *) &id->route.addr.src_addr);
1492 if (ret) 1484 if (ret)
1493 return ret; 1485 return ret;
1494 } 1486 }
@@ -1885,10 +1877,14 @@ err:
1885static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, 1877static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
1886 struct sockaddr *dst_addr) 1878 struct sockaddr *dst_addr)
1887{ 1879{
1888 if (src_addr && src_addr->sa_family) 1880 if (!src_addr || !src_addr->sa_family) {
1889 return rdma_bind_addr(id, src_addr); 1881 src_addr = (struct sockaddr *) &id->route.addr.src_addr;
1890 else 1882 if ((src_addr->sa_family = dst_addr->sa_family) == AF_INET6) {
1891 return cma_bind_any(id, dst_addr->sa_family); 1883 ((struct sockaddr_in6 *) src_addr)->sin6_scope_id =
1884 ((struct sockaddr_in6 *) dst_addr)->sin6_scope_id;
1885 }
1886 }
1887 return rdma_bind_addr(id, src_addr);
1892} 1888}
1893 1889
1894int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, 1890int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
@@ -2084,6 +2080,25 @@ static int cma_get_port(struct rdma_id_private *id_priv)
2084 return ret; 2080 return ret;
2085} 2081}
2086 2082
2083static int cma_check_linklocal(struct rdma_dev_addr *dev_addr,
2084 struct sockaddr *addr)
2085{
2086#if defined(CONFIG_IPv6) || defined(CONFIG_IPV6_MODULE)
2087 struct sockaddr_in6 *sin6;
2088
2089 if (addr->sa_family != AF_INET6)
2090 return 0;
2091
2092 sin6 = (struct sockaddr_in6 *) addr;
2093 if ((ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
2094 !sin6->sin6_scope_id)
2095 return -EINVAL;
2096
2097 dev_addr->bound_dev_if = sin6->sin6_scope_id;
2098#endif
2099 return 0;
2100}
2101
2087int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) 2102int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2088{ 2103{
2089 struct rdma_id_private *id_priv; 2104 struct rdma_id_private *id_priv;
@@ -2096,6 +2111,10 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
2096 if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) 2111 if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
2097 return -EINVAL; 2112 return -EINVAL;
2098 2113
2114 ret = cma_check_linklocal(&id->route.addr.dev_addr, addr);
2115 if (ret)
2116 goto err1;
2117
2099 if (cma_loopback_addr(addr)) { 2118 if (cma_loopback_addr(addr)) {
2100 ret = cma_bind_loopback(id_priv); 2119 ret = cma_bind_loopback(id_priv);
2101 } else if (!cma_zero_addr(addr)) { 2120 } else if (!cma_zero_addr(addr)) {