1
1

Fix ibv_port_query() usnic extension usage

* Older versions of libusnic_verbs actually return 0 when querying for
  an unknown port.  So also check for a magic ID in the returned data
  to *really* know if the usnic extensions are supported.
* Use a union (in the common_verbs area) and memcpy (in the btl) to
  avoid undefined C type aliasing behavior.
* Ensure to memset the function table to 0 if the usnic extensions
  are not supported.

Submitted by Jeff Squyres, reviewed by Dave Goodell.

cmr=v1.7.5:reviewer=ompi-rm1.7

This commit was SVN r30935.
This commit is contained in:
Jeff Squyres 2014-03-04 22:11:47 +00:00
parent 0461e54875
commit fbde50e7cd
3 changed files with 48 additions and 8 deletions

View File

@ -30,11 +30,21 @@ void ompi_btl_usnic_ext_init(struct ibv_context *context)
memset(&ompi_btl_usnic_ext, 0, sizeof(ompi_btl_usnic_ext));
/* See if this context supports the usnic extensions. Do the
magic query port on port number 42 (which is THE ANSWER) */
magic query port on port number 42 (which is THE ANSWER). If
it works, we'll get rc==0 and the magic number in the struct
will be set. Note, however, that due to a bug in early
versions of libusnic_verbs, we *may* get rc==0 even if it
doesn't work, which is why we also must check for the magic
value, too. */
int rc;
rc = ibv_query_port(context, 42,
(struct ibv_port_attr*) &ompi_btl_usnic_ext.qpt);
if (0 != rc) {
struct ibv_port_attr attr;
rc = ibv_query_port(context, 42, &attr);
assert(sizeof(ompi_btl_usnic_ext) <= sizeof(attr));
memcpy(&ompi_btl_usnic_ext, &attr, sizeof(ompi_btl_usnic_ext));
if (0 != rc || USNIC_PORT_QUERY_MAGIC != ompi_btl_usnic_ext.qpt.magic) {
/* If the probe fails, we must re-memset() the function
pointer block */
memset(&ompi_btl_usnic_ext, 0, sizeof(ompi_btl_usnic_ext));
opal_output_verbose(5, USNIC_OUT,
"btl:usnic: verbs plugin does not support extensions");
return;
@ -50,6 +60,9 @@ void ompi_btl_usnic_ext_init(struct ibv_context *context)
"btl:usnic: verbs plugin has extension lookup ABI version %d",
ompi_btl_usnic_ext.qpt.lookup_version);
if (1 != ompi_btl_usnic_ext.qpt.lookup_version) {
/* If the probe fails, we must re-memset() the function
pointer block, because it may/will return junk in the qpt */
memset(&ompi_btl_usnic_ext, 0, sizeof(ompi_btl_usnic_ext));
opal_output_verbose(5, USNIC_OUT,
"btl:usnic: unrecognized lookup ABI version"
" (I only recognize version 1) "

View File

@ -14,13 +14,18 @@
#include <infiniband/verbs.h>
#include "opal_stdint.h"
typedef void *(*ompi_btl_usnic_dlsym_fn_t)(const char *name);
typedef struct {
int lookup_version;
uint64_t magic;
ompi_btl_usnic_dlsym_fn_t lookup;
} ompi_btl_usnic_query_port_table_t;
#define USNIC_PORT_QUERY_MAGIC (0x43494e7375534355ULL)
/*
* Tells libusnic_verbs to enable UDP support.
*/

View File

@ -232,6 +232,20 @@ enum {
USNIC_UNKNOWN
};
/* See comment in btl_usnic_ext.c about why we must check the return
from the usnic verbs extensions probe for a magic number (which
means we must also copy the usnic extension struct and magic number
value down here into common/verbs. Bummer). */
typedef union {
struct {
int lookup_version;
uint64_t magic;
} qpt;
struct ibv_port_attr attr;
} port_query_u;
#define USNIC_PORT_QUERY_MAGIC (0x43494e7375534355ULL)
/*
* usNIC devices will always return one of three
* device->transport_type values:
@ -269,10 +283,18 @@ static int usnic_transport(struct ibv_device *device,
here. */
if (IBV_TRANSPORT_IWARP == device->transport_type) {
int rc;
struct ibv_port_attr attr;
rc = ibv_query_port(context, 42, &attr);
if (0 == rc) {
return USNIC_UDP;
port_query_u u;
rc = ibv_query_port(context, 42, &u.attr);
/* See comment in btl_usnic_ext.c about why we have to check
for rc==0 *and* the magic number. */
if (0 == rc && USNIC_PORT_QUERY_MAGIC == u.qpt.magic) {
/* We only support version 1 of the lookup function in
this particular version of Open MPI */
if (1 == u.qpt.lookup_version) {
return USNIC_UDP;
} else {
return USNIC_UNKNOWN;
}
} else {
return USNIC_L2;
}