aboutsummaryrefslogtreecommitdiff
path: root/sys/ofed
diff options
context:
space:
mode:
authorSlava Shwartsman <slavash@FreeBSD.org>2018-12-05 13:23:14 +0000
committerSlava Shwartsman <slavash@FreeBSD.org>2018-12-05 13:23:14 +0000
commitae8534ca28e4914cfe544c1108e675fecca8a051 (patch)
tree702ce9ec82ce191e06439d59f2426a2d22057c55 /sys/ofed
parentf3cf3b7e8420c638516ee236e09d19b6427653fa (diff)
downloadsrc-ae8534ca28e4914cfe544c1108e675fecca8a051.tar.gz
src-ae8534ca28e4914cfe544c1108e675fecca8a051.zip
ibcore: Fix loopback with rdma-cm.
Trying to validate loopback fails because rtalloc1() resolves system local addresses to the loopback network interface, lo0. Fix this by explicitly checking for loopback during validation of the source and destination network address. If the source address belongs to a local network interface and is equal to the destination address, there is no need to run the destination address through rtalloc1(). Submitted by: hselasky@ Approved by: hselasky (mentor) MFC after: 1 week Sponsored by: Mellanox Technologies
Notes
Notes: svn path=/head/; revision=341530
Diffstat (limited to 'sys/ofed')
-rw-r--r--sys/ofed/drivers/infiniband/core/ib_cma.c33
1 files changed, 26 insertions, 7 deletions
diff --git a/sys/ofed/drivers/infiniband/core/ib_cma.c b/sys/ofed/drivers/infiniband/core/ib_cma.c
index 4a45efc5852e..51e74a451967 100644
--- a/sys/ofed/drivers/infiniband/core/ib_cma.c
+++ b/sys/ofed/drivers/infiniband/core/ib_cma.c
@@ -1292,6 +1292,12 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
dev_put(dst_dev);
/*
+ * Check for loopback.
+ */
+ if (saddr == daddr)
+ return true;
+
+ /*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
*/
@@ -1318,12 +1324,12 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
{
#ifdef INET6
struct sockaddr_in6 src_tmp = *src_addr;
- struct in6_addr in6_addr = dst_addr->sin6_addr;
+ struct sockaddr_in6 dst_tmp = *dst_addr;
struct net_device *dst_dev;
struct rtentry *rte;
bool ret;
- dst_dev = ip6_dev_find(net_dev->if_vnet, in6_addr);
+ dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr);
if (dst_dev != net_dev) {
if (dst_dev != NULL)
dev_put(dst_dev);
@@ -1345,12 +1351,25 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
src_tmp.sin6_scope_id = net_dev->if_index;
sa6_embedscope(&src_tmp, 0);
- rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
- if (rte != NULL) {
- ret = (rte->rt_ifp == net_dev);
- RTFREE_LOCKED(rte);
+ dst_tmp.sin6_scope_id = net_dev->if_index;
+ sa6_embedscope(&dst_tmp, 0);
+
+ /*
+ * Check for loopback after scope ID
+ * has been embedded:
+ */
+ if (memcmp(&src_tmp.sin6_addr, &dst_tmp.sin6_addr,
+ sizeof(dst_tmp.sin6_addr)) == 0) {
+ ret = true;
} else {
- ret = false;
+ /* non-loopback case */
+ rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
+ if (rte != NULL) {
+ ret = (rte->rt_ifp == net_dev);
+ RTFREE_LOCKED(rte);
+ } else {
+ ret = false;
+ }
}
CURVNET_RESTORE();
return ret;