svn commit: r214042 - projects/ofed/head/sys/ofed/drivers/infiniband/core

Jeff Roberson jeff at FreeBSD.org
Mon Oct 18 22:28:30 UTC 2010


Author: jeff
Date: Mon Oct 18 22:28:30 2010
New Revision: 214042
URL: http://svn.freebsd.org/changeset/base/214042

Log:
   - Fix a rtentry locking problem.
   - Sanitize the src_in address before passing it to ifwithaddr, annoyingly
     this fails if a port is specified in an sockaddr_sin.  Perhaps
     ifwithaddr needs protocol specific comparators.  The similar
     line for ipv6 likely does not work either and will need some adjustment.
   - Don't set the dev_type based on the if_type.  The rest of the stack
     assumes it's the ARPHDR type instead.  Only permit the two known
     types (ETHER and INFINIBAND).  This code should equally support
     iWarp and Infiniband rdma.
  
  Sponsored by:	Isilon Systems, iX Systems, and Panasas.

Modified:
  projects/ofed/head/sys/ofed/drivers/infiniband/core/addr.c

Modified: projects/ofed/head/sys/ofed/drivers/infiniband/core/addr.c
==============================================================================
--- projects/ofed/head/sys/ofed/drivers/infiniband/core/addr.c	Mon Oct 18 22:25:33 2010	(r214041)
+++ projects/ofed/head/sys/ofed/drivers/infiniband/core/addr.c	Mon Oct 18 22:28:30 2010	(r214042)
@@ -104,7 +104,12 @@ int rdma_copy_addr(struct rdma_dev_addr 
 int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct ifnet *dev,
 		     const unsigned char *dst_dev_addr)
 {
-	dev_addr->dev_type = dev->if_type;
+	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;
+	else
+		dev_addr->dev_type = 0;
 	memcpy(dev_addr->src_dev_addr, IF_LLADDR(dev), dev->if_addrlen);
 	memcpy(dev_addr->broadcast, __DECONST(char *, dev->if_broadcastaddr),
 	    dev->if_addrlen);
@@ -144,6 +149,7 @@ int rdma_translate_ip(struct sockaddr *a
 
 #if defined(INET6)
 	case AF_INET6:
+#ifdef __linux__
 		read_lock(&dev_base_lock);
 		for_each_netdev(&init_net, dev) {
 			if (ipv6_chk_addr(&init_net,
@@ -154,6 +160,7 @@ int rdma_translate_ip(struct sockaddr *a
 			}
 		}
 		read_unlock(&dev_base_lock);
+#endif
 		break;
 #endif
 	}
@@ -311,18 +318,18 @@ static int addr6_resolve(struct sockaddr
 
 #else
 #include <netinet/if_ether.h>
-#ifdef INET6
-#include <netinet6/nd6.h>
-#endif
 
 static int addr_resolve(struct sockaddr *src_in,
 			struct sockaddr *dst_in,
 			struct rdma_dev_addr *addr)
 {
+	struct sockaddr_in *sin;
+	struct sockaddr_in6 *sin6;
 	struct ifaddr *ifa;
 	struct ifnet *ifp;
 	struct llentry *lle;
 	struct rtentry *rte;
+	short port;
 	u_char edst[MAX_ADDR_LEN];
 	int multi;
 	int bcast;
@@ -334,26 +341,35 @@ static int addr_resolve(struct sockaddr 
 	 */
 	multi = 0;
 	bcast = 0;
+	sin = NULL;
+	sin6 = NULL;
 	ifp = NULL;
 	switch (dst_in->sa_family) {
 	case AF_INET:
-		if (((struct sockaddr_in *)dst_in)->sin_addr.s_addr ==
-		    INADDR_BROADCAST)
+		sin = (struct sockaddr_in *)dst_in;
+		if (sin->sin_addr.s_addr == INADDR_BROADCAST)
 			bcast = 1;
-		if (IN_MULTICAST((
-		    (struct sockaddr_in *)dst_in)->sin_addr.s_addr))
+		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
 			multi = 1;
-		if (((struct sockaddr_in *)src_in)->sin_addr.s_addr ==
-		    INADDR_ANY)
+		sin = (struct sockaddr_in *)src_in;
+		if (sin->sin_addr.s_addr != INADDR_ANY) {
+			/*
+			 * Address comparison fails if the port is set
+			 * cache it here to be restored later.
+			 */
+			port = sin->sin_port;
+			sin->sin_port = 0;
+			memset(&sin->sin_zero, 0, sizeof(sin->sin_zero));
+		} else
 			src_in = NULL; 
 		break;
 #ifdef INET6
 	case AF_INET6:
-		if (IN6_IS_ADDR_MULTICAST(
-		    &((struct sockaddr_in6 *)dst_in)->sin6_addr))
+		sin6 = (struct sockaddr_in6 *)dst_in;
+		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
 			multi = 1;
-		if (IN6_IS_ADDR_UNSPECIFIED(
-		    &((struct sockaddr_in6 *)src_in)->sin6_addr))
+		sin6 = (struct sockaddr_in6 *)src_in;
+		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
 			src_in = NULL;
 		break;
 #endif
@@ -365,7 +381,9 @@ static int addr_resolve(struct sockaddr 
 	 * that it is a local interface.
 	 */
 	if (src_in) {
-		ifa = ifa_ifwithdstaddr(src_in);
+		ifa = ifa_ifwithaddr(src_in);
+		if (sin)
+			sin->sin_port = port;
 		if (ifa == NULL)
 			return -ENETUNREACH;
 		ifp = ifa->ifa_ifp;
@@ -378,8 +396,8 @@ static int addr_resolve(struct sockaddr 
 	 */
 	rte = rtalloc1(dst_in, 1, 0);
 	if (rte == NULL || rte->rt_ifp == NULL || !RT_LINK_IS_UP(rte->rt_ifp)) {
-		if (rte)
-			RTFREE(rte);
+		if (rte) 
+			RTFREE_LOCKED(rte);
 		return -EHOSTUNREACH;
 	}
 	/*
@@ -387,11 +405,12 @@ static int addr_resolve(struct sockaddr 
 	 * requested interface return unreachable.
 	 */
 	if (multi || bcast) {
-		RTFREE(rte);
+		RTFREE_LOCKED(rte);
 	} else if (ifp && ifp != rte->rt_ifp) {
-		RTFREE(rte);
+		RTFREE_LOCKED(rte);
 		return -ENETUNREACH;
-	}
+	} else
+		RT_UNLOCK(rte);
 	if (ifp == NULL)
 		ifp = rte->rt_ifp;
 mcast:


More information about the svn-src-projects mailing list