1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
/*
* Copyright (c) 2013-2019 Cisco Systems, Inc. All rights reserved
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#include <stdio.h>
#include <unistd.h>
#include "opal/constants.h"
#include "opal/util/if.h"
#include "opal/util/show_help.h"
#include "btl_usnic_module.h"
#include "btl_usnic_util.h"
// The following comment tells Coverity that this function does not return.
// See https://scan.coverity.com/tune.
/* coverity[+kill] */
void opal_btl_usnic_exit(opal_btl_usnic_module_t *module)
{
if (NULL == module) {
/* Find the first module with an error callback */
for (int i = 0; i < mca_btl_usnic_component.num_modules; ++i) {
if (NULL != mca_btl_usnic_component.usnic_active_modules
&& NULL != mca_btl_usnic_component.usnic_active_modules[i]
&& NULL != mca_btl_usnic_component.usnic_active_modules[i]->pml_error_callback) {
module = mca_btl_usnic_component.usnic_active_modules[i];
break;
}
}
/* If we didn't find a PML error callback, just exit. */
if (NULL == module) {
fprintf(stderr, "*** The Open MPI usnic BTL is aborting the MPI job (via exit(3)).\n");
fflush(stderr);
exit(1);
}
}
/* After discussion with George, we decided that it was safe to
cast away the const from opal_proc_local_get() -- the error
function needs to be smart enough to not take certain actions
if the passed proc is yourself (e.g., don't call del_procs() on
yourself). */
if (NULL != module->pml_error_callback) {
module
->pml_error_callback(&module->super, MCA_BTL_ERROR_FLAGS_FATAL,
(opal_proc_t *) opal_proc_local_get(),
"The usnic BTL is aborting the MPI job (via PML error callback).");
}
/* If the PML error callback returns (or if there wasn't one),
just exit. Shrug. */
exit(1);
}
/*
* Simple utility in a .c file, mainly so that inline functions in .h
* files don't need to include the show_help header file.
*
* The following comment tells Coverity that this function does not
* return. See https://scan.coverity.com/tune. Technically, we
* shouldn't need this, because opal_btl_usnic_exit() has the same
* annotation, but let's just help Coverity out.
*/
/* coverity[+kill] */
void opal_btl_usnic_util_abort(const char *msg, const char *file, int line)
{
opal_show_help("help-mpi-btl-usnic.txt", "internal error after init", true,
opal_process_info.nodename, file, line, msg);
opal_btl_usnic_exit(NULL);
/* Never returns */
}
void opal_btl_usnic_dump_hex(int verbose_level, int output_id, void *vaddr, int len)
{
char buf[128];
size_t bufspace;
int i, ret;
char *p;
uint32_t sum = 0;
uint8_t *addr;
addr = vaddr;
p = buf;
memset(buf, 0, sizeof(buf));
bufspace = sizeof(buf) - 1;
for (i = 0; i < len; ++i) {
ret = snprintf(p, bufspace, "%02x ", addr[i]);
p += ret;
bufspace -= ret;
sum += addr[i];
if ((i & 15) == 15) {
opal_output_verbose(verbose_level, output_id, "%4x: %s\n", i & ~15, buf);
p = buf;
memset(buf, 0, sizeof(buf));
bufspace = sizeof(buf) - 1;
}
}
if ((i & 15) != 0) {
opal_output_verbose(verbose_level, output_id, "%4x: %s\n", i & ~15, buf);
}
/*opal_output_verbose(verbose_level, output_id, "buffer sum = %x\n", sum); */
}
/*
* Trivial wrapper around snprintf'ing an IPv4 address, with or
* without a CIDR mask (we don't usually carry around addresses in
* struct sockaddr form, so this wrapper is marginally easier than
* using inet_ntop()).
*/
void opal_btl_usnic_snprintf_ipv4_addr(char *out, size_t maxlen, uint32_t addr_be,
uint32_t netmask_be)
{
int prefixlen;
uint32_t netmask = ntohl(netmask_be);
uint32_t addr = ntohl(addr_be);
uint8_t *p = (uint8_t *) &addr;
if (netmask != 0) {
prefixlen = 33 - ffs(netmask);
snprintf(out, maxlen, "%u.%u.%u.%u/%u", p[3], p[2], p[1], p[0], prefixlen);
} else {
snprintf(out, maxlen, "%u.%u.%u.%u", p[3], p[2], p[1], p[0]);
}
}
/* Pretty-print the given boolean array as a hexadecimal string. slen should
* include space for any null terminator. */
void opal_btl_usnic_snprintf_bool_array(char *s, size_t slen, bool a[], size_t alen)
{
size_t i = 0;
size_t j = 0;
/* could accommodate other cases, but not needed right now */
assert(slen % 4 == 0);
/* compute one nybble at a time */
while (i < alen && (j < slen - 1)) {
unsigned char tmp = 0;
/* first bool is the leftmost (most significant) bit of the nybble */
tmp |= !!a[i + 0] << 3;
tmp |= !!a[i + 1] << 2;
tmp |= !!a[i + 2] << 1;
tmp |= !!a[i + 3] << 0;
tmp += '0';
s[j] = tmp;
++j;
i += 4;
}
s[j++] = '\0';
assert(i <= alen);
assert(j <= slen);
}
/* Return the largest size data size that can be packed into max_len using the
* given convertor. For example, a 1000 byte max_len buffer may only be able
* to hold 998 bytes if an indivisible convertor element straddles the 1000
* byte boundary.
*
* This routine internally clones the convertor and does not mutate it!
*/
size_t opal_btl_usnic_convertor_pack_peek(const opal_convertor_t *conv, size_t max_len)
{
int rc;
size_t packable_len, position;
opal_convertor_t temp;
OBJ_CONSTRUCT(&temp, opal_convertor_t);
position = conv->bConverted + max_len;
rc = opal_convertor_clone_with_position(conv, &temp, 1, &position);
if (OPAL_UNLIKELY(rc < 0)) {
BTL_ERROR(("unexpected convertor error"));
abort(); /* XXX */
}
assert(position >= conv->bConverted);
packable_len = position - conv->bConverted;
OBJ_DESTRUCT(&temp);
return packable_len;
}
|