Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Mar 2018 13:57:38 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r330504 - head/sys/ofed/drivers/infiniband/core
Message-ID:  <201803051357.w25Dvcr5084582@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon Mar  5 13:57:37 2018
New Revision: 330504
URL: https://svnweb.freebsd.org/changeset/base/330504

Log:
  Add support for loopback in ibcore.
  
  Implement the missing pieces in addr_resolve() to support loopback
  addresses. IB core will test for the IFF_LOOPBACK flag in the network
  interface and treat these devices in a special way.
  
  MFC after:	1 week
  Sponsored by:	Mellanox Technologies

Modified:
  head/sys/ofed/drivers/infiniband/core/ib_addr.c

Modified: head/sys/ofed/drivers/infiniband/core/ib_addr.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/core/ib_addr.c	Mon Mar  5 13:52:25 2018	(r330503)
+++ head/sys/ofed/drivers/infiniband/core/ib_addr.c	Mon Mar  5 13:57:37 2018	(r330504)
@@ -123,7 +123,15 @@ rdma_copy_addr_sub(u8 *dst, const u8 *src, unsigned mi
 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
 		     const unsigned char *dst_dev_addr)
 {
-	if (dev->if_type == IFT_INFINIBAND)
+	/* check for loopback device */
+	if (dev->if_type == IFT_LOOP) {
+		dev_addr->dev_type = ARPHRD_ETHER;
+		memset(dev_addr->src_dev_addr, 0, MAX_ADDR_LEN);
+		memset(dev_addr->broadcast, 0, MAX_ADDR_LEN);
+		memset(dev_addr->dst_dev_addr, 0, MAX_ADDR_LEN);
+		dev_addr->bound_dev_if = dev->if_index;
+		return (0);
+	} else if (dev->if_type == IFT_INFINIBAND)
 		dev_addr->dev_type = ARPHRD_INFINIBAND;
 	else if (dev->if_type == IFT_ETHER)
 		dev_addr->dev_type = ARPHRD_ETHER;
@@ -240,10 +248,10 @@ static int addr_resolve_multi(u8 *edst, struct ifnet *
 static int addr4_resolve(struct sockaddr_in *src_in,
 			 const struct sockaddr_in *dst_in,
 			 struct rdma_dev_addr *addr,
+			 u8 *edst,
 			 struct ifnet **ifpp)
 {
 	struct sockaddr_in dst_tmp = *dst_in;
-	u8 edst[MAX_ADDR_LEN];
 	in_port_t src_port;
 	struct sockaddr *saddr;
 	struct rtentry *rte;
@@ -278,8 +286,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 		if (rte == NULL) {
 			error = EHOSTUNREACH;
 			goto done;
-		} else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif ||
-		    RT_LINK_IS_UP(rte->rt_ifp) == 0) {
+		} else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
 			RTFREE_LOCKED(rte);
 			error = EHOSTUNREACH;
 			goto done;
@@ -294,8 +301,14 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 	/* Step 2 - find outgoing network interface */
 	switch (type) {
 	case 0:
-		/* source check */
-		ifp = ip_dev_find(addr->net, src_in->sin_addr.s_addr);
+		/* check for loopback device */
+		if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
+			ifp = rte->rt_ifp;
+			dev_hold(ifp);
+		} else {
+			ifp = ip_dev_find(addr->net, src_in->sin_addr.s_addr);
+		}
+		/* check source interface */
 		if (ifp == NULL) {
 			error = ENETUNREACH;
 			goto error_rt_free;
@@ -305,11 +318,17 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 		}
 		break;
 	case 1:
+		/* check for loopback device */
+		if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
+			saddr = (struct sockaddr *)&dst_tmp;
+		else
+			saddr = rte->rt_ifa->ifa_addr;
+
 		/* get destination network interface from route */
 		ifp = rte->rt_ifp;
 		dev_hold(ifp);
-		saddr = rte->rt_ifa->ifa_addr;
 
+		/* update source address */
 		src_port = src_in->sin_port;
 		memcpy(src_in, saddr, rdma_addr_size(saddr));
 		src_in->sin_port = src_port;	/* preserve port number */
@@ -324,13 +343,17 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 	if (dst_tmp.sin_addr.s_addr == INADDR_BROADCAST) {
 		rdma_copy_addr_sub(edst, ifp->if_broadcastaddr,
 		    ifp->if_addrlen, MAX_ADDR_LEN);
+		error = 0;
 	} else if (IN_MULTICAST(ntohl(dst_tmp.sin_addr.s_addr))) {
 		error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp);
 		if (error != 0)
 			goto error_put_ifp;
+	} else if (ifp->if_flags & IFF_LOOPBACK) {
+		memset(edst, 0, MAX_ADDR_LEN);
+		error = 0;
 	} else {
 		bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
-		memset(edst, 0, sizeof(edst));
+		memset(edst, 0, MAX_ADDR_LEN);
 		error = arpresolve(ifp, is_gw, NULL, is_gw ?
 		    rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
 		    edst, NULL, NULL);
@@ -340,13 +363,6 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 			addr->network = RDMA_NETWORK_IPV4;
 	}
 
-	/*
-	 * Step 4 - copy destination and source MAC addresses
-	 */
-	error = -rdma_copy_addr(addr, ifp, edst);
-	if (error != 0)
-		goto error_put_ifp;
-
 	if (rte != NULL)
 		RTFREE(rte);
 
@@ -369,6 +385,7 @@ done:
 static int addr4_resolve(struct sockaddr_in *src_in,
 			 const struct sockaddr_in *dst_in,
 			 struct rdma_dev_addr *addr,
+			 u8 *edst,
 			 struct ifnet **ifpp)
 {
 	return -EADDRNOTAVAIL;
@@ -379,10 +396,10 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 static int addr6_resolve(struct sockaddr_in6 *src_in,
 			 const struct sockaddr_in6 *dst_in,
 			 struct rdma_dev_addr *addr,
+			 u8 *edst,
 			 struct ifnet **ifpp)
 {
 	struct sockaddr_in6 dst_tmp = *dst_in;
-	u8 edst[MAX_ADDR_LEN];
 	in_port_t src_port;
 	struct sockaddr *saddr;
 	struct rtentry *rte;
@@ -424,8 +441,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 		if (rte == NULL) {
 			error = EHOSTUNREACH;
 			goto done;
-		} else if (rte->rt_ifp == NULL || rte->rt_ifp == V_loif ||
-		    RT_LINK_IS_UP(rte->rt_ifp) == 0) {
+		} else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
 			RTFREE_LOCKED(rte);
 			error = EHOSTUNREACH;
 			goto done;
@@ -440,8 +456,14 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 	/* Step 2 - find outgoing network interface */
 	switch (type) {
 	case 0:
-		/* source check */
-		ifp = ip6_dev_find(addr->net, src_in->sin6_addr);
+		/* check for loopback device */
+		if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
+			ifp = rte->rt_ifp;
+			dev_hold(ifp);
+		} else {
+			ifp = ip6_dev_find(addr->net, src_in->sin6_addr);
+		}
+		/* check source interface */
 		if (ifp == NULL) {
 			error = ENETUNREACH;
 			goto error_rt_free;
@@ -451,10 +473,15 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 		}
 		break;
 	case 1:
+		/* check for loopback device */
+		if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
+			saddr = (struct sockaddr *)&dst_tmp;
+		else
+			saddr = rte->rt_ifa->ifa_addr;
+
 		/* get destination network interface from route */
 		ifp = rte->rt_ifp;
 		dev_hold(ifp);
-		saddr = rte->rt_ifa->ifa_addr;
 
 		src_port = src_in->sin6_port;
 		memcpy(src_in, saddr, rdma_addr_size(saddr));
@@ -472,9 +499,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 		    (struct sockaddr *)&dst_tmp);
 		if (error != 0)
 			goto error_put_ifp;
+	} else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
+		memset(edst, 0, MAX_ADDR_LEN);
+		error = 0;
 	} else {
 		bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
-		memset(edst, 0, sizeof(edst));
+		memset(edst, 0, MAX_ADDR_LEN);
 		error = nd6_resolve(ifp, is_gw, NULL, is_gw ?
 		    rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
 		    edst, NULL, NULL);
@@ -484,13 +514,6 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 			addr->network = RDMA_NETWORK_IPV6;
 	}
 
-	/*
-	 * Step 4 - copy destination and source MAC addresses
-	 */
-	error = -rdma_copy_addr(addr, ifp, edst);
-	if (error != 0)
-		goto error_put_ifp;
-
 	if (rte != NULL)
 		RTFREE(rte);
 
@@ -513,6 +536,7 @@ done:
 static int addr6_resolve(struct sockaddr_in6 *src_in,
 			 const struct sockaddr_in6 *dst_in,
 			 struct rdma_dev_addr *addr,
+			 u8 *edst,
 			 struct ifnet **ifpp)
 {
 	return -EADDRNOTAVAIL;
@@ -521,6 +545,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 
 static int addr_resolve_neigh(struct ifnet *dev,
 			      const struct sockaddr *dst_in,
+			      u8 *edst,
 			      struct rdma_dev_addr *addr)
 {
 	if (dev->if_flags & IFF_LOOPBACK) {
@@ -536,7 +561,7 @@ static int addr_resolve_neigh(struct ifnet *dev,
 
 	/* If the device doesn't do ARP internally */
 	if (!(dev->if_flags & IFF_NOARP))
-		return 0;
+		return rdma_copy_addr(addr, dev, edst);
 
 	return rdma_copy_addr(addr, dev, NULL);
 }
@@ -547,6 +572,7 @@ static int addr_resolve(struct sockaddr *src_in,
 			bool resolve_neigh)
 {
 	struct net_device *ndev = NULL;
+	u8 edst[MAX_ADDR_LEN];
 	int ret;
 
 	if (dst_in->sa_family != src_in->sa_family)
@@ -555,21 +581,21 @@ static int addr_resolve(struct sockaddr *src_in,
 	if (src_in->sa_family == AF_INET) {
 		ret = addr4_resolve((struct sockaddr_in *)src_in,
 				    (const struct sockaddr_in *)dst_in,
-				    addr, &ndev);
+				    addr, edst, &ndev);
 		if (ret)
 			return ret;
 
 		if (resolve_neigh)
-			ret = addr_resolve_neigh(ndev, dst_in, addr);
+			ret = addr_resolve_neigh(ndev, dst_in, edst, addr);
 	} else {
 		ret = addr6_resolve((struct sockaddr_in6 *)src_in,
 				    (const struct sockaddr_in6 *)dst_in, addr,
-				    &ndev);
+				    edst, &ndev);
 		if (ret)
 			return ret;
 
 		if (resolve_neigh)
-			ret = addr_resolve_neigh(ndev, dst_in, addr);
+			ret = addr_resolve_neigh(ndev, dst_in, edst, addr);
 	}
 
 	addr->bound_dev_if = ndev->if_index;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803051357.w25Dvcr5084582>