Author: slavash
Date: Wed Dec  5 13:24:43 2018
New Revision: 341533
URL: https://svnweb.freebsd.org/changeset/base/341533

Log:
  ibcore: ip6_dev_find() needs to know the scope ID.
  
  Else the wrong network device can be returned for link-local addresses.
  
  Submitted by:   hselasky@
  Approved by:    hselasky (mentor)
  MFC after:      1 week
  Sponsored by:   Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/linux/inetdevice.h
  head/sys/ofed/drivers/infiniband/core/ib_addr.c
  head/sys/ofed/drivers/infiniband/core/ib_cma.c

Modified: head/sys/compat/linuxkpi/common/include/linux/inetdevice.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/inetdevice.h  Wed Dec  5 
13:24:12 2018        (r341532)
+++ head/sys/compat/linuxkpi/common/include/linux/inetdevice.h  Wed Dec  5 
13:24:43 2018        (r341533)
@@ -59,37 +59,32 @@ ip_dev_find(struct vnet *vnet, uint32_t addr)
 }
 
 static inline struct net_device *
-ip6_dev_find(struct vnet *vnet, struct in6_addr addr)
+ip6_dev_find(struct vnet *vnet, struct in6_addr addr, uint16_t scope_id)
 {
        struct sockaddr_in6 sin6;
-       struct ifaddr *ifa = NULL;
-       struct ifnet *ifp = NULL;
-       int x;
+       struct ifaddr *ifa;
+       struct ifnet *ifp;
 
        memset(&sin6, 0, sizeof(sin6));
        sin6.sin6_addr = addr;
        sin6.sin6_len = sizeof(sin6);
        sin6.sin6_family = AF_INET6;
-       NET_EPOCH_ENTER();
-       CURVNET_SET_QUIET(vnet);
        if (IN6_IS_SCOPE_LINKLOCAL(&addr) ||
            IN6_IS_ADDR_MC_INTFACELOCAL(&addr)) {
-               /* XXX need to search all scope ID's */
-               for (x = 0; x <= V_if_index && x < 65536; x++) {
-                       sin6.sin6_addr.s6_addr16[1] = htons(x);
-                       ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
-                       if (ifa != NULL)
-                               break;
-               }
-       } else {
-               ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
+               /* embed the IPv6 scope ID */
+               sin6.sin6_addr.s6_addr16[1] = htons(scope_id);
        }
+       NET_EPOCH_ENTER();
+       CURVNET_SET_QUIET(vnet);
+       ifa = ifa_ifwithaddr((struct sockaddr *)&sin6);
+       CURVNET_RESTORE();
        if (ifa != NULL) {
                ifp = ifa->ifa_ifp;
                if_ref(ifp);
+       } else {
+               ifp = NULL;
        }
        NET_EPOCH_EXIT();
-       CURVNET_RESTORE();
        return (ifp);
 }
 

Modified: head/sys/ofed/drivers/infiniband/core/ib_addr.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/core/ib_addr.c     Wed Dec  5 13:24:12 
2018        (r341532)
+++ head/sys/ofed/drivers/infiniband/core/ib_addr.c     Wed Dec  5 13:24:43 
2018        (r341533)
@@ -185,7 +185,7 @@ int rdma_translate_ip(const struct sockaddr *addr,
 #ifdef INET6
        case AF_INET6:
                dev = ip6_dev_find(dev_addr->net,
-                       ((const struct sockaddr_in6 *)addr)->sin6_addr);
+                       ((const struct sockaddr_in6 *)addr)->sin6_addr, 0);
                break;
 #endif
        default:
@@ -525,7 +525,7 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
                if (addr->bound_dev_if != 0) {
                        ifp = dev_get_by_index(addr->net, addr->bound_dev_if);
                } else {
-                       ifp = ip6_dev_find(addr->net, src_in->sin6_addr);
+                       ifp = ip6_dev_find(addr->net, src_in->sin6_addr, 0);
                }
 
                /* check source interface */

Modified: head/sys/ofed/drivers/infiniband/core/ib_cma.c
==============================================================================
--- head/sys/ofed/drivers/infiniband/core/ib_cma.c      Wed Dec  5 13:24:12 
2018        (r341532)
+++ head/sys/ofed/drivers/infiniband/core/ib_cma.c      Wed Dec  5 13:24:43 
2018        (r341533)
@@ -1329,7 +1329,8 @@ static bool validate_ipv6_net_dev(struct net_device *n
        struct rtentry *rte;
        bool ret;
 
-       dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr);
+       dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr,
+           net_dev->if_index);
        if (dst_dev != net_dev) {
                if (dst_dev != NULL)
                        dev_put(dst_dev);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to