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,
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;
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 */
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;
}
struct ksock_net *net;
struct ksock_interface *ksi = NULL;
struct lnet_inetdev *ifaces = NULL;
- struct sockaddr_in *sa;
int i = 0;
int rc;
- LASSERT (ni->ni_net->net_lnd == &the_ksocklnd);
- if (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING) {
- rc = ksocknal_base_startup();
- if (rc != 0)
- return rc;
- }
+ LASSERT (ni->ni_net->net_lnd == &the_ksocklnd);
+ if (ksocknal_data.ksnd_init == SOCKNAL_INIT_NOTHING) {
+ rc = ksocknal_base_startup();
+ if (rc != 0)
+ return rc;
+ }
LIBCFS_ALLOC(net, sizeof(*net));
if (net == NULL)
goto fail_0;
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;
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 */
if (rc != 0)
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++;
#include <linux/nsproxy.h>
#include <net/net_namespace.h>
#include <lnet/lib-lnet.h>
+#include <net/addrconf.h>
/* tmp struct for parsing routes */
struct lnet_text_buf {
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;
for_each_netdev(ns, dev) {
int flags = dev_get_flags(dev);
struct in_device *in_dev;
+ struct inet6_dev *in6_dev;
+ const struct inet6_ifaddr *ifa6;
int node_id;
int cpt;
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;
}
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);
nip++;
}
endfor_ifa(in_dev);
+
+ 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();
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,