aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2012-06-14 16:31:39 -0400
committerRoland Dreier <roland@purestorage.com>2012-07-08 21:02:24 -0400
commit406b6a25f85271397739a7e9f5af1df665b8a0d0 (patch)
tree92e5b43df5689594432bcc0aec8a28861218919f /drivers/infiniband
parent5b0ec991c0576c54db75803fbcb0ef5bebfa0828 (diff)
RDMA/cma: Listen on specific address family
The rdma_cm maps IPv4 and IPv6 addresses to the same service ID. This prevents apps from listening only for IPv4 or IPv6 addresses. It also results in an app binding to an IPv4 address receiving connection requests for an IPv6 address. Change this to match socket behavior: restrict listens on IPv4 addresses to only IPv4 addresses, and if a listen is on an IPv6 address, allow it to receive either IPv4 or IPv6 addresses, based on its address family binding. Signed-off-by: Sean Hefty <sean.hefty@intel.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/cma.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index c10c45a07162..454e7ea111e6 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1298,8 +1298,10 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
1298 } else { 1298 } else {
1299 cma_set_ip_ver(cma_data, 4); 1299 cma_set_ip_ver(cma_data, 4);
1300 cma_set_ip_ver(cma_mask, 0xF); 1300 cma_set_ip_ver(cma_mask, 0xF);
1301 cma_data->dst_addr.ip4.addr = ip4_addr; 1301 if (!cma_any_addr(addr)) {
1302 cma_mask->dst_addr.ip4.addr = htonl(~0); 1302 cma_data->dst_addr.ip4.addr = ip4_addr;
1303 cma_mask->dst_addr.ip4.addr = htonl(~0);
1304 }
1303 } 1305 }
1304 break; 1306 break;
1305 case AF_INET6: 1307 case AF_INET6:
@@ -1313,9 +1315,11 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
1313 } else { 1315 } else {
1314 cma_set_ip_ver(cma_data, 6); 1316 cma_set_ip_ver(cma_data, 6);
1315 cma_set_ip_ver(cma_mask, 0xF); 1317 cma_set_ip_ver(cma_mask, 0xF);
1316 cma_data->dst_addr.ip6 = ip6_addr; 1318 if (!cma_any_addr(addr)) {
1317 memset(&cma_mask->dst_addr.ip6, 0xFF, 1319 cma_data->dst_addr.ip6 = ip6_addr;
1318 sizeof cma_mask->dst_addr.ip6); 1320 memset(&cma_mask->dst_addr.ip6, 0xFF,
1321 sizeof cma_mask->dst_addr.ip6);
1322 }
1319 } 1323 }
1320 break; 1324 break;
1321 default: 1325 default:
@@ -1500,7 +1504,7 @@ static int cma_ib_listen(struct rdma_id_private *id_priv)
1500 1504
1501 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr; 1505 addr = (struct sockaddr *) &id_priv->id.route.addr.src_addr;
1502 svc_id = cma_get_service_id(id_priv->id.ps, addr); 1506 svc_id = cma_get_service_id(id_priv->id.ps, addr);
1503 if (cma_any_addr(addr)) 1507 if (cma_any_addr(addr) && !id_priv->afonly)
1504 ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); 1508 ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
1505 else { 1509 else {
1506 cma_set_compare_data(id_priv->id.ps, addr, &compare_data); 1510 cma_set_compare_data(id_priv->id.ps, addr, &compare_data);