bab990d812
This commit was SVN r23930. The following SVN revision numbers were found above: r23928 --> open-mpi/ompi@7394f6d167
165 строки
5.0 KiB
C
165 строки
5.0 KiB
C
/*
|
|
* Copyright (c) 2010 Cisco Systems, Inc. All rights reserved.
|
|
* Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*/
|
|
|
|
#include "opal_config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "opal/constants.h"
|
|
#include "opal/util/output.h"
|
|
#include "opal/mca/if/if.h"
|
|
|
|
static int if_solaris_ipv6_open(void);
|
|
|
|
/* Discovers Solaris IPv6 interfaces */
|
|
opal_if_base_component_t mca_if_solaris_ipv6_component = {
|
|
/* First, the mca_component_t struct containing meta information
|
|
about the component itself */
|
|
{
|
|
OPAL_IF_BASE_VERSION_2_0_0,
|
|
|
|
/* Component name and version */
|
|
"solaris_ipv6",
|
|
OPAL_MAJOR_VERSION,
|
|
OPAL_MINOR_VERSION,
|
|
OPAL_RELEASE_VERSION,
|
|
|
|
/* Component open and close functions */
|
|
if_solaris_ipv6_open,
|
|
NULL
|
|
},
|
|
{
|
|
/* This component is checkpointable */
|
|
MCA_BASE_METADATA_PARAM_CHECKPOINT
|
|
},
|
|
};
|
|
|
|
/* configure using getifaddrs(3) */
|
|
static int if_solaris_ipv6_open(void)
|
|
{
|
|
#if OPAL_WANT_IPV6
|
|
int i;
|
|
int sd;
|
|
int error;
|
|
uint16_t kindex;
|
|
struct lifnum lifnum;
|
|
struct lifconf lifconf;
|
|
struct lifreq *lifreq, lifquery;
|
|
|
|
sd = socket (AF_INET6, SOCK_DGRAM, 0);
|
|
if (sd < 0) {
|
|
opal_output (0, "opal_ifinit: unable to open IPv6 socket\n");
|
|
return OPAL_ERROR;
|
|
}
|
|
|
|
/* we only ask for IPv6; IPv4 discovery has already been done */
|
|
lifnum.lifn_family = AF_INET6;
|
|
lifnum.lifn_flags = 0;
|
|
lifnum.lifn_count = 0;
|
|
|
|
/* get the number of interfaces in the system */
|
|
error = ioctl (sd, SIOCGLIFNUM, &lifnum);
|
|
if (error < 0) {
|
|
opal_output (0,
|
|
"opal_ifinit: ioctl SIOCGLIFNUM failed with errno=%d\n", errno);
|
|
return OPAL_ERROR;
|
|
}
|
|
|
|
memset (&lifconf, 0, sizeof (struct lifconf));
|
|
memset (&lifquery, 0, sizeof (struct lifreq));
|
|
lifconf.lifc_family = AF_INET6;
|
|
lifconf.lifc_flags = 0;
|
|
lifconf.lifc_len = lifnum.lifn_count * sizeof (struct lifreq) * 2;
|
|
lifconf.lifc_buf = malloc (lifconf.lifc_len);
|
|
if (NULL == lifconf.lifc_buf) {
|
|
opal_output (0, "opal_ifinit: IPv6 discovery: malloc() failed\n");
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
}
|
|
|
|
memset (lifconf.lifc_buf, 0, lifconf.lifc_len);
|
|
|
|
error = ioctl (sd, SIOCGLIFCONF, &lifconf);
|
|
if (error < 0) {
|
|
opal_output (0,
|
|
"opal_ifinit: IPv6 SIOCGLIFCONF failed with errno=%d\n", errno);
|
|
}
|
|
|
|
for (i = 0; i + sizeof (struct lifreq) <= lifconf.lifc_len;
|
|
i += sizeof (*lifreq)) {
|
|
|
|
lifreq = (struct lifreq *)((caddr_t)lifconf.lifc_buf + i);
|
|
strncpy (lifquery.lifr_name, lifreq->lifr_name,
|
|
sizeof (lifquery.lifr_name));
|
|
|
|
/* lookup kernel index */
|
|
error = ioctl (sd, SIOCGLIFINDEX, &lifquery);
|
|
if (error < 0) {
|
|
opal_output (0,
|
|
"opal_ifinit: SIOCGLIFINDEX failed with errno=%d\n", errno);
|
|
return OPAL_ERROR;
|
|
}
|
|
kindex = lifquery.lifr_index;
|
|
|
|
/* lookup interface flags */
|
|
error = ioctl (sd, SIOCGLIFFLAGS, &lifquery);
|
|
if (error < 0) {
|
|
opal_output (0,
|
|
"opal_ifinit: SIOCGLIFFLAGS failed with errno=%d\n", errno);
|
|
return OPAL_ERROR;
|
|
}
|
|
|
|
if (AF_INET6 == lifreq->lifr_addr.ss_family) {
|
|
struct sockaddr_in6* my_addr = (struct sockaddr_in6*) &lifreq->lifr_addr;
|
|
/* we surely want to check for sin6_scope_id, but Solaris
|
|
does not set it correctly, so we have to look for
|
|
global scope. For now, global is anything which is
|
|
neither loopback nor link local.
|
|
|
|
Bug, FIXME: site-local, multicast, ... missing
|
|
Check for 2000::/3?
|
|
*/
|
|
if ( (!opal_if_retain_loopback && !IN6_IS_ADDR_LOOPBACK (&my_addr->sin6_addr)) &&
|
|
(! IN6_IS_ADDR_LINKLOCAL (&my_addr->sin6_addr))) {
|
|
/* create interface for newly found address */
|
|
opal_if_t *intf;
|
|
|
|
intf = OBJ_NEW(opal_if_t);
|
|
if (NULL == intf) {
|
|
opal_output (0,
|
|
"opal_ifinit: unable to allocate %d bytes\n",
|
|
sizeof (opal_if_t));
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
|
}
|
|
|
|
strncpy (intf->if_name, lifreq->lifr_name, IF_NAMESIZE);
|
|
intf->if_index = opal_list_get_size(&opal_if_list)+1;
|
|
memcpy(&intf->if_addr, my_addr, sizeof (*my_addr));
|
|
intf->if_mask = 64;
|
|
/* lifrq flags are uint64_t */
|
|
intf->if_flags =
|
|
(uint32_t)(0x00000000ffffffff) & lifquery.lifr_flags;
|
|
|
|
/* append to list */
|
|
opal_list_append (&opal_if_list, &(intf->super));
|
|
}
|
|
}
|
|
} /* for */
|
|
|
|
if (NULL != lifconf.lifc_buf) {
|
|
free (lifconf.lifc_buf);
|
|
}
|
|
#endif /* OPAL_WANT_IPV6 */
|
|
|
|
return OPAL_SUCCESS;
|
|
}
|
|
|
|
|