@@ -823,14 +823,21 @@ void lnet_connect_console_error(int rc, struct lnet_nid *peer_nid,
struct lnet_inetdev {
u32 li_cpt;
- u32 li_flags;
- u32 li_ipaddr;
- u32 li_netmask;
+ union {
+ struct {
+ u32 li_ipaddr;
+ u32 li_netmask;
+ };
+ u32 li_ipv6addr[4];
+ };
u32 li_index;
+ bool li_iff_master;
+ bool li_ipv6;
char li_name[IFNAMSIZ];
};
-int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns);
+int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns,
+ bool v6);
void lnet_sock_setbuf(struct socket *socket, int txbufsize, int rxbufsize);
void lnet_sock_getbuf(struct socket *socket, int *txbufsize, int *rxbufsize);
int lnet_sock_getaddr(struct socket *socket, bool remote,
@@ -3034,7 +3034,7 @@ static int kiblnd_startup(struct lnet_ni *ni)
goto failed;
}
- rc = lnet_inet_enumerate(&ifaces, ni->ni_net_ns);
+ rc = lnet_inet_enumerate(&ifaces, ni->ni_net_ns, false);
if (rc < 0)
goto failed;
@@ -3062,7 +3062,7 @@ static int kiblnd_startup(struct lnet_ni *ni)
ibdev->ibd_ifip = ifaces[i].li_ipaddr;
strlcpy(ibdev->ibd_ifname, ifaces[i].li_name,
sizeof(ibdev->ibd_ifname));
- ibdev->ibd_can_failover = !!(ifaces[i].li_flags & IFF_MASTER);
+ ibdev->ibd_can_failover = ifaces[i].li_iff_master;
INIT_LIST_HEAD(&ibdev->ibd_nets);
INIT_LIST_HEAD(&ibdev->ibd_list); /* not yet in kib_devs */
@@ -1744,11 +1744,13 @@ static int ksocknal_push(struct lnet_ni *ni, struct lnet_processid *id)
iface = &net->ksnn_interface;
sa = (void *)&iface->ksni_addr;
- if (sa->sin_family == AF_INET)
+ if (sa->sin_family == AF_INET) {
data->ioc_u32[0] = ntohl(sa->sin_addr.s_addr);
- else
+ data->ioc_u32[1] = iface->ksni_netmask;
+ } else {
data->ioc_u32[0] = 0xFFFFFFFF;
- data->ioc_u32[1] = iface->ksni_netmask;
+ data->ioc_u32[1] = 0;
+ }
data->ioc_u32[2] = iface->ksni_npeers;
data->ioc_u32[3] = iface->ksni_nroutes;
}
@@ -2443,7 +2445,6 @@ static int ksocknal_inetaddr_event(struct notifier_block *unused,
struct ksock_net *net;
struct ksock_interface *ksi = NULL;
struct lnet_inetdev *ifaces = NULL;
- struct sockaddr_in *sa;
int i = 0;
int rc;
@@ -2464,7 +2465,7 @@ static int ksocknal_inetaddr_event(struct notifier_block *unused,
ksocknal_tunables_setup(ni);
- rc = lnet_inet_enumerate(&ifaces, ni->ni_net_ns);
+ rc = lnet_inet_enumerate(&ifaces, ni->ni_net_ns, true);
if (rc < 0)
goto fail_1;
@@ -2485,11 +2486,26 @@ static int ksocknal_inetaddr_event(struct notifier_block *unused,
ni->ni_dev_cpt = ifaces[i].li_cpt;
ksi->ksni_index = ifaces[i].li_index;
- sa = (void *)&ksi->ksni_addr;
- memset(sa, 0, sizeof(*sa));
- sa->sin_family = AF_INET;
- sa->sin_addr.s_addr = htonl(ifaces[i].li_ipaddr);
- ksi->ksni_netmask = ifaces[i].li_netmask;
+ if (ifaces[i].li_ipv6) {
+ struct sockaddr_in6 *sa;
+ sa = (void *)&ksi->ksni_addr;
+ memset(sa, 0, sizeof(*sa));
+ sa->sin6_family = AF_INET6;
+ memcpy(&sa->sin6_addr, ifaces[i].li_ipv6addr,
+ sizeof(struct in6_addr));
+ ni->ni_nid.nid_size = sizeof(struct in6_addr) - 4;
+ memcpy(&ni->ni_nid.nid_addr, ifaces[i].li_ipv6addr,
+ sizeof(struct in6_addr));
+ } else {
+ struct sockaddr_in *sa;
+ sa = (void *)&ksi->ksni_addr;
+ memset(sa, 0, sizeof(*sa));
+ sa->sin_family = AF_INET;
+ sa->sin_addr.s_addr = htonl(ifaces[i].li_ipaddr);
+ ksi->ksni_netmask = ifaces[i].li_netmask;
+ ni->ni_nid.nid_size = 4 - 4;
+ ni->ni_nid.nid_addr[0] = sa->sin_addr.s_addr;
+ }
strlcpy(ksi->ksni_name, ifaces[i].li_name, sizeof(ksi->ksni_name));
/* call it before add it to ksocknal_data.ksnd_nets */
@@ -2497,9 +2513,6 @@ static int ksocknal_inetaddr_event(struct notifier_block *unused,
if (rc)
goto fail_1;
- LASSERT(ksi);
- LASSERT(ksi->ksni_addr.ss_family == AF_INET);
- ni->ni_nid.nid_addr[0] = ((struct sockaddr_in *)&ksi->ksni_addr)->sin_addr.s_addr;
list_add(&net->ksnn_list, &ksocknal_data.ksnd_nets);
net->ksnn_ni = ni;
ksocknal_data.ksnd_nnets++;
@@ -31,11 +31,12 @@
*/
#define DEBUG_SUBSYSTEM S_LNET
+#include <linux/ctype.h>
+#include <linux/inetdevice.h>
#include <linux/nsproxy.h>
#include <net/net_namespace.h>
-#include <linux/ctype.h>
#include <linux/lnet/lib-lnet.h>
-#include <linux/inetdevice.h>
+#include <net/addrconf.h>
struct lnet_text_buf { /* tmp struct for parsing routes */
struct list_head ltb_list; /* stash on lists */
@@ -1488,7 +1489,7 @@ struct lnet_ni *
return count;
}
-int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
+int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns, bool v6)
{
struct lnet_inetdev *ifaces = NULL;
struct net_device *dev;
@@ -1500,6 +1501,8 @@ int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
int flags = dev_get_flags(dev);
const struct in_ifaddr *ifa;
struct in_device *in_dev;
+ struct inet6_dev *in6_dev;
+ const struct inet6_ifaddr *ifa6;
int node_id;
int cpt;
@@ -1511,15 +1514,18 @@ int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
dev->name);
continue;
}
+
+ node_id = dev_to_node(&dev->dev);
+ cpt = cfs_cpt_of_node(lnet_cpt_table(), node_id);
+
in_dev = __in_dev_get_rtnl(dev);
if (!in_dev) {
- CWARN("lnet: Interface %s has no IPv4 status.\n",
- dev->name);
- continue;
+ if (!v6)
+ CWARN("lnet: Interface %s has no IPv4 status.\n",
+ dev->name);
+ goto try_v6;
}
- node_id = dev_to_node(&dev->dev);
- cpt = cfs_cpt_of_node(lnet_cpt_table(), node_id);
in_dev_for_each_ifa_rtnl(ifa, in_dev) {
if (nip >= nalloc) {
struct lnet_inetdev *tmp;
@@ -1537,7 +1543,8 @@ int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
}
ifaces[nip].li_cpt = cpt;
- ifaces[nip].li_flags = flags;
+ ifaces[nip].li_iff_master = !!(flags & IFF_MASTER);
+ ifaces[nip].li_ipv6 = false;
ifaces[nip].li_index = dev->ifindex;
ifaces[nip].li_ipaddr = ntohl(ifa->ifa_local);
ifaces[nip].li_netmask = ntohl(ifa->ifa_mask);
@@ -1545,6 +1552,53 @@ int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
sizeof(ifaces[nip].li_name));
nip++;
}
+ try_v6:
+ if (!v6)
+ continue;
+#if IS_ENABLED(CONFIG_IPV6)
+ in6_dev = __in6_dev_get(dev);
+ if (!in6_dev) {
+ if (!in_dev)
+ CWARN("lnet: Interface %s has no IP status.\n",
+ dev->name);
+ continue;
+ }
+
+ list_for_each_entry_rcu(ifa6, &in6_dev->addr_list, if_list) {
+ if (ifa6->flags & IFA_F_TEMPORARY)
+ continue;
+ if (nip >= nalloc) {
+ struct lnet_inetdev *tmp;
+
+ nalloc += LNET_INTERFACES_NUM;
+ tmp = krealloc(ifaces, nalloc * sizeof(*tmp),
+ GFP_KERNEL);
+ if (!tmp) {
+ kfree(ifaces);
+ ifaces = NULL;
+ nip = -ENOMEM;
+ goto unlock_rtnl;
+ }
+ ifaces = tmp;
+ }
+
+ ifaces[nip].li_cpt = cpt;
+ ifaces[nip].li_iff_master = !!(flags & IFF_MASTER);
+ ifaces[nip].li_ipv6 = true;
+ ifaces[nip].li_index = dev->ifindex;
+ memcpy(ifaces[nip].li_ipv6addr,
+ &ifa6->addr, sizeof(struct in6_addr));
+ strlcpy(ifaces[nip].li_name, dev->name,
+ sizeof(ifaces[nip].li_name));
+ nip++;
+ /* As different IPv6 addresses don't have unique
+ * labels, it is safest just to use the first
+ * and ignore the rest.
+ */
+ break;
+ }
+#endif /* IS_ENABLED(CONFIG_IPV6) */
+
}
unlock_rtnl:
rtnl_unlock();
@@ -1569,9 +1623,10 @@ int lnet_inet_enumerate(struct lnet_inetdev **dev_list, struct net *ns)
int i;
if (current->nsproxy && current->nsproxy->net_ns)
- nip = lnet_inet_enumerate(&ifaces, current->nsproxy->net_ns);
+ nip = lnet_inet_enumerate(&ifaces, current->nsproxy->net_ns,
+ false);
else
- nip = lnet_inet_enumerate(&ifaces, &init_net);
+ nip = lnet_inet_enumerate(&ifaces, &init_net, false);
if (nip < 0) {
if (nip != -ENOENT) {
LCONSOLE_ERROR_MSG(0x117,