Whamcloud - gitweb
LU-10391 socklnd: support IPv6 in ksocknal_ip2index() 70/48570/2
authorMr NeilBrown <neilb@suse.de>
Thu, 15 Sep 2022 05:09:59 +0000 (15:09 +1000)
committerOleg Drokin <green@whamcloud.com>
Tue, 4 Oct 2022 19:33:07 +0000 (19:33 +0000)
ksocknal_ip2index() can now find the interface index for an IPv6
address.

Test-Parameters: trivial testlist=sanity-lnet
Test-Parameters: serverversion=2.12 serverdistro=el7.9 testlist=runtests
Test-Parameters: clientversion=2.12 testlist=runtests
Signed-off-by: Mr NeilBrown <neilb@suse.de>
Change-Id: Idd6bee5c9db417b05f8208ab5ab309f4c8404d54
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48570
Reviewed-by: jsimmons <jsimmons@infradead.org>
Reviewed-by: Serguei Smirnov <ssmirnov@whamcloud.com>
Reviewed-by: Frank Sehr <fsehr@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lnet/klnds/socklnd/socklnd.c

index b7e8240..a71364c 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/inetdevice.h>
 #include "socklnd.h"
 #include <linux/sunrpc/addr.h>
+#include <net/addrconf.h>
 
 static const struct lnet_lnd the_ksocklnd;
 struct ksock_nal_data ksocknal_data;
@@ -78,8 +79,7 @@ static int ksocknal_ip2index(struct sockaddr *addr, struct lnet_ni *ni)
        int ret = -1;
        DECLARE_CONST_IN_IFADDR(ifa);
 
-       if (addr->sa_family != AF_INET)
-               /* No IPv6 support yet */
+       if (addr->sa_family != AF_INET && addr->sa_family != AF_INET6)
                return ret;
 
        rcu_read_lock();
@@ -93,16 +93,38 @@ static int ksocknal_ip2index(struct sockaddr *addr, struct lnet_ni *ni)
                if (!(flags & IFF_UP))
                        continue;
 
-               in_dev = __in_dev_get_rcu(dev);
-               if (!in_dev)
-                       continue;
+               switch (addr->sa_family) {
+               case AF_INET:
+                       in_dev = __in_dev_get_rcu(dev);
+                       if (!in_dev)
+                               continue;
+
+                       in_dev_for_each_ifa_rcu(ifa, in_dev) {
+                               if (ifa->ifa_local ==
+                                   ((struct sockaddr_in *)addr)->sin_addr.s_addr)
+                                       ret = dev->ifindex;
+                       }
+                       endfor_ifa(in_dev);
+                       break;
+#if IS_ENABLED(CONFIG_IPV6)
+               case AF_INET6: {
+                       struct inet6_dev *in6_dev;
+                       const struct inet6_ifaddr *ifa6;
+                       struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)addr;
+
+                       in6_dev = __in6_dev_get(dev);
+                       if (!in6_dev)
+                               continue;
 
-               in_dev_for_each_ifa_rcu(ifa, in_dev) {
-                       if (ifa->ifa_local ==
-                           ((struct sockaddr_in *)addr)->sin_addr.s_addr)
-                               ret = dev->ifindex;
+                       list_for_each_entry_rcu(ifa6, &in6_dev->addr_list, if_list) {
+                               if (ipv6_addr_cmp(&ifa6->addr,
+                                                &addr6->sin6_addr) == 0)
+                                       ret = dev->ifindex;
+                       }
+                       break;
+                       }
+#endif /* IS_ENABLED(CONFIG_IPV6) */
                }
-               endfor_ifa(in_dev);
                if (ret >= 0)
                        break;
        }