aboutsummaryrefslogtreecommitdiff
path: root/sys/ofed
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2017-11-09 19:27:29 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2017-11-09 19:27:29 +0000
commitcee98bee7dc776b32394b21f527ab48cf7beb1fd (patch)
treea274eb76d9f74e28af7a0fc1ca5e3754dd0edce1 /sys/ofed
parent860bbba0bbc4414965e320c9fa31645e26b72bad (diff)
downloadsrc-cee98bee7dc776b32394b21f527ab48cf7beb1fd.tar.gz
src-cee98bee7dc776b32394b21f527ab48cf7beb1fd.zip
Make sure the IPv6 scope ID gets zeroed when exchanging CMA messages in ibcore.
Else the IPv6 address matching might fail. This change adds support for both embedded and non-embedded IPv6 scope IDs when passing a IPv6 link-local socket address to RDMA. Prior to this change only global IPv6 addresses would work with RDMA. Sponsored by: Mellanox Technologies MFC after: 1 week
Notes
Notes: svn path=/head/; revision=325615
Diffstat (limited to 'sys/ofed')
-rw-r--r--sys/ofed/drivers/infiniband/core/cma.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/sys/ofed/drivers/infiniband/core/cma.c b/sys/ofed/drivers/infiniband/core/cma.c
index d35a201dba1d..b8a23f64f917 100644
--- a/sys/ofed/drivers/infiniband/core/cma.c
+++ b/sys/ofed/drivers/infiniband/core/cma.c
@@ -934,6 +934,17 @@ static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
return 0;
}
+static void cma_ip6_clear_scope_id(struct in6_addr *addr)
+{
+ /* make sure link local scope ID gets zeroed */
+ if (IN6_IS_SCOPE_LINKLOCAL(addr) ||
+ IN6_IS_ADDR_MC_INTFACELOCAL(addr)) {
+ /* use byte-access to be alignment safe */
+ addr->s6_addr[2] = 0;
+ addr->s6_addr[3] = 0;
+ }
+}
+
static void cma_save_net_info(struct rdma_addr *addr,
struct rdma_addr *listen_addr,
u8 ip_ver, __be16 port,
@@ -965,6 +976,7 @@ static void cma_save_net_info(struct rdma_addr *addr,
ip6->sin6_port = listen6->sin6_port;
ip6->sin6_len = sizeof(struct sockaddr_in6);
ip6->sin6_scope_id = listen6->sin6_scope_id;
+ cma_ip6_clear_scope_id(&ip6->sin6_addr);
ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
ip6->sin6_family = listen6->sin6_family;
@@ -972,6 +984,7 @@ static void cma_save_net_info(struct rdma_addr *addr,
ip6->sin6_port = port;
ip6->sin6_len = sizeof(struct sockaddr_in6);
ip6->sin6_scope_id = listen6->sin6_scope_id;
+ cma_ip6_clear_scope_id(&ip6->sin6_addr);
break;
default:
break;
@@ -1535,6 +1548,7 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
break;
case AF_INET6:
ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
+ cma_ip6_clear_scope_id(&ip6_addr);
if (ps == RDMA_PS_SDP) {
sdp_set_ip_ver(sdp_data, 6);
sdp_set_ip_ver(sdp_mask, 0xF);
@@ -2840,6 +2854,8 @@ static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
cma_hdr->src_addr.ip6 = src6->sin6_addr;
cma_hdr->dst_addr.ip6 = dst6->sin6_addr;
cma_hdr->port = src6->sin6_port;
+ cma_ip6_clear_scope_id(&cma_hdr->src_addr.ip6);
+ cma_ip6_clear_scope_id(&cma_hdr->dst_addr.ip6);
break;
}
}