From owner-svn-src-projects@FreeBSD.ORG Mon Oct 18 22:28:30 2010 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5F6A1106566B; Mon, 18 Oct 2010 22:28:30 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4D5E98FC13; Mon, 18 Oct 2010 22:28:30 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9IMSUnX088217; Mon, 18 Oct 2010 22:28:30 GMT (envelope-from jeff@svn.freebsd.org) Received: (from jeff@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9IMSUar088215; Mon, 18 Oct 2010 22:28:30 GMT (envelope-from jeff@svn.freebsd.org) Message-Id: <201010182228.o9IMSUar088215@svn.freebsd.org> From: Jeff Roberson Date: Mon, 18 Oct 2010 22:28:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r214042 - projects/ofed/head/sys/ofed/drivers/infiniband/core X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Oct 2010 22:28:30 -0000 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 -#ifdef INET6 -#include -#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: