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.
Этот коммит содержится в:
Jeff Squyres 2014-03-04 22:11:47 +00:00
родитель 0461e54875
Коммит fbde50e7cd
3 изменённых файлов: 48 добавлений и 8 удалений

Просмотреть файл

@ -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)); memset(&ompi_btl_usnic_ext, 0, sizeof(ompi_btl_usnic_ext));
/* See if this context supports the usnic extensions. Do the /* 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; int rc;
rc = ibv_query_port(context, 42, struct ibv_port_attr attr;
(struct ibv_port_attr*) &ompi_btl_usnic_ext.qpt); rc = ibv_query_port(context, 42, &attr);
if (0 != rc) { 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, opal_output_verbose(5, USNIC_OUT,
"btl:usnic: verbs plugin does not support extensions"); "btl:usnic: verbs plugin does not support extensions");
return; 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", "btl:usnic: verbs plugin has extension lookup ABI version %d",
ompi_btl_usnic_ext.qpt.lookup_version); ompi_btl_usnic_ext.qpt.lookup_version);
if (1 != 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, opal_output_verbose(5, USNIC_OUT,
"btl:usnic: unrecognized lookup ABI version" "btl:usnic: unrecognized lookup ABI version"
" (I only recognize version 1) " " (I only recognize version 1) "

Просмотреть файл

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

Просмотреть файл

@ -232,6 +232,20 @@ enum {
USNIC_UNKNOWN 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 * usNIC devices will always return one of three
* device->transport_type values: * device->transport_type values:
@ -269,10 +283,18 @@ static int usnic_transport(struct ibv_device *device,
here. */ here. */
if (IBV_TRANSPORT_IWARP == device->transport_type) { if (IBV_TRANSPORT_IWARP == device->transport_type) {
int rc; int rc;
struct ibv_port_attr attr; port_query_u u;
rc = ibv_query_port(context, 42, &attr); rc = ibv_query_port(context, 42, &u.attr);
if (0 == rc) { /* 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; return USNIC_UDP;
} else {
return USNIC_UNKNOWN;
}
} else { } else {
return USNIC_L2; return USNIC_L2;
} }