2013-07-19 22:13:58 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
|
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2011 The University of Tennessee and The University
|
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
|
|
|
* University of Stuttgart. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
|
|
|
* Copyright (c) 2006 Sandia National Laboratories. All rights
|
|
|
|
* reserved.
|
2014-02-26 07:46:50 +00:00
|
|
|
* Copyright (c) 2013-2014 Cisco Systems, Inc. All rights reserved.
|
As per the email discussion, revise the sparse handling of hostnames so that we avoid potential infinite loops while allowing large-scale users to improve their startup time:
* add a new MCA param orte_hostname_cutoff to specify the number of nodes at which we stop including hostnames. This defaults to INT_MAX => always include hostnames. If a value is given, then we will include hostnames for any allocation smaller than the given limit.
* remove ompi_proc_get_hostname. Replace all occurrences with a direct link to ompi_proc_t's proc_hostname, protected by appropriate "if NULL"
* modify the OMPI-ORTE integration component so that any call to modex_recv automatically loads the ompi_proc_t->proc_hostname field as well as returning the requested info. Thus, any process whose modex info you retrieve will automatically receive the hostname. Note that on-demand retrieval is still enabled - i.e., if we are running under direct launch with PMI, the hostname will be fetched upon first call to modex_recv, and then the ompi_proc_t->proc_hostname field will be loaded
* removed a stale MCA param "mpi_keep_peer_hostnames" that was no longer used anywhere in the code base
* added an envar lookup in ess/pmi for the number of nodes in the allocation. Sadly, PMI itself doesn't provide that info, so we have to get it a different way. Currently, we support PBS-based systems and SLURM - for any other, rank0 will emit a warning and we assume max number of daemons so we will always retain hostnames
This commit was SVN r29052.
2013-08-20 18:59:36 +00:00
|
|
|
* Copyright (c) 2013 Intel, Inc. All rights reserved
|
2013-07-19 22:13:58 +00:00
|
|
|
* $COPYRIGHT$
|
|
|
|
*
|
|
|
|
* Additional copyrights may follow
|
|
|
|
*
|
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ompi_config.h"
|
|
|
|
|
|
|
|
#include <infiniband/verbs.h>
|
|
|
|
|
|
|
|
#include "opal_stdint.h"
|
|
|
|
#include "opal/util/arch.h"
|
2013-07-22 17:28:23 +00:00
|
|
|
#include "opal/util/show_help.h"
|
2013-07-19 22:13:58 +00:00
|
|
|
|
2013-07-22 17:28:23 +00:00
|
|
|
#include "ompi/mca/rte/rte.h"
|
2013-07-19 22:13:58 +00:00
|
|
|
#include "ompi/runtime/ompi_module_exchange.h"
|
|
|
|
#include "ompi/constants.h"
|
|
|
|
|
|
|
|
#include "btl_usnic.h"
|
|
|
|
#include "btl_usnic_proc.h"
|
|
|
|
#include "btl_usnic_endpoint.h"
|
|
|
|
#include "btl_usnic_module.h"
|
|
|
|
#include "btl_usnic_util.h"
|
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
/* larger weight values are more desirable (i.e., worth, not cost) */
|
|
|
|
enum conn_weight {
|
|
|
|
WEIGHT_UNREACHABLE = -1,
|
|
|
|
WEIGHT_DIFF_NET = 0,
|
|
|
|
WEIGHT_SAME_NET = 1
|
|
|
|
};
|
2013-07-19 22:13:58 +00:00
|
|
|
|
|
|
|
static void proc_construct(ompi_btl_usnic_proc_t* proc)
|
|
|
|
{
|
|
|
|
proc->proc_ompi = 0;
|
|
|
|
proc->proc_modex = NULL;
|
|
|
|
proc->proc_modex_count = 0;
|
|
|
|
proc->proc_modex_claimed = NULL;
|
|
|
|
proc->proc_endpoints = NULL;
|
|
|
|
proc->proc_endpoint_count = 0;
|
2014-02-26 07:44:49 +00:00
|
|
|
proc->proc_ep_weights = NULL;
|
2013-07-19 22:13:58 +00:00
|
|
|
|
|
|
|
/* add to list of all proc instance */
|
|
|
|
opal_list_append(&mca_btl_usnic_component.usnic_procs, &proc->super);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void proc_destruct(ompi_btl_usnic_proc_t* proc)
|
|
|
|
{
|
2014-02-26 07:44:49 +00:00
|
|
|
uint32_t i;
|
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/* remove from list of all proc instances */
|
|
|
|
opal_list_remove_item(&mca_btl_usnic_component.usnic_procs, &proc->super);
|
|
|
|
|
|
|
|
/* release resources */
|
|
|
|
if (NULL != proc->proc_modex) {
|
|
|
|
free(proc->proc_modex);
|
|
|
|
proc->proc_modex = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NULL != proc->proc_modex_claimed) {
|
|
|
|
free(proc->proc_modex_claimed);
|
|
|
|
proc->proc_modex_claimed = NULL;
|
|
|
|
}
|
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
if (NULL != proc->proc_ep_weights) {
|
|
|
|
for (i = 0; i < mca_btl_usnic_component.num_modules; ++i) {
|
|
|
|
free(proc->proc_ep_weights[i]);
|
|
|
|
proc->proc_ep_weights[i] = NULL;
|
|
|
|
}
|
|
|
|
free(proc->proc_ep_weights);
|
|
|
|
proc->proc_ep_weights = NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/* Release all endpoints associated with this proc */
|
|
|
|
if (NULL != proc->proc_endpoints) {
|
|
|
|
free(proc->proc_endpoints);
|
|
|
|
proc->proc_endpoints = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
OBJ_CLASS_INSTANCE(ompi_btl_usnic_proc_t,
|
|
|
|
opal_list_item_t,
|
|
|
|
proc_construct,
|
|
|
|
proc_destruct);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for an existing usnic process instance based on the
|
|
|
|
* associated ompi_proc_t instance.
|
|
|
|
*/
|
|
|
|
ompi_btl_usnic_proc_t *
|
|
|
|
ompi_btl_usnic_proc_lookup_ompi(ompi_proc_t* ompi_proc)
|
|
|
|
{
|
|
|
|
ompi_btl_usnic_proc_t* usnic_proc;
|
|
|
|
|
|
|
|
for (usnic_proc = (ompi_btl_usnic_proc_t*)
|
|
|
|
opal_list_get_first(&mca_btl_usnic_component.usnic_procs);
|
|
|
|
usnic_proc != (ompi_btl_usnic_proc_t*)
|
|
|
|
opal_list_get_end(&mca_btl_usnic_component.usnic_procs);
|
|
|
|
usnic_proc = (ompi_btl_usnic_proc_t*)
|
|
|
|
opal_list_get_next(usnic_proc)) {
|
|
|
|
if (usnic_proc->proc_ompi == ompi_proc) {
|
|
|
|
return usnic_proc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2013-07-22 17:28:23 +00:00
|
|
|
* Look for an existing usnic proc based on a hashed RTE process
|
2013-07-19 22:13:58 +00:00
|
|
|
* name.
|
|
|
|
*/
|
|
|
|
ompi_btl_usnic_endpoint_t *
|
|
|
|
ompi_btl_usnic_proc_lookup_endpoint(ompi_btl_usnic_module_t *receiver,
|
2013-07-22 17:28:23 +00:00
|
|
|
uint64_t sender_hashed_rte_name)
|
2013-07-19 22:13:58 +00:00
|
|
|
{
|
|
|
|
ompi_btl_usnic_proc_t *proc;
|
|
|
|
ompi_btl_usnic_endpoint_t *endpoint;
|
2014-02-26 07:46:50 +00:00
|
|
|
opal_list_item_t *item;
|
2013-07-19 22:13:58 +00:00
|
|
|
|
2014-02-26 07:46:50 +00:00
|
|
|
MSGDEBUG1_OUT("lookup_endpoint: recvmodule=%p sendhash=0x%" PRIx64,
|
|
|
|
(void *)receiver, sender_hashed_rte_name);
|
2013-07-19 22:13:58 +00:00
|
|
|
|
2014-02-26 07:46:50 +00:00
|
|
|
for (item = opal_list_get_first(&receiver->all_endpoints);
|
|
|
|
item != opal_list_get_end(&receiver->all_endpoints);
|
|
|
|
item = opal_list_get_next(item)) {
|
|
|
|
endpoint = container_of(item, ompi_btl_usnic_endpoint_t,
|
|
|
|
endpoint_endpoint_li);
|
|
|
|
proc = endpoint->endpoint_proc;
|
|
|
|
if (ompi_rte_hash_name(&proc->proc_ompi->proc_name) ==
|
|
|
|
sender_hashed_rte_name) {
|
|
|
|
MSGDEBUG1_OUT("lookup_endpoint: matched endpoint=%p",
|
|
|
|
(void *)endpoint);
|
2013-07-19 22:13:58 +00:00
|
|
|
return endpoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Didn't find it */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create an ompi_btl_usnic_proc_t and initialize it with modex info
|
|
|
|
* and an empty array of endpoints.
|
|
|
|
*/
|
|
|
|
static ompi_btl_usnic_proc_t *create_proc(ompi_proc_t *ompi_proc)
|
|
|
|
{
|
|
|
|
ompi_btl_usnic_proc_t *proc = NULL;
|
|
|
|
size_t size;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* Create the proc if it doesn't already exist */
|
|
|
|
proc = OBJ_NEW(ompi_btl_usnic_proc_t);
|
|
|
|
if (NULL == proc) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize number of peers */
|
|
|
|
proc->proc_endpoint_count = 0;
|
|
|
|
proc->proc_ompi = ompi_proc;
|
|
|
|
|
|
|
|
/* query for the peer address info */
|
|
|
|
rc = ompi_modex_recv(&mca_btl_usnic_component.super.btl_version,
|
|
|
|
ompi_proc, (void*)&proc->proc_modex,
|
|
|
|
&size);
|
|
|
|
|
|
|
|
if (OMPI_SUCCESS != rc) {
|
2013-07-22 17:28:23 +00:00
|
|
|
opal_show_help("help-mpi-btl-usnic.txt", "internal error during init",
|
2013-07-19 22:13:58 +00:00
|
|
|
true,
|
2013-07-22 17:28:23 +00:00
|
|
|
ompi_process_info.nodename,
|
2013-07-19 22:13:58 +00:00
|
|
|
"<none>", 0,
|
|
|
|
"ompi_modex_recv() failed", __FILE__, __LINE__,
|
|
|
|
opal_strerror(rc));
|
2013-08-01 16:56:15 +00:00
|
|
|
OBJ_RELEASE(proc);
|
2013-07-19 22:13:58 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((size % sizeof(ompi_btl_usnic_addr_t)) != 0) {
|
|
|
|
char msg[1024];
|
|
|
|
|
|
|
|
snprintf(msg, sizeof(msg),
|
|
|
|
"sizeof(modex for peer %s data) == %d, expected multiple of %d",
|
2013-07-22 17:28:23 +00:00
|
|
|
OMPI_NAME_PRINT(&ompi_proc->proc_name),
|
2013-07-19 22:13:58 +00:00
|
|
|
(int) size, (int) sizeof(ompi_btl_usnic_addr_t));
|
2013-07-22 17:28:23 +00:00
|
|
|
opal_show_help("help-mpi-btl-usnic.txt", "internal error during init",
|
2013-07-19 22:13:58 +00:00
|
|
|
true,
|
2013-07-22 17:28:23 +00:00
|
|
|
ompi_process_info.nodename,
|
2013-07-19 22:13:58 +00:00
|
|
|
"<none>", 0,
|
|
|
|
"invalid modex data", __FILE__, __LINE__,
|
|
|
|
msg);
|
|
|
|
|
|
|
|
OBJ_RELEASE(proc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc->proc_modex_count = size / sizeof(ompi_btl_usnic_addr_t);
|
|
|
|
if (0 == proc->proc_modex_count) {
|
|
|
|
proc->proc_endpoints = NULL;
|
|
|
|
OBJ_RELEASE(proc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc->proc_modex_claimed = (bool*)
|
|
|
|
calloc(proc->proc_modex_count, sizeof(bool));
|
|
|
|
if (NULL == proc->proc_modex_claimed) {
|
2013-07-22 17:28:23 +00:00
|
|
|
OMPI_ERROR_LOG(OMPI_ERR_OUT_OF_RESOURCE);
|
2013-07-19 22:13:58 +00:00
|
|
|
OBJ_RELEASE(proc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
proc->proc_endpoints = (mca_btl_base_endpoint_t**)
|
|
|
|
calloc(proc->proc_modex_count, sizeof(mca_btl_base_endpoint_t*));
|
|
|
|
if (NULL == proc->proc_endpoints) {
|
2013-07-22 17:28:23 +00:00
|
|
|
OMPI_ERROR_LOG(OMPI_ERR_OUT_OF_RESOURCE);
|
2013-07-19 22:13:58 +00:00
|
|
|
OBJ_RELEASE(proc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return proc;
|
|
|
|
}
|
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
/* Compare the addresses of the local interface corresponding to module and the
|
|
|
|
* remote interface corresponding to proc_modex_addr. Returns a weight value. */
|
|
|
|
static enum conn_weight compute_weight(
|
|
|
|
ompi_btl_usnic_module_t *module,
|
|
|
|
ompi_btl_usnic_addr_t *proc_modex_addr)
|
|
|
|
{
|
|
|
|
char my_ip_string[INET_ADDRSTRLEN], peer_ip_string[INET_ADDRSTRLEN];
|
|
|
|
uint32_t mynet, peernet;
|
|
|
|
|
|
|
|
inet_ntop(AF_INET, &module->if_ipv4_addr,
|
|
|
|
my_ip_string, sizeof(my_ip_string));
|
|
|
|
inet_ntop(AF_INET, &proc_modex_addr->ipv4_addr,
|
|
|
|
peer_ip_string, sizeof(peer_ip_string));
|
|
|
|
|
|
|
|
/* Just compare the CIDR-masked IP address to see if they're on
|
|
|
|
the same network. If so, we're good. */
|
|
|
|
mynet = ompi_btl_usnic_get_ipv4_subnet(module->if_ipv4_addr,
|
|
|
|
module->if_cidrmask);
|
|
|
|
peernet = ompi_btl_usnic_get_ipv4_subnet(proc_modex_addr->ipv4_addr,
|
|
|
|
proc_modex_addr->cidrmask);
|
|
|
|
|
|
|
|
opal_output_verbose(5, USNIC_OUT,
|
|
|
|
"btl:usnic:%s: checking my IP address/subnet (%s/%d) vs. peer (%s/%d): %s",
|
|
|
|
__func__, my_ip_string, module->if_cidrmask,
|
|
|
|
peer_ip_string, proc_modex_addr->cidrmask,
|
|
|
|
(mynet == peernet ? "match" : "DO NOT match"));
|
|
|
|
|
|
|
|
if (mynet == peernet) {
|
|
|
|
return WEIGHT_SAME_NET;
|
|
|
|
} else {
|
|
|
|
return WEIGHT_DIFF_NET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/*
|
|
|
|
* For a specific module, see if this proc has matching address/modex
|
|
|
|
* info. If so, create an endpoint and return it.
|
|
|
|
*/
|
|
|
|
static int match_modex(ompi_btl_usnic_module_t *module,
|
|
|
|
ompi_btl_usnic_proc_t *proc)
|
|
|
|
{
|
2014-02-26 07:44:49 +00:00
|
|
|
size_t i, j;
|
|
|
|
int8_t **weights;
|
|
|
|
uint32_t num_modules;
|
|
|
|
int modex_index = -1;
|
|
|
|
|
|
|
|
num_modules = mca_btl_usnic_component.num_modules;
|
|
|
|
|
|
|
|
opal_output_verbose(20, USNIC_OUT, "btl:usnic:%s: module=%p proc=%p with dimensions %d x %d",
|
|
|
|
__func__, (void *)module, (void *)proc,
|
|
|
|
num_modules, (int)proc->proc_modex_count);
|
|
|
|
|
|
|
|
/* We compute an interface match-up weights table once for each
|
|
|
|
* (module,proc) pair and cache it in the proc. Store per-proc instead of
|
|
|
|
* per-module, since MPI dynamic process routines can add procs but not new
|
|
|
|
* modules. */
|
|
|
|
if (NULL == proc->proc_ep_weights) {
|
|
|
|
proc->proc_ep_weights = malloc(num_modules *
|
|
|
|
sizeof(*proc->proc_ep_weights));
|
|
|
|
if (NULL == proc->proc_ep_weights) {
|
|
|
|
OMPI_ERROR_LOG(OMPI_ERR_OUT_OF_RESOURCE);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
proc->proc_ep_max_weight = WEIGHT_UNREACHABLE;
|
|
|
|
|
|
|
|
weights = proc->proc_ep_weights;
|
|
|
|
|
|
|
|
for (i = 0; i < num_modules; ++i) {
|
|
|
|
weights[i] = malloc(proc->proc_modex_count * sizeof(*weights[i]));
|
|
|
|
if (NULL == weights[i]) {
|
|
|
|
OMPI_ERROR_LOG(OMPI_ERR_OUT_OF_RESOURCE);
|
2013-07-19 22:13:58 +00:00
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
/* free everything allocated so far */
|
|
|
|
for (j = 0; j < i; ++j) {
|
|
|
|
free(proc->proc_ep_weights[j]);
|
|
|
|
}
|
|
|
|
free(proc->proc_ep_weights);
|
|
|
|
return -1;
|
2013-07-19 22:13:58 +00:00
|
|
|
}
|
2014-02-26 07:44:49 +00:00
|
|
|
|
|
|
|
/* compute all weights */
|
|
|
|
for (j = 0; j < proc->proc_modex_count; ++j) {
|
|
|
|
weights[i][j] = compute_weight(mca_btl_usnic_component.usnic_active_modules[i],
|
|
|
|
&proc->proc_modex[j]);
|
|
|
|
if (!mca_btl_usnic_component.use_udp &&
|
|
|
|
WEIGHT_DIFF_NET == weights[i][j]) {
|
|
|
|
/* UDP is required for routability */
|
|
|
|
weights[i][j] = WEIGHT_UNREACHABLE;
|
|
|
|
}
|
|
|
|
if (weights[i][j] > proc->proc_ep_max_weight) {
|
|
|
|
proc->proc_ep_max_weight = weights[i][j];
|
|
|
|
}
|
2013-07-19 22:13:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
if (WEIGHT_UNREACHABLE == proc->proc_ep_max_weight) {
|
|
|
|
opal_output_verbose(5, USNIC_OUT, "btl:usnic:%s: unable to find any valid interface pairs for proc %s",
|
|
|
|
__func__, OMPI_NAME_PRINT(&proc->proc_ompi->proc_name));
|
2013-07-19 22:13:58 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
weights = proc->proc_ep_weights;
|
|
|
|
|
|
|
|
/* Each module can claim an address in the proc's modex info that no other
|
|
|
|
* local module is using. Take the first maximal interface pairing where
|
|
|
|
* the remote interface is not yet claimed. If unclaimed remote interfaces
|
|
|
|
* remain but their pairings are non-maximal, they will not be used.
|
|
|
|
*
|
|
|
|
* This code relies on the order of modules on a local side matching the
|
|
|
|
* order of the modex entries that we send around, otherwise both sides may
|
|
|
|
* not agree on a bidirectional connection. It also assumes that add_procs
|
|
|
|
* will be invoked on the local modules in that same order, for the same
|
|
|
|
* reason. If those assumptions do not hold, we will need to canonicalize
|
|
|
|
* this match ordering somehow, probably by (jobid,vpid) pair or by the
|
|
|
|
* interface MAC or IP address. */
|
|
|
|
for (i = 0; i < num_modules; ++i) {
|
|
|
|
if (mca_btl_usnic_component.usnic_active_modules[i] == module) {
|
|
|
|
for (j = 0; j < proc->proc_modex_count; ++j) {
|
|
|
|
if (!proc->proc_modex_claimed[j] &&
|
|
|
|
weights[i][j] == proc->proc_ep_max_weight) {
|
|
|
|
opal_output_verbose(5, USNIC_OUT,
|
|
|
|
"module[%d] (%p) claiming endpoint[%d] on proc %p",
|
|
|
|
(int)i, (void *)module, (int)j,
|
|
|
|
(void *)proc);
|
|
|
|
modex_index = j;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/* If MTU does not match, throw an error */
|
2014-02-26 07:44:49 +00:00
|
|
|
if (modex_index >= 0 &&
|
|
|
|
proc->proc_modex[modex_index].mtu != module->if_mtu) {
|
2013-07-22 17:28:23 +00:00
|
|
|
opal_show_help("help-mpi-btl-usnic.txt", "MTU mismatch",
|
As per the email discussion, revise the sparse handling of hostnames so that we avoid potential infinite loops while allowing large-scale users to improve their startup time:
* add a new MCA param orte_hostname_cutoff to specify the number of nodes at which we stop including hostnames. This defaults to INT_MAX => always include hostnames. If a value is given, then we will include hostnames for any allocation smaller than the given limit.
* remove ompi_proc_get_hostname. Replace all occurrences with a direct link to ompi_proc_t's proc_hostname, protected by appropriate "if NULL"
* modify the OMPI-ORTE integration component so that any call to modex_recv automatically loads the ompi_proc_t->proc_hostname field as well as returning the requested info. Thus, any process whose modex info you retrieve will automatically receive the hostname. Note that on-demand retrieval is still enabled - i.e., if we are running under direct launch with PMI, the hostname will be fetched upon first call to modex_recv, and then the ompi_proc_t->proc_hostname field will be loaded
* removed a stale MCA param "mpi_keep_peer_hostnames" that was no longer used anywhere in the code base
* added an envar lookup in ess/pmi for the number of nodes in the allocation. Sadly, PMI itself doesn't provide that info, so we have to get it a different way. Currently, we support PBS-based systems and SLURM - for any other, rank0 will emit a warning and we assume max number of daemons so we will always retain hostnames
This commit was SVN r29052.
2013-08-20 18:59:36 +00:00
|
|
|
true,
|
|
|
|
ompi_process_info.nodename,
|
|
|
|
ibv_get_device_name(module->device),
|
|
|
|
module->port_num,
|
|
|
|
module->if_mtu,
|
|
|
|
(NULL == proc->proc_ompi->proc_hostname) ?
|
|
|
|
"unknown" : proc->proc_ompi->proc_hostname,
|
|
|
|
proc->proc_modex[i].mtu);
|
2013-07-19 22:13:58 +00:00
|
|
|
return -1;
|
2014-02-26 07:44:49 +00:00
|
|
|
}
|
2013-07-19 22:13:58 +00:00
|
|
|
|
2014-02-26 07:44:49 +00:00
|
|
|
return modex_index;
|
2013-07-19 22:13:58 +00:00
|
|
|
}
|
2014-02-26 07:44:49 +00:00
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/*
|
|
|
|
* Create an endpoint and claim the matched modex slot
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
ompi_btl_usnic_create_endpoint(ompi_btl_usnic_module_t *module,
|
|
|
|
ompi_btl_usnic_proc_t *proc,
|
|
|
|
ompi_btl_usnic_endpoint_t **endpoint_o)
|
|
|
|
{
|
|
|
|
int modex_index;
|
|
|
|
struct ibv_ah_attr ah_attr;
|
|
|
|
ompi_btl_usnic_endpoint_t *endpoint;
|
|
|
|
|
|
|
|
/* look for matching modex info */
|
|
|
|
modex_index = match_modex(module, proc);
|
|
|
|
if (modex_index < 0) {
|
|
|
|
opal_output_verbose(5, USNIC_OUT,
|
|
|
|
"btl:usnic:create_endpoint: did not find usnic modex info for peer %s",
|
2013-07-22 17:28:23 +00:00
|
|
|
OMPI_NAME_PRINT(&proc->proc_ompi->proc_name));
|
2013-07-19 22:13:58 +00:00
|
|
|
return OMPI_ERR_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
endpoint = OBJ_NEW(ompi_btl_usnic_endpoint_t);
|
|
|
|
if (NULL == endpoint) {
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initalize the endpoint */
|
|
|
|
endpoint->endpoint_module = module;
|
|
|
|
endpoint->endpoint_remote_addr = proc->proc_modex[modex_index];
|
|
|
|
|
2013-08-01 16:56:15 +00:00
|
|
|
/* Initialize endpoint sequence number info */
|
|
|
|
endpoint->endpoint_next_seq_to_send = module->local_addr.isn;
|
|
|
|
endpoint->endpoint_ack_seq_rcvd = endpoint->endpoint_next_seq_to_send - 1;
|
|
|
|
endpoint->endpoint_next_contig_seq_to_recv =
|
|
|
|
endpoint->endpoint_remote_addr.isn;
|
|
|
|
endpoint->endpoint_highest_seq_rcvd =
|
|
|
|
endpoint->endpoint_next_contig_seq_to_recv - 1;
|
2013-08-27 22:43:20 +00:00
|
|
|
endpoint->endpoint_rfstart = WINDOW_SIZE_MOD(endpoint->endpoint_next_contig_seq_to_recv);
|
2013-08-01 16:56:15 +00:00
|
|
|
|
2013-07-19 22:13:58 +00:00
|
|
|
/* Create the address handle on this endpoint from the modex info.
|
|
|
|
memset to both silence valgrind warnings (since the attr struct
|
|
|
|
ends up getting written down an fd to the kernel) and actually
|
|
|
|
zero out all the fields that we don't care about / want to be
|
|
|
|
logically false. */
|
|
|
|
memset(&ah_attr, 0, sizeof(ah_attr));
|
|
|
|
ah_attr.is_global = 1;
|
|
|
|
ah_attr.port_num = 1;
|
|
|
|
ah_attr.grh.dgid = endpoint->endpoint_remote_addr.gid;
|
|
|
|
|
|
|
|
endpoint->endpoint_remote_ah = ibv_create_ah(module->pd, &ah_attr);
|
|
|
|
if (NULL == endpoint->endpoint_remote_ah) {
|
2013-07-22 17:28:23 +00:00
|
|
|
opal_show_help("help-mpi-btl-usnic.txt", "ibv API failed",
|
2013-07-19 22:13:58 +00:00
|
|
|
true,
|
2013-07-22 17:28:23 +00:00
|
|
|
ompi_process_info.nodename,
|
2013-07-19 22:13:58 +00:00
|
|
|
ibv_get_device_name(module->device),
|
|
|
|
module->port_num,
|
|
|
|
"ibv_create_ah()", __FILE__, __LINE__,
|
|
|
|
"Failed to create an address handle");
|
|
|
|
OBJ_RELEASE(endpoint);
|
|
|
|
return OMPI_ERR_OUT_OF_RESOURCE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now claim that modex slot */
|
|
|
|
proc->proc_modex_claimed[modex_index] = true;
|
2014-02-26 07:46:50 +00:00
|
|
|
MSGDEBUG1_OUT("create_endpoint: module=%p claimed endpoint=%p on proc=%p (hash=0x%" PRIx64 ")\n",
|
|
|
|
(void *)module, (void *)endpoint, (void *)proc,
|
|
|
|
ompi_rte_hash_name(&proc->proc_ompi->proc_name));
|
2013-07-19 22:13:58 +00:00
|
|
|
|
|
|
|
/* Save the endpoint on this proc's array of endpoints */
|
|
|
|
proc->proc_endpoints[proc->proc_endpoint_count] = endpoint;
|
|
|
|
endpoint->endpoint_proc_index = proc->proc_endpoint_count;
|
|
|
|
endpoint->endpoint_proc = proc;
|
|
|
|
++proc->proc_endpoint_count;
|
|
|
|
OBJ_RETAIN(proc);
|
|
|
|
|
|
|
|
/* also add endpoint to module's list of endpoints */
|
|
|
|
opal_list_append(&(module->all_endpoints),
|
|
|
|
&(endpoint->endpoint_endpoint_li));
|
|
|
|
|
|
|
|
*endpoint_o = endpoint;
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we haven't done so already, receive the modex info for the
|
|
|
|
* specified ompi_proc. Search that proc's modex info; if we can find
|
|
|
|
* matching address info, then create an endpoint.
|
|
|
|
*
|
|
|
|
* If we don't find a match, it's not an error: just return "not
|
|
|
|
* found".
|
|
|
|
*
|
2014-02-26 07:39:34 +00:00
|
|
|
* This routine transfers ownership of an object reference to the caller, who
|
|
|
|
* is eventually responsible for transferring or releasing that reference.
|
|
|
|
*
|
2013-07-19 22:13:58 +00:00
|
|
|
* There is a one-to-one correspondence between a ompi_proc_t and a
|
|
|
|
* ompi_btl_usnic_proc_t instance. We cache additional data on the
|
|
|
|
* ompi_btl_usnic_proc_t: specifically, the list of
|
|
|
|
* ompi_btl_usnic_endpoint_t instances, and published addresses/modex
|
|
|
|
* info.
|
|
|
|
*/
|
|
|
|
int ompi_btl_usnic_proc_match(ompi_proc_t *ompi_proc,
|
|
|
|
ompi_btl_usnic_module_t *module,
|
|
|
|
ompi_btl_usnic_proc_t **proc)
|
|
|
|
{
|
|
|
|
/* Check if we have already created a proc structure for this peer
|
|
|
|
ompi process */
|
|
|
|
*proc = ompi_btl_usnic_proc_lookup_ompi(ompi_proc);
|
|
|
|
if (*proc != NULL) {
|
|
|
|
OBJ_RETAIN(*proc);
|
|
|
|
} else {
|
|
|
|
/* If not, go make one */
|
|
|
|
*proc = create_proc(ompi_proc);
|
|
|
|
if (NULL == *proc) {
|
|
|
|
return OMPI_ERR_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OMPI_SUCCESS;
|
|
|
|
}
|