Blob Blame History Raw
From: Parav Pandit <parav@mellanox.com>
Date: Wed, 5 Sep 2018 12:54:19 +0300
Subject: RDMA/core: Introduce and use rdma_set_src_addr() between IPv4 and
 IPv6
Patch-mainline: v4.20-rc1
Git-commit: a362ea1d9e1acf674094614518f4245d17cfc01e
References: bsc#1103992 FATE#326009

rdma_translate_ip() is done while resolving address for the loopback
addresses. The current flow is convoluted with resolve neighbor being
optional.

This patch simplifies the code in following ways.

(a) Use common code between IPv4 and IPv6 for address translation,
    loopback checks and acquiring netdevice.
(b) During neigh resolve in addr_resolve_neigh(), only copy destination
    address.
(c) Always resolve the source address before the destination address,
    because it doesn't depend on resolving neigh being requested or not.

This helps to reduce 3 calls of rdma_copy_addr and rdma_translate_ip to
one and makes it easier to follow the code flow.

Now that ib_nl_fetch_ha() doesn't depend on dst, drop dst argument from
ib_nl_fetch_ha().

Signed-off-by: Parav Pandit <parav@mellanox.com>
Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/infiniband/core/addr.c |   65 ++++++++++++++---------------------------
 1 file changed, 23 insertions(+), 42 deletions(-)

--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -304,15 +304,12 @@ static void queue_req(struct addr_req *r
 	spin_unlock_bh(&lock);
 }
 
-static int ib_nl_fetch_ha(const struct dst_entry *dst,
-			  struct rdma_dev_addr *dev_addr,
+static int ib_nl_fetch_ha(struct rdma_dev_addr *dev_addr,
 			  const void *daddr, u32 seq, u16 family)
 {
 	if (rdma_nl_chk_listeners(RDMA_NL_GROUP_LS))
 		return -EADDRNOTAVAIL;
 
-	/* We fill in what we can, the response will fill the rest */
-	rdma_copy_addr(dev_addr, dst->dev, NULL);
 	return ib_nl_ip_send_msg(dev_addr, daddr, seq, family);
 }
 
@@ -331,7 +328,7 @@ static int dst_fetch_ha(const struct dst
 		neigh_event_send(n, NULL);
 		ret = -ENODATA;
 	} else {
-		rdma_copy_addr(dev_addr, dst->dev, n->ha);
+		memcpy(dev_addr->dst_dev_addr, n->ha, MAX_ADDR_LEN);
 	}
 
 	neigh_release(n);
@@ -367,7 +364,7 @@ static int fetch_ha(const struct dst_ent
 
 	/* Gateway + ARPHRD_INFINIBAND -> IB router */
 	if (has_gateway(dst, family) && dst->dev->type == ARPHRD_INFINIBAND)
-		return ib_nl_fetch_ha(dst, dev_addr, daddr, seq, family);
+		return ib_nl_fetch_ha(dev_addr, daddr, seq, family);
 	else
 		return dst_fetch_ha(dst, dev_addr, daddr);
 }
@@ -467,32 +464,37 @@ static int addr_resolve_neigh(const stru
 			      u32 seq)
 {
 	if (dst->dev->flags & IFF_LOOPBACK) {
-		int ret;
-
-		ret = rdma_translate_ip(dst_in, addr);
-		if (!ret)
-			memcpy(addr->dst_dev_addr, addr->src_dev_addr,
-			       MAX_ADDR_LEN);
-
-		return ret;
+		memcpy(addr->dst_dev_addr, addr->src_dev_addr, MAX_ADDR_LEN);
+		return 0;
 	}
 
 	/* If the device doesn't do ARP internally */
 	if (!(dst->dev->flags & IFF_NOARP))
 		return fetch_ha(dst, addr, dst_in, seq);
 
-	rdma_copy_addr(addr, dst->dev, NULL);
-
 	return 0;
 }
 
+static int rdma_set_src_addr(const struct dst_entry *dst,
+			     const struct sockaddr *dst_in,
+			     struct rdma_dev_addr *dev_addr)
+{
+	int ret = 0;
+
+	if (dst->dev->flags & IFF_LOOPBACK)
+		ret = rdma_translate_ip(dst_in, dev_addr);
+	else
+		rdma_copy_addr(dev_addr, dst->dev, NULL);
+	return ret;
+}
+
 static int addr_resolve(struct sockaddr *src_in,
 			const struct sockaddr *dst_in,
 			struct rdma_dev_addr *addr,
 			bool resolve_neigh,
 			u32 seq)
 {
-	struct net_device *ndev;
+	struct rtable *rt = NULL;
 	struct dst_entry *dst;
 	int ret;
 
@@ -502,49 +504,28 @@ static int addr_resolve(struct sockaddr
 	}
 
 	if (src_in->sa_family == AF_INET) {
-		struct rtable *rt = NULL;
 
 		ret = addr4_resolve(src_in, dst_in, addr, &rt);
 		if (ret)
 			return ret;
 
-		if (resolve_neigh)
+		ret = rdma_set_src_addr(&rt->dst, dst_in, addr);
+		if (!ret && resolve_neigh)
 			ret = addr_resolve_neigh(&rt->dst, dst_in, addr, seq);
 
-		if (addr->bound_dev_if) {
-			ndev = dev_get_by_index(addr->net, addr->bound_dev_if);
-		} else {
-			ndev = rt->dst.dev;
-			dev_hold(ndev);
-		}
-
 		ip_rt_put(rt);
 	} else {
 		ret = addr6_resolve(src_in, dst_in, addr, &dst);
 		if (ret)
 			return ret;
 
-		if (resolve_neigh)
+		ret = rdma_set_src_addr(dst, dst_in, addr);
+		if (!ret && resolve_neigh)
 			ret = addr_resolve_neigh(dst, dst_in, addr, seq);
 
-		if (addr->bound_dev_if) {
-			ndev = dev_get_by_index(addr->net, addr->bound_dev_if);
-		} else {
-			ndev = dst->dev;
-			dev_hold(ndev);
-		}
-
 		dst_release(dst);
 	}
 
-	if (ndev) {
-		if (ndev->flags & IFF_LOOPBACK)
-			ret = rdma_translate_ip(dst_in, addr);
-		else
-			addr->bound_dev_if = ndev->ifindex;
-		dev_put(ndev);
-	}
-
 	return ret;
 }