libfabric: update to upstream d4ab6e56e23124e565ada939054a159737e52102
Fix a critical usnic bug, and other misc updates.
Этот коммит содержится в:
родитель
a50ad505e7
Коммит
faf3324b0e
@ -86,6 +86,7 @@ libfabric_usnic_headers = \
|
|||||||
libfabric/prov/usnic/src/usdf_cq.h \
|
libfabric/prov/usnic/src/usdf_cq.h \
|
||||||
libfabric/prov/usnic/src/usdf_dgram.h \
|
libfabric/prov/usnic/src/usdf_dgram.h \
|
||||||
libfabric/prov/usnic/src/usdf_endpoint.h \
|
libfabric/prov/usnic/src/usdf_endpoint.h \
|
||||||
|
libfabric/prov/usnic/src/usdf_fake_ibv.c \
|
||||||
libfabric/prov/usnic/src/usdf_msg.h \
|
libfabric/prov/usnic/src/usdf_msg.h \
|
||||||
libfabric/prov/usnic/src/usdf_progress.h \
|
libfabric/prov/usnic/src/usdf_progress.h \
|
||||||
libfabric/prov/usnic/src/usdf_rdm.h \
|
libfabric/prov/usnic/src/usdf_rdm.h \
|
||||||
|
@ -201,6 +201,7 @@ _usnic_files = \
|
|||||||
prov/usnic/src/usdf_ep_rdm.c \
|
prov/usnic/src/usdf_ep_rdm.c \
|
||||||
prov/usnic/src/usdf_eq.c \
|
prov/usnic/src/usdf_eq.c \
|
||||||
prov/usnic/src/usdf_fabric.c \
|
prov/usnic/src/usdf_fabric.c \
|
||||||
|
prov/usnic/src/usdf_fake_ibv.c \
|
||||||
prov/usnic/src/usdf_mem.c \
|
prov/usnic/src/usdf_mem.c \
|
||||||
prov/usnic/src/usdf_msg.c \
|
prov/usnic/src/usdf_msg.c \
|
||||||
prov/usnic/src/usdf_msg.h \
|
prov/usnic/src/usdf_msg.h \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
Version Libfabric v1.0.0rc6
|
Version Libfabric v1.0.0rc6
|
||||||
Released on 2015-04-24
|
Released on 2015-04-29
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_cm 3 "2015\-04\-23" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_cm 3 "2015\-04\-29" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_cm - Connection management operations
|
fi_cm - Connection management operations
|
||||||
@ -167,9 +167,19 @@ peer endpoint address, respectively.
|
|||||||
On input, the addrlen parameter should indicate the size of the addr
|
On input, the addrlen parameter should indicate the size of the addr
|
||||||
buffer.
|
buffer.
|
||||||
If the actual address is larger than what can fit into the buffer, it
|
If the actual address is larger than what can fit into the buffer, it
|
||||||
will be truncated.
|
will be truncated and -FI_ETOOSMALL will be returned.
|
||||||
On output, addrlen is set to the size of the buffer needed to store the
|
On output, addrlen is set to the size of the buffer needed to store the
|
||||||
address, which may be larger than the input value.
|
address, which may be larger than the input value.
|
||||||
|
.PP
|
||||||
|
fi_getname is not guaranteed to return a valid source address until
|
||||||
|
after the specified endpoint has been enabled or has had an address
|
||||||
|
assigned.
|
||||||
|
An endpoint may be enabled explicitly through fi_enable, or implicitly,
|
||||||
|
such as through fi_connect or fi_listen.
|
||||||
|
An address may be assigned using fi_setname.
|
||||||
|
fi_getpeer is not guaranteed to return a valid peer address until an
|
||||||
|
endpoint has been completely connected -- an FI_CONNECTED event has been
|
||||||
|
generated.
|
||||||
.SH FLAGS
|
.SH FLAGS
|
||||||
.PP
|
.PP
|
||||||
Flag values are reserved and must be 0.
|
Flag values are reserved and must be 0.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_domain 3 "2015\-04\-23" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_domain 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_domain - Open a fabric access domain
|
fi_domain - Open a fabric access domain
|
||||||
@ -177,7 +177,7 @@ data flows.
|
|||||||
FI_THREAD_FID, but with the added restriction that serialization is
|
FI_THREAD_FID, but with the added restriction that serialization is
|
||||||
required when accessing the same endpoint, even if multiple transmit and
|
required when accessing the same endpoint, even if multiple transmit and
|
||||||
receive contexts are used.
|
receive contexts are used.
|
||||||
Conceptualy, FI_THREAD_ENDPOINT maps well to providers that implement
|
Conceptually, FI_THREAD_ENDPOINT maps well to providers that implement
|
||||||
fabric services in hardware but use a single command queue to access
|
fabric services in hardware but use a single command queue to access
|
||||||
different data flows.
|
different data flows.
|
||||||
.PP
|
.PP
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_endpoint 3 "2015\-04\-24" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_endpoint 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_endpoint - Fabric endpoint operations
|
fi_endpoint - Fabric endpoint operations
|
||||||
@ -1086,8 +1086,8 @@ counters.
|
|||||||
Completed receive operations are posted to the CQs bound to the
|
Completed receive operations are posted to the CQs bound to the
|
||||||
endpoint.
|
endpoint.
|
||||||
An endpoint may only be associated with a single receive context, and
|
An endpoint may only be associated with a single receive context, and
|
||||||
all connectless endpoints associated with a shared receive context must
|
all connectionless endpoints associated with a shared receive context
|
||||||
also share the same address vector.
|
must also share the same address vector.
|
||||||
.PP
|
.PP
|
||||||
Endpoints associated with a shared transmit context may use dedicated
|
Endpoints associated with a shared transmit context may use dedicated
|
||||||
receive contexts, and vice-versa.
|
receive contexts, and vice-versa.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_eq 3 "2015\-04\-13" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_eq 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_eq - Event queue operations
|
fi_eq - Event queue operations
|
||||||
@ -244,7 +244,7 @@ corresponding object type (e.g., see \f[C]fi_av\f[](3) for a description
|
|||||||
of how asynchronous address vector insertions are completed).
|
of how asynchronous address vector insertions are completed).
|
||||||
.PP
|
.PP
|
||||||
\f[I]Connection Notification\f[] : Connection notifications are
|
\f[I]Connection Notification\f[] : Connection notifications are
|
||||||
connection management notifications used to setup or teardown
|
connection management notifications used to setup or tear down
|
||||||
connections between endpoints.
|
connections between endpoints.
|
||||||
There are three connection notification events: FI_CONNREQ,
|
There are three connection notification events: FI_CONNREQ,
|
||||||
FI_CONNECTED, and FI_SHUTDOWN.
|
FI_CONNECTED, and FI_SHUTDOWN.
|
||||||
@ -322,7 +322,7 @@ Endpoint errors may be result of numerous actions, but are often
|
|||||||
associated with a failed operation.
|
associated with a failed operation.
|
||||||
Operations may fail because of buffer overruns, invalid permissions,
|
Operations may fail because of buffer overruns, invalid permissions,
|
||||||
incorrect memory access keys, network routing failures, network
|
incorrect memory access keys, network routing failures, network
|
||||||
reachability issues, etc.
|
reach-ability issues, etc.
|
||||||
.PP
|
.PP
|
||||||
Asynchronous errors are reported using struct fi_eq_err_entry, as
|
Asynchronous errors are reported using struct fi_eq_err_entry, as
|
||||||
defined below.
|
defined below.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_errno 3 "2015\-01\-08" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_errno 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_errno - fabric errors
|
fi_errno - fabric errors
|
||||||
@ -10,7 +10,7 @@ fi_strerror - Convert fabric error into a printable string
|
|||||||
\f[C]
|
\f[C]
|
||||||
#include\ <rdma/fi_errno.h>
|
#include\ <rdma/fi_errno.h>
|
||||||
|
|
||||||
const\ char\ *fi_strerror(int\ errnum);
|
const\ char\ *fi_strerror(int\ errno);
|
||||||
\f[]
|
\f[]
|
||||||
.fi
|
.fi
|
||||||
.SH ERRORS
|
.SH ERRORS
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_tagged 3 "2015\-04\-17" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_tagged 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_tagged - Tagged data transfer operations
|
fi_tagged - Tagged data transfer operations
|
||||||
@ -257,7 +257,7 @@ of FI_ENOMSG.
|
|||||||
.PP
|
.PP
|
||||||
If a peek request locates a matching message, the operation will
|
If a peek request locates a matching message, the operation will
|
||||||
complete successfully.
|
complete successfully.
|
||||||
The returned completion data will indicate the metadata associated with
|
The returned completion data will indicate the meta-data associated with
|
||||||
the message, such as the message length, completion flags, available CQ
|
the message, such as the message length, completion flags, available CQ
|
||||||
data, tag, and source address.
|
data, tag, and source address.
|
||||||
The data available is subject to the completion entry format (e.g.
|
The data available is subject to the completion entry format (e.g.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_trigger 3 "2015\-01\-01" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_trigger 3 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
fi_trigger - Triggered operations
|
fi_trigger - Triggered operations
|
||||||
@ -19,13 +19,13 @@ A triggered operation may be requested by specifying the FI_TRIGGER flag
|
|||||||
as part of the operation.
|
as part of the operation.
|
||||||
Alternatively, an endpoint alias may be created and configured with the
|
Alternatively, an endpoint alias may be created and configured with the
|
||||||
FI_TRIGGER flag.
|
FI_TRIGGER flag.
|
||||||
Such an endpoint is referred to as a triggerable endpoint.
|
Such an endpoint is referred to as a trigger-able endpoint.
|
||||||
All data transfer operations on a triggerable endpoint are deferred.
|
All data transfer operations on a trigger-able endpoint are deferred.
|
||||||
.PP
|
.PP
|
||||||
Any data transfer operation is potentially triggerable, subject to
|
Any data transfer operation is potentially trigger-able, subject to
|
||||||
provider constraints.
|
provider constraints.
|
||||||
Triggerable endpoints are initialized such that only those interfaces
|
Trigger-able endpoints are initialized such that only those interfaces
|
||||||
supported by the provider which are triggerable are available.
|
supported by the provider which are trigger-able are available.
|
||||||
.PP
|
.PP
|
||||||
Triggered operations require that applications use struct
|
Triggered operations require that applications use struct
|
||||||
fi_triggered_context as their per operation context parameter.
|
fi_triggered_context as their per operation context parameter.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_provider 7 "2015\-03\-31" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_provider 7 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
Fabric Interface Providers
|
Fabric Interface Providers
|
||||||
@ -14,7 +14,7 @@ Devices and the drivers that plug into the libfabric framework are
|
|||||||
referred to as fabric providers, or simply providers.
|
referred to as fabric providers, or simply providers.
|
||||||
.PP
|
.PP
|
||||||
This distribution of libfabric contains the following providers
|
This distribution of libfabric contains the following providers
|
||||||
(although more may be available via run-time plugins):
|
(although more may be available via run-time plug-ins):
|
||||||
.PP
|
.PP
|
||||||
\f[I]PSM\f[] : High-speed InfiniBand networking from Intel.
|
\f[I]PSM\f[] : High-speed InfiniBand networking from Intel.
|
||||||
See \f[C]fi_psm\f[](7) for more information.
|
See \f[C]fi_psm\f[](7) for more information.
|
||||||
@ -49,53 +49,88 @@ hardware constraints.
|
|||||||
To assist in the development of applications, libfabric specifies the
|
To assist in the development of applications, libfabric specifies the
|
||||||
following requirements that must be met by any fabric provider, if
|
following requirements that must be met by any fabric provider, if
|
||||||
requested by an application.
|
requested by an application.
|
||||||
(Note that the instantiation of a specific fabric object is subject to
|
.PP
|
||||||
|
Note that the instantiation of a specific fabric object is subject to
|
||||||
application configuration parameters and need not meet these
|
application configuration parameters and need not meet these
|
||||||
requirements).
|
requirements.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
A fabric provider must support at least one endpoint type.
|
A fabric provider must support at least one endpoint type.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
All endpoints must support the message queue data transfer interface.
|
All endpoints must support the message queue data transfer interface
|
||||||
|
(fi_ops_msg).
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
An endpoint that advertises support for a specific endpoint capability
|
An endpoint that advertises support for a specific endpoint capability
|
||||||
must support the corresponding data transfer interface.
|
must support the corresponding data transfer interface.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Endpoints must support operations to send and receive data for any data
|
FI_ATOMIC - fi_ops_atomic
|
||||||
transfer operations that they support.
|
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Connectionless endpoints must support all relevant data transfer
|
FI_RMA - fi_ops_rma
|
||||||
routines.
|
|
||||||
(send / recv / write / read / etc.)
|
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Connectionless endpoints must support the CM interface getname.
|
FI_TAGGED - fi_ops_tagged
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Connectionless endpoints that support multicast operations must support
|
Endpoints must support all transmit and receive operations for any data
|
||||||
the CM interfaces join and leave.
|
transfer interface that they support.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Connection-oriented interfaces must support the CM interfaces getname,
|
Exception: If an operation is only usable for an operation that the
|
||||||
getpeer, connect, listen, accept, reject, and shutdown.
|
provider does not support, and support for that operation is conveyed
|
||||||
|
using some other mechanism, the operation may return
|
||||||
|
.RS 2
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
All endpoints must support all relevant \[aq]msg\[aq] data transfer
|
FI_ENOSYS.
|
||||||
routines.
|
For example, if the provider does not support injected data, it can set
|
||||||
(sendmsg / recvmsg / writemsg / readmsg / etc.)
|
the attribute inject_size = 0, and fail all fi_inject operations.
|
||||||
|
.RE
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Access domains must support opening address vector maps and tables.
|
The framework supplies wrappers around the \[aq]msg\[aq] operations that
|
||||||
|
can be used.
|
||||||
|
For example, the framework implements the sendv() msg operation by
|
||||||
|
calling sendmsg().
|
||||||
|
Providers may reference the general operation, and supply on the
|
||||||
|
sendmsg() implementation.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Address vectors associated with domains that may be identified using IP
|
Providers must set all operations to an implementation.
|
||||||
addresses must support the FI_SOCKADDR_IN input format.
|
Function pointers may not be left NULL or uninitialized.
|
||||||
|
The framework supplies empty functions that return -FI_ENOSYS which can
|
||||||
|
be used for this purpose.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Access domains must support opening completion queues and counters.
|
Endpoints must support the CM interface as follows:
|
||||||
|
.IP \[bu] 2
|
||||||
|
FI_EP_MSG endpoints must support all CM operations.
|
||||||
|
.IP \[bu] 2
|
||||||
|
FI_EP_DGRAM endpoints must support CM getname and setname.
|
||||||
|
.IP \[bu] 2
|
||||||
|
FI_EP_RDM endpoints must support CM getname and setname.
|
||||||
|
.IP \[bu] 2
|
||||||
|
Providers that support connectionless endpoints must support all AV
|
||||||
|
operations (fi_ops_av).
|
||||||
|
.IP \[bu] 2
|
||||||
|
Providers that support memory registration, must support all MR
|
||||||
|
operations (fi_ops_mr).
|
||||||
|
.IP \[bu] 2
|
||||||
|
Providers should support both completion queues and counters.
|
||||||
|
.IP \[bu] 2
|
||||||
|
If FI_RMA_EVENT is not supported, counter support is limited to local
|
||||||
|
events only.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Completion queues must support the FI_CQ_FORMAT_CONTEXT and
|
Completion queues must support the FI_CQ_FORMAT_CONTEXT and
|
||||||
FI_CQ_FORMAT_MSG formats.
|
FI_CQ_FORMAT_MSG.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Event queues associated with tagged message transfers must support the
|
Providers that support FI_REMOTE_CQ_DATA shall support
|
||||||
FI_CQ_FORMAT_TAGGED format.
|
FI_CQ_FORMAT_DATA.
|
||||||
|
.IP \[bu] 2
|
||||||
|
Providers that support FI_TAGGED shall support FI_CQ_FORMAT_TAGGED.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
A provider is expected to be forward compatible, and must be able to be
|
A provider is expected to be forward compatible, and must be able to be
|
||||||
compiled against expanded \f[C]fi_xxx_ops\f[] structures that define new
|
compiled against expanded \f[C]fi_xxx_ops\f[] structures that define new
|
||||||
functions added after the provider was written.
|
functions added after the provider was written.
|
||||||
Any unknown functions must be set to NULL.
|
Any unknown functions must be set to NULL.
|
||||||
|
.IP \[bu] 2
|
||||||
|
Providers shall document in their man page which features they support,
|
||||||
|
and any missing requirements.
|
||||||
|
.PP
|
||||||
|
Future versions of libfabric will automatically enable a more complete
|
||||||
|
set of features for providers that focus their implementation on a
|
||||||
|
narrow subset of libfabric capabilities.
|
||||||
.SH LOGGING INTERFACE
|
.SH LOGGING INTERFACE
|
||||||
.PP
|
.PP
|
||||||
Logging is performed using the FI_ERR, FI_LOG, and FI_DEBUG macros.
|
Logging is performed using the FI_ERR, FI_LOG, and FI_DEBUG macros.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_psm 7 "2015\-04\-23" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_psm 7 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
The PSM Fabric Provider
|
The PSM Fabric Provider
|
||||||
@ -94,7 +94,7 @@ The name server won\[aq]t work properly if there are more than one
|
|||||||
processes from the same job (i.e.
|
processes from the same job (i.e.
|
||||||
with the same UUID) running on the same node and acting as servers.
|
with the same UUID) running on the same node and acting as servers.
|
||||||
For such scenario it is recommended to have each process getting local
|
For such scenario it is recommended to have each process getting local
|
||||||
transport address with \f[I]fi_cm_getname\f[] and exchanginge the
|
transport address with \f[I]fi_cm_getname\f[] and exchanging the
|
||||||
addresses with out-of-band mechanism.
|
addresses with out-of-band mechanism.
|
||||||
.PP
|
.PP
|
||||||
The name server is on by default.
|
The name server is on by default.
|
||||||
@ -106,7 +106,7 @@ created when the name server is on.
|
|||||||
of the PSM Active Message functions.
|
of the PSM Active Message functions.
|
||||||
The Active Message functions has limit on the size of data can be
|
The Active Message functions has limit on the size of data can be
|
||||||
transferred in a single message.
|
transferred in a single message.
|
||||||
Large transfers can be divided into small chunks and be pipelined.
|
Large transfers can be divided into small chunks and be pipe-lined.
|
||||||
However, the bandwidth is sub-optimal by doing this way.
|
However, the bandwidth is sub-optimal by doing this way.
|
||||||
.PP
|
.PP
|
||||||
The \f[I]psm\f[] provider use PSM tag-matching message queue functions
|
The \f[I]psm\f[] provider use PSM tag-matching message queue functions
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH fi_usnic 7 "2015\-03\-31" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_usnic 7 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
The usNIC Fabric Provider
|
The usNIC Fabric Provider
|
||||||
@ -66,7 +66,7 @@ Passive endpoints only support listen CM operations.
|
|||||||
\f[I]FI_EP_DGRAM\f[] endpoints support \f[C]fi_sendmsg()\f[] and
|
\f[I]FI_EP_DGRAM\f[] endpoints support \f[C]fi_sendmsg()\f[] and
|
||||||
\f[C]fi_recvmsg()\f[], but all flags are ignored.
|
\f[C]fi_recvmsg()\f[], but all flags are ignored.
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
\f[I]FI_EP_RDM\f[] and \f[I]FI_EP_MSG\f[] endponts do not support
|
\f[I]FI_EP_RDM\f[] and \f[I]FI_EP_MSG\f[] endpoints do not support
|
||||||
\f[C]fi_sendmsg()\f[] and \f[C]fi_recvmsg()\f[].
|
\f[C]fi_sendmsg()\f[] and \f[C]fi_recvmsg()\f[].
|
||||||
.IP \[bu] 2
|
.IP \[bu] 2
|
||||||
Address vectors only support \f[C]FI_AV_MAP\f[].
|
Address vectors only support \f[C]FI_AV_MAP\f[].
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
.TH fi_verbs 7 "2015\-04\-23" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
.TH fi_verbs 7 "2015\-04\-28" "Libfabric Programmer\[aq]s Manual" "Libfabric v1.0.0rc6"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
The Verbs Fabric Provider
|
The Verbs Fabric Provider
|
||||||
.SH OVERVIEW
|
.SH OVERVIEW
|
||||||
.PP
|
.PP
|
||||||
The verbs provider enables applications using OFI to be run over any
|
The verbs provider enables applications using OFI to be run over any
|
||||||
verbs hardware (Infiniband, iWARP, etc).
|
verbs hardware (Infiniband, iWarp, etc).
|
||||||
It uses the Linux Verbs API for network transport and provides a
|
It uses the Linux Verbs API for network transport and provides a
|
||||||
translation OFI calls to appropriate verbs API calls.
|
translation OFI calls to appropriate verbs API calls.
|
||||||
It uses librdmacm for communication management and libibverbs for other
|
It uses librdmacm for communication management and libibverbs for other
|
||||||
@ -25,7 +25,7 @@ Applications must take responsibility of posting receives for any
|
|||||||
incoming CQ data.
|
incoming CQ data.
|
||||||
.PP
|
.PP
|
||||||
\f[I]Progress\f[] : Verbs provider supports FI_PROGRESS_AUTO:
|
\f[I]Progress\f[] : Verbs provider supports FI_PROGRESS_AUTO:
|
||||||
Asynchonous operations make forward progress automatically.
|
Asynchronous operations make forward progress automatically.
|
||||||
.PP
|
.PP
|
||||||
\f[I]Operation flags\f[] : Verbs provider supports FI_INJECT,
|
\f[I]Operation flags\f[] : Verbs provider supports FI_INJECT,
|
||||||
FI_COMPLETION, FI_REMOTE_CQ_DATA.
|
FI_COMPLETION, FI_REMOTE_CQ_DATA.
|
||||||
@ -43,7 +43,7 @@ supported.
|
|||||||
are not supported.
|
are not supported.
|
||||||
.PP
|
.PP
|
||||||
\f[I]Endpoint features\f[] : Scalable endpoints and shared contexts are
|
\f[I]Endpoint features\f[] : Scalable endpoints and shared contexts are
|
||||||
not suppoted.
|
not supported.
|
||||||
fi_cancel, fi_tx/rx_size_left and fi_alias operations are not supported.
|
fi_cancel, fi_tx/rx_size_left and fi_alias operations are not supported.
|
||||||
.PP
|
.PP
|
||||||
\f[I]Others\f[] : Other unsupported features include resource
|
\f[I]Others\f[] : Other unsupported features include resource
|
||||||
|
@ -126,9 +126,15 @@ int psmx_am_init(struct psmx_fid_domain *domain)
|
|||||||
if (err)
|
if (err)
|
||||||
return psmx_errno(err);
|
return psmx_errno(err);
|
||||||
|
|
||||||
assert(psmx_am_handlers_idx[0] == PSMX_AM_RMA_HANDLER);
|
if ((psmx_am_handlers_idx[0] != PSMX_AM_RMA_HANDLER) ||
|
||||||
assert(psmx_am_handlers_idx[1] == PSMX_AM_MSG_HANDLER);
|
(psmx_am_handlers_idx[1] != PSMX_AM_MSG_HANDLER) ||
|
||||||
assert(psmx_am_handlers_idx[2] == PSMX_AM_ATOMIC_HANDLER);
|
(psmx_am_handlers_idx[2] != PSMX_AM_ATOMIC_HANDLER)) {
|
||||||
|
FI_WARN(&psmx_prov, FI_LOG_CORE,
|
||||||
|
"failed to register one or mroe AM handlers "
|
||||||
|
"at indecies %d, %d, %d\n", PSMX_AM_RMA_HANDLER,
|
||||||
|
PSMX_AM_MSG_HANDLER, PSMX_AM_ATOMIC_HANDLER);
|
||||||
|
return -FI_EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
psmx_am_handlers_initialized = 1;
|
psmx_am_handlers_initialized = 1;
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,12 @@
|
|||||||
FI_ORDER_SAR | FI_ORDER_SAW | FI_ORDER_SAS)
|
FI_ORDER_SAR | FI_ORDER_SAW | FI_ORDER_SAS)
|
||||||
|
|
||||||
#define SOCK_EP_COMP_ORDER (FI_ORDER_STRICT | FI_ORDER_DATA)
|
#define SOCK_EP_COMP_ORDER (FI_ORDER_STRICT | FI_ORDER_DATA)
|
||||||
|
#define SOCK_EP_DEFAULT_OP_FLAGS (FI_TRANSMIT_COMPLETE)
|
||||||
|
|
||||||
|
#define SOCK_EP_SET_TX_OP_FLAGS(_flags) do { \
|
||||||
|
if (!((_flags) & FI_INJECT_COMPLETE)) \
|
||||||
|
(_flags) |= FI_TRANSMIT_COMPLETE; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SOCK_MODE (0)
|
#define SOCK_MODE (0)
|
||||||
#define SOCK_NO_COMPLETION (1ULL << 60)
|
#define SOCK_NO_COMPLETION (1ULL << 60)
|
||||||
@ -817,7 +823,8 @@ int sock_dgram_verify_ep_attr(struct fi_ep_attr *ep_attr, struct fi_tx_attr *tx_
|
|||||||
struct fi_rx_attr *rx_attr);
|
struct fi_rx_attr *rx_attr);
|
||||||
int sock_msg_verify_ep_attr(struct fi_ep_attr *ep_attr, struct fi_tx_attr *tx_attr,
|
int sock_msg_verify_ep_attr(struct fi_ep_attr *ep_attr, struct fi_tx_attr *tx_attr,
|
||||||
struct fi_rx_attr *rx_attr);
|
struct fi_rx_attr *rx_attr);
|
||||||
|
int sock_get_src_addr(struct sockaddr_in *dest_addr,
|
||||||
|
struct sockaddr_in *src_addr);
|
||||||
|
|
||||||
struct fi_info *sock_fi_info(enum fi_ep_type ep_type,
|
struct fi_info *sock_fi_info(enum fi_ep_type ep_type,
|
||||||
struct fi_info *hints, void *src_addr, void *dest_addr);
|
struct fi_info *hints, void *src_addr, void *dest_addr);
|
||||||
|
@ -104,6 +104,7 @@ static ssize_t sock_ep_tx_atomic(struct fid_ep *ep,
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
return -FI_EAGAIN;
|
return -FI_EAGAIN;
|
||||||
|
|
||||||
|
SOCK_EP_SET_TX_OP_FLAGS(flags);
|
||||||
if (flags & SOCK_USE_OP_FLAGS)
|
if (flags & SOCK_USE_OP_FLAGS)
|
||||||
flags |= tx_ctx->attr.op_flags;
|
flags |= tx_ctx->attr.op_flags;
|
||||||
|
|
||||||
@ -162,7 +163,6 @@ static ssize_t sock_ep_tx_atomic(struct fid_ep *ep,
|
|||||||
for (i = 0; i< msg->iov_count; i++) {
|
for (i = 0; i< msg->iov_count; i++) {
|
||||||
tx_iov.ioc.addr = (uintptr_t) msg->msg_iov[i].addr;
|
tx_iov.ioc.addr = (uintptr_t) msg->msg_iov[i].addr;
|
||||||
tx_iov.ioc.count = msg->msg_iov[i].count;
|
tx_iov.ioc.count = msg->msg_iov[i].count;
|
||||||
tx_iov.ioc.key = (uintptr_t) msg->desc[i];
|
|
||||||
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
||||||
src_len += (tx_iov.ioc.count * datatype_sz);
|
src_len += (tx_iov.ioc.count * datatype_sz);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
#include "sock_util.h"
|
#include "sock_util.h"
|
||||||
@ -1321,6 +1322,9 @@ struct fi_info *sock_fi_info(enum fi_ep_type ep_type, struct fi_info *hints,
|
|||||||
if (hints->rx_attr)
|
if (hints->rx_attr)
|
||||||
*(info->rx_attr) = *(hints->rx_attr);
|
*(info->rx_attr) = *(hints->rx_attr);
|
||||||
|
|
||||||
|
if (hints->handle)
|
||||||
|
info->handle = hints->handle;
|
||||||
|
|
||||||
sock_set_domain_attr(hints->domain_attr, info->domain_attr);
|
sock_set_domain_attr(hints->domain_attr, info->domain_attr);
|
||||||
sock_set_fabric_attr(hints->fabric_attr, info->fabric_attr);
|
sock_set_fabric_attr(hints->fabric_attr, info->fabric_attr);
|
||||||
} else {
|
} else {
|
||||||
@ -1332,6 +1336,39 @@ struct fi_info *sock_fi_info(enum fi_ep_type ep_type, struct fi_info *hints,
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sock_ep_assign_src_addr(struct sock_ep *sock_ep, struct fi_info *info)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct addrinfo ai, *rai = NULL;
|
||||||
|
char hostname[HOST_NAME_MAX];
|
||||||
|
|
||||||
|
sock_ep->src_addr = calloc(1, sizeof(struct sockaddr_in));
|
||||||
|
if (!sock_ep->src_addr)
|
||||||
|
return -FI_ENOMEM;
|
||||||
|
|
||||||
|
if (info && info->dest_addr) {
|
||||||
|
return sock_get_src_addr(info->dest_addr, sock_ep->src_addr);
|
||||||
|
} else {
|
||||||
|
memset(&ai, 0, sizeof(ai));
|
||||||
|
ai.ai_family = AF_INET;
|
||||||
|
ai.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
if (gethostname(hostname, sizeof hostname) != 0) {
|
||||||
|
SOCK_LOG_INFO("gethostname failed!\n");
|
||||||
|
return -FI_EINVAL;
|
||||||
|
}
|
||||||
|
ret = getaddrinfo(hostname, NULL, &ai, &rai);
|
||||||
|
if (ret) {
|
||||||
|
SOCK_LOG_INFO("getaddrinfo failed!\n");
|
||||||
|
return -FI_EINVAL;
|
||||||
|
}
|
||||||
|
memcpy(sock_ep->src_addr, (struct sockaddr_in *)rai->ai_addr,
|
||||||
|
sizeof *sock_ep->src_addr);
|
||||||
|
freeaddrinfo(rai);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sock_alloc_endpoint(struct fid_domain *domain, struct fi_info *info,
|
int sock_alloc_endpoint(struct fid_domain *domain, struct fi_info *info,
|
||||||
struct sock_ep **ep, void *context, size_t fclass)
|
struct sock_ep **ep, void *context, size_t fclass)
|
||||||
{
|
{
|
||||||
@ -1421,6 +1458,11 @@ int sock_alloc_endpoint(struct fid_domain *domain, struct fi_info *info,
|
|||||||
}
|
}
|
||||||
sock_ep->info.handle = info->handle;
|
sock_ep->info.handle = info->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sock_ep->src_addr && sock_ep_assign_src_addr(sock_ep, info)) {
|
||||||
|
SOCK_LOG_ERROR("failed to get src_address\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
atomic_initialize(&sock_ep->ref, 0);
|
atomic_initialize(&sock_ep->ref, 0);
|
||||||
atomic_initialize(&sock_ep->num_tx_ctx, 0);
|
atomic_initialize(&sock_ep->num_tx_ctx, 0);
|
||||||
@ -1490,6 +1532,10 @@ int sock_alloc_endpoint(struct fid_domain *domain, struct fi_info *info,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
if (sock_ep->src_addr)
|
||||||
|
free(sock_ep->src_addr);
|
||||||
|
if (sock_ep->dest_addr)
|
||||||
|
free(sock_ep->dest_addr);
|
||||||
free(sock_ep);
|
free(sock_ep);
|
||||||
return -FI_EINVAL;
|
return -FI_EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ const struct fi_ep_attr sock_dgram_ep_attr = {
|
|||||||
const struct fi_tx_attr sock_dgram_tx_attr = {
|
const struct fi_tx_attr sock_dgram_tx_attr = {
|
||||||
.caps = SOCK_EP_DGRAM_CAP,
|
.caps = SOCK_EP_DGRAM_CAP,
|
||||||
.mode = SOCK_MODE,
|
.mode = SOCK_MODE,
|
||||||
.op_flags = FI_TRANSMIT_COMPLETE,
|
.op_flags = SOCK_EP_DEFAULT_OP_FLAGS,
|
||||||
.msg_order = SOCK_EP_MSG_ORDER,
|
.msg_order = SOCK_EP_MSG_ORDER,
|
||||||
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
||||||
.size = SOCK_EP_TX_SZ,
|
.size = SOCK_EP_TX_SZ,
|
||||||
|
@ -77,7 +77,7 @@ static const struct fi_ep_attr sock_msg_ep_attr = {
|
|||||||
static const struct fi_tx_attr sock_msg_tx_attr = {
|
static const struct fi_tx_attr sock_msg_tx_attr = {
|
||||||
.caps = SOCK_EP_MSG_CAP,
|
.caps = SOCK_EP_MSG_CAP,
|
||||||
.mode = SOCK_MODE,
|
.mode = SOCK_MODE,
|
||||||
.op_flags = FI_TRANSMIT_COMPLETE,
|
.op_flags = SOCK_EP_DEFAULT_OP_FLAGS,
|
||||||
.msg_order = SOCK_EP_MSG_ORDER,
|
.msg_order = SOCK_EP_MSG_ORDER,
|
||||||
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
||||||
.size = SOCK_EP_TX_SZ,
|
.size = SOCK_EP_TX_SZ,
|
||||||
@ -254,10 +254,75 @@ static int sock_ep_cm_getname(fid_t fid, void *addr, size_t *addrlen)
|
|||||||
SOCK_LOG_ERROR("Invalid argument\n");
|
SOCK_LOG_ERROR("Invalid argument\n");
|
||||||
return -FI_EINVAL;
|
return -FI_EINVAL;
|
||||||
}
|
}
|
||||||
|
return (*addrlen == sizeof(struct sockaddr_in)) ? 0 : -FI_ETOOSMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sock_pep_create_listener(struct sock_pep *pep)
|
||||||
|
{
|
||||||
|
int optval, ret;
|
||||||
|
socklen_t addr_size;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
struct addrinfo *s_res = NULL, *p;
|
||||||
|
struct addrinfo hints;
|
||||||
|
char sa_ip[INET_ADDRSTRLEN] = {0};
|
||||||
|
char sa_port[NI_MAXSERV] = {0};
|
||||||
|
|
||||||
|
pep->cm.do_listen = 1;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_INET;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
hints.ai_protocol = IPPROTO_UDP;
|
||||||
|
|
||||||
|
memcpy(sa_ip, inet_ntoa(pep->src_addr.sin_addr), INET_ADDRSTRLEN);
|
||||||
|
sprintf(sa_port, "%d", ntohs(pep->src_addr.sin_port));
|
||||||
|
|
||||||
|
ret = getaddrinfo(sa_ip, sa_port, &hints, &s_res);
|
||||||
|
if (ret) {
|
||||||
|
SOCK_LOG_ERROR("no available AF_INET address service:%s, %s\n",
|
||||||
|
sa_port, gai_strerror(ret));
|
||||||
|
return -FI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p=s_res; p; p=p->ai_next) {
|
||||||
|
pep->cm.sock = socket(p->ai_family, p->ai_socktype,
|
||||||
|
p->ai_protocol);
|
||||||
|
if (pep->cm.sock >= 0) {
|
||||||
|
optval = 1;
|
||||||
|
if (setsockopt(pep->cm.sock, SOL_SOCKET, SO_REUSEADDR, &optval,
|
||||||
|
sizeof optval))
|
||||||
|
SOCK_LOG_ERROR("setsockopt failed\n");
|
||||||
|
|
||||||
|
if (!bind(pep->cm.sock, s_res->ai_addr, s_res->ai_addrlen))
|
||||||
|
break;
|
||||||
|
close(pep->cm.sock);
|
||||||
|
pep->cm.sock = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(s_res);
|
||||||
|
if (pep->cm.sock < 0)
|
||||||
|
return -FI_EIO;
|
||||||
|
|
||||||
|
optval = 1;
|
||||||
|
if (setsockopt(pep->cm.sock, SOL_SOCKET, SO_REUSEADDR, &optval,
|
||||||
|
sizeof optval))
|
||||||
|
SOCK_LOG_ERROR("setsockopt failed\n");
|
||||||
|
|
||||||
|
if (pep->src_addr.sin_port == 0) {
|
||||||
|
addr_size = sizeof(addr);
|
||||||
|
if (getsockname(pep->cm.sock, (struct sockaddr*)&addr, &addr_size))
|
||||||
|
return -FI_EINVAL;
|
||||||
|
pep->src_addr.sin_port = addr.sin_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOCK_LOG_INFO("Listener thread bound to %s:%d\n",
|
||||||
|
sa_ip, ntohs(pep->src_addr.sin_port));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_ep_cm_setnmae(fid_t fid, void *addr, size_t addrlen)
|
static int sock_ep_cm_setname(fid_t fid, void *addr, size_t addrlen)
|
||||||
{
|
{
|
||||||
struct sock_ep *sock_ep = NULL;
|
struct sock_ep *sock_ep = NULL;
|
||||||
struct sock_pep *sock_pep = NULL;
|
struct sock_pep *sock_pep = NULL;
|
||||||
@ -272,13 +337,13 @@ static int sock_ep_cm_setnmae(fid_t fid, void *addr, size_t addrlen)
|
|||||||
if (sock_ep->listener.listener_thread)
|
if (sock_ep->listener.listener_thread)
|
||||||
return -FI_EINVAL;
|
return -FI_EINVAL;
|
||||||
memcpy(sock_ep->src_addr, addr, addrlen);
|
memcpy(sock_ep->src_addr, addr, addrlen);
|
||||||
break;
|
return sock_conn_listen(sock_ep);
|
||||||
case FI_CLASS_PEP:
|
case FI_CLASS_PEP:
|
||||||
sock_pep = container_of(fid, struct sock_pep, pep.fid);
|
sock_pep = container_of(fid, struct sock_pep, pep.fid);
|
||||||
if (sock_pep->cm.listener_thread)
|
if (sock_pep->cm.listener_thread)
|
||||||
return -FI_EINVAL;
|
return -FI_EINVAL;
|
||||||
memcpy(&sock_pep->src_addr, addr, addrlen);
|
memcpy(&sock_pep->src_addr, addr, addrlen);
|
||||||
break;
|
return sock_pep_create_listener(sock_pep);
|
||||||
default:
|
default:
|
||||||
SOCK_LOG_ERROR("Invalid argument\n");
|
SOCK_LOG_ERROR("Invalid argument\n");
|
||||||
return -FI_EINVAL;
|
return -FI_EINVAL;
|
||||||
@ -298,7 +363,7 @@ static int sock_ep_cm_getpeer(struct fid_ep *ep, void *addr, size_t *addrlen)
|
|||||||
sock_ep = container_of(ep, struct sock_ep, ep);
|
sock_ep = container_of(ep, struct sock_ep, ep);
|
||||||
*addrlen = MIN(*addrlen, sizeof(struct sockaddr_in));
|
*addrlen = MIN(*addrlen, sizeof(struct sockaddr_in));
|
||||||
memcpy(addr, sock_ep->dest_addr, *addrlen);
|
memcpy(addr, sock_ep->dest_addr, *addrlen);
|
||||||
return 0;
|
return (*addrlen == sizeof(struct sockaddr_in)) ? 0 : -FI_ETOOSMALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_ep_cm_create_socket(void)
|
static int sock_ep_cm_create_socket(void)
|
||||||
@ -678,6 +743,8 @@ static int sock_ep_cm_connect(struct fid_ep *ep, const void *addr,
|
|||||||
req->ep_attr = *_ep->info.ep_attr;
|
req->ep_attr = *_ep->info.ep_attr;
|
||||||
req->domain_attr = *_ep->info.domain_attr;
|
req->domain_attr = *_ep->info.domain_attr;
|
||||||
req->fabric_attr = *_ep->info.fabric_attr;
|
req->fabric_attr = *_ep->info.fabric_attr;
|
||||||
|
req->fabric_attr.fabric = NULL;
|
||||||
|
req->domain_attr.domain = NULL;
|
||||||
|
|
||||||
if (param && paramlen)
|
if (param && paramlen)
|
||||||
memcpy(&req->user_data, param, paramlen);
|
memcpy(&req->user_data, param, paramlen);
|
||||||
@ -777,7 +844,7 @@ static int sock_ep_cm_shutdown(struct fid_ep *ep, uint64_t flags)
|
|||||||
|
|
||||||
struct fi_ops_cm sock_ep_cm_ops = {
|
struct fi_ops_cm sock_ep_cm_ops = {
|
||||||
.size = sizeof(struct fi_ops_cm),
|
.size = sizeof(struct fi_ops_cm),
|
||||||
.setname = sock_ep_cm_setnmae,
|
.setname = sock_ep_cm_setname,
|
||||||
.getname = sock_ep_cm_getname,
|
.getname = sock_ep_cm_getname,
|
||||||
.getpeer = sock_ep_cm_getpeer,
|
.getpeer = sock_ep_cm_getpeer,
|
||||||
.connect = sock_ep_cm_connect,
|
.connect = sock_ep_cm_connect,
|
||||||
@ -791,6 +858,7 @@ static int sock_msg_endpoint(struct fid_domain *domain, struct fi_info *info,
|
|||||||
struct sock_ep **ep, void *context, size_t fclass)
|
struct sock_ep **ep, void *context, size_t fclass)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
struct sock_pep *pep;
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
if (info->ep_attr) {
|
if (info->ep_attr) {
|
||||||
@ -813,11 +881,16 @@ static int sock_msg_endpoint(struct fid_domain *domain, struct fi_info *info,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sock_alloc_endpoint(domain, info, ep, context, fclass);
|
ret = sock_alloc_endpoint(domain, info, ep, context, fclass);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (info && info->handle && info->handle->fclass == FI_CLASS_PEP) {
|
||||||
|
pep = container_of(info->handle, struct sock_pep, pep.fid);
|
||||||
|
memcpy((*ep)->src_addr, &pep->src_addr, sizeof *(*ep)->src_addr);
|
||||||
|
}
|
||||||
|
|
||||||
if (!info || !info->ep_attr)
|
if (!info || !info->ep_attr)
|
||||||
(*ep)->ep_attr = sock_msg_ep_attr;
|
(*ep)->ep_attr = sock_msg_ep_attr;
|
||||||
|
|
||||||
@ -1046,69 +1119,8 @@ out:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_pep_create_listener_thread(struct sock_pep *pep)
|
static int sock_pep_start_listener_thread(struct sock_pep *pep)
|
||||||
{
|
{
|
||||||
int optval, ret;
|
|
||||||
socklen_t addr_size;
|
|
||||||
struct sockaddr_in addr;
|
|
||||||
struct addrinfo *s_res = NULL, *p;
|
|
||||||
struct addrinfo hints;
|
|
||||||
char sa_ip[INET_ADDRSTRLEN] = {0};
|
|
||||||
char sa_port[NI_MAXSERV] = {0};
|
|
||||||
|
|
||||||
pep->cm.do_listen = 1;
|
|
||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = AF_INET;
|
|
||||||
hints.ai_socktype = SOCK_DGRAM;
|
|
||||||
hints.ai_flags = AI_PASSIVE;
|
|
||||||
hints.ai_protocol = IPPROTO_UDP;
|
|
||||||
|
|
||||||
memcpy(sa_ip, inet_ntoa(pep->src_addr.sin_addr), INET_ADDRSTRLEN);
|
|
||||||
sprintf(sa_port, "%d", ntohs(pep->src_addr.sin_port));
|
|
||||||
|
|
||||||
ret = getaddrinfo(sa_ip, sa_port, &hints, &s_res);
|
|
||||||
if (ret) {
|
|
||||||
SOCK_LOG_ERROR("no available AF_INET address service:%s, %s\n",
|
|
||||||
sa_port, gai_strerror(ret));
|
|
||||||
return -FI_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p=s_res; p; p=p->ai_next) {
|
|
||||||
pep->cm.sock = socket(p->ai_family, p->ai_socktype,
|
|
||||||
p->ai_protocol);
|
|
||||||
if (pep->cm.sock >= 0) {
|
|
||||||
optval = 1;
|
|
||||||
if (setsockopt(pep->cm.sock, SOL_SOCKET, SO_REUSEADDR, &optval,
|
|
||||||
sizeof optval))
|
|
||||||
SOCK_LOG_ERROR("setsockopt failed\n");
|
|
||||||
|
|
||||||
if (!bind(pep->cm.sock, s_res->ai_addr, s_res->ai_addrlen))
|
|
||||||
break;
|
|
||||||
close(pep->cm.sock);
|
|
||||||
pep->cm.sock = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
freeaddrinfo(s_res);
|
|
||||||
if (pep->cm.sock < 0)
|
|
||||||
return -FI_EIO;
|
|
||||||
|
|
||||||
optval = 1;
|
|
||||||
if (setsockopt(pep->cm.sock, SOL_SOCKET, SO_REUSEADDR, &optval,
|
|
||||||
sizeof optval))
|
|
||||||
SOCK_LOG_ERROR("setsockopt failed\n");
|
|
||||||
|
|
||||||
if (pep->src_addr.sin_port == 0) {
|
|
||||||
addr_size = sizeof(addr);
|
|
||||||
if (getsockname(pep->cm.sock, (struct sockaddr*)&addr, &addr_size))
|
|
||||||
return -FI_EINVAL;
|
|
||||||
pep->src_addr.sin_port = addr.sin_port;
|
|
||||||
}
|
|
||||||
|
|
||||||
SOCK_LOG_INFO("Listener thread bound to %s:%d\n",
|
|
||||||
sa_ip, ntohs(pep->src_addr.sin_port));
|
|
||||||
|
|
||||||
if (pthread_create(&pep->cm.listener_thread, NULL,
|
if (pthread_create(&pep->cm.listener_thread, NULL,
|
||||||
sock_pep_listener_thread, (void *)pep)) {
|
sock_pep_listener_thread, (void *)pep)) {
|
||||||
SOCK_LOG_ERROR("Couldn't create listener thread\n");
|
SOCK_LOG_ERROR("Couldn't create listener thread\n");
|
||||||
@ -1121,7 +1133,15 @@ static int sock_pep_listen(struct fid_pep *pep)
|
|||||||
{
|
{
|
||||||
struct sock_pep *_pep;
|
struct sock_pep *_pep;
|
||||||
_pep = container_of(pep, struct sock_pep, pep);
|
_pep = container_of(pep, struct sock_pep, pep);
|
||||||
return sock_pep_create_listener_thread(_pep);
|
if (_pep->cm.listener_thread)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!_pep->cm.do_listen && sock_pep_create_listener(_pep)) {
|
||||||
|
SOCK_LOG_ERROR("Failed to create pep thread\n");
|
||||||
|
return -FI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_pep_start_listener_thread(_pep);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_pep_reject(struct fid_pep *pep, fid_t handle,
|
static int sock_pep_reject(struct fid_pep *pep, fid_t handle,
|
||||||
@ -1170,7 +1190,7 @@ out:
|
|||||||
|
|
||||||
static struct fi_ops_cm sock_pep_cm_ops = {
|
static struct fi_ops_cm sock_pep_cm_ops = {
|
||||||
.size = sizeof(struct fi_ops_cm),
|
.size = sizeof(struct fi_ops_cm),
|
||||||
.setname = sock_ep_cm_setnmae,
|
.setname = sock_ep_cm_setname,
|
||||||
.getname = sock_ep_cm_getname,
|
.getname = sock_ep_cm_getname,
|
||||||
.getpeer = fi_no_getpeer,
|
.getpeer = fi_no_getpeer,
|
||||||
.connect = fi_no_connect,
|
.connect = fi_no_connect,
|
||||||
|
@ -76,7 +76,7 @@ const struct fi_ep_attr sock_rdm_ep_attr = {
|
|||||||
const struct fi_tx_attr sock_rdm_tx_attr = {
|
const struct fi_tx_attr sock_rdm_tx_attr = {
|
||||||
.caps = SOCK_EP_RDM_CAP,
|
.caps = SOCK_EP_RDM_CAP,
|
||||||
.mode = SOCK_MODE,
|
.mode = SOCK_MODE,
|
||||||
.op_flags = FI_TRANSMIT_COMPLETE,
|
.op_flags = SOCK_EP_DEFAULT_OP_FLAGS,
|
||||||
.msg_order = SOCK_EP_MSG_ORDER,
|
.msg_order = SOCK_EP_MSG_ORDER,
|
||||||
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
.inject_size = SOCK_EP_MAX_INJECT_SZ,
|
||||||
.size = SOCK_EP_TX_SZ,
|
.size = SOCK_EP_TX_SZ,
|
||||||
|
@ -383,8 +383,8 @@ void sock_fabric_remove_service(struct sock_fabric *fab, int service)
|
|||||||
fastlock_release(&fab->lock);
|
fastlock_release(&fab->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_get_src_addr(struct sockaddr_in *dest_addr,
|
int sock_get_src_addr(struct sockaddr_in *dest_addr,
|
||||||
struct sockaddr_in *src_addr)
|
struct sockaddr_in *src_addr)
|
||||||
{
|
{
|
||||||
int sock, ret;
|
int sock, ret;
|
||||||
socklen_t len;
|
socklen_t len;
|
||||||
@ -402,6 +402,7 @@ static int sock_get_src_addr(struct sockaddr_in *dest_addr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = getsockname(sock, (struct sockaddr *) src_addr, &len);
|
ret = getsockname(sock, (struct sockaddr *) src_addr, &len);
|
||||||
|
src_addr->sin_port = 0;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
SOCK_LOG_INFO("getsockname failed\n");
|
SOCK_LOG_INFO("getsockname failed\n");
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
|
@ -205,6 +205,7 @@ static ssize_t sock_ep_sendmsg(struct fid_ep *ep, const struct fi_msg *msg,
|
|||||||
SOCK_LOG_INFO("New sendmsg on TX: %p using conn: %p\n",
|
SOCK_LOG_INFO("New sendmsg on TX: %p using conn: %p\n",
|
||||||
tx_ctx, conn);
|
tx_ctx, conn);
|
||||||
|
|
||||||
|
SOCK_EP_SET_TX_OP_FLAGS(flags);
|
||||||
if (flags & SOCK_USE_OP_FLAGS)
|
if (flags & SOCK_USE_OP_FLAGS)
|
||||||
flags |= tx_ctx->attr.op_flags;
|
flags |= tx_ctx->attr.op_flags;
|
||||||
memset(&tx_op, 0, sizeof(struct sock_op));
|
memset(&tx_op, 0, sizeof(struct sock_op));
|
||||||
@ -516,6 +517,7 @@ static ssize_t sock_ep_tsendmsg(struct fid_ep *ep,
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
return -FI_EAGAIN;
|
return -FI_EAGAIN;
|
||||||
|
|
||||||
|
SOCK_EP_SET_TX_OP_FLAGS(flags);
|
||||||
if (flags & SOCK_USE_OP_FLAGS)
|
if (flags & SOCK_USE_OP_FLAGS)
|
||||||
flags |= tx_ctx->attr.op_flags;
|
flags |= tx_ctx->attr.op_flags;
|
||||||
|
|
||||||
|
@ -349,7 +349,7 @@ static void sock_pe_report_rx_error(struct sock_pe_entry *pe_entry, int rem)
|
|||||||
sock_cntr_err_inc(pe_entry->comp->recv_cntr);
|
sock_cntr_err_inc(pe_entry->comp->recv_cntr);
|
||||||
if (pe_entry->comp->recv_cq)
|
if (pe_entry->comp->recv_cq)
|
||||||
sock_cq_report_error(pe_entry->comp->recv_cq, pe_entry, rem,
|
sock_cq_report_error(pe_entry->comp->recv_cq, pe_entry, rem,
|
||||||
FI_ENOSPC, -FI_ENOSPC, NULL);
|
FI_ETRUNC, -FI_ETRUNC, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sock_pe_report_tx_rma_read_err(struct sock_pe_entry *pe_entry, int err)
|
static void sock_pe_report_tx_rma_read_err(struct sock_pe_entry *pe_entry, int err)
|
||||||
|
@ -113,6 +113,7 @@ static ssize_t sock_ep_rma_readmsg(struct fid_ep *ep,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SOCK_EP_SET_TX_OP_FLAGS(flags);
|
||||||
if (flags & SOCK_USE_OP_FLAGS)
|
if (flags & SOCK_USE_OP_FLAGS)
|
||||||
flags |= tx_ctx->attr.op_flags;
|
flags |= tx_ctx->attr.op_flags;
|
||||||
memset(&tx_op, 0, sizeof(struct sock_op));
|
memset(&tx_op, 0, sizeof(struct sock_op));
|
||||||
@ -137,7 +138,6 @@ static ssize_t sock_ep_rma_readmsg(struct fid_ep *ep,
|
|||||||
for (i = 0; i< msg->iov_count; i++) {
|
for (i = 0; i< msg->iov_count; i++) {
|
||||||
tx_iov.iov.addr = (uintptr_t) msg->msg_iov[i].iov_base;
|
tx_iov.iov.addr = (uintptr_t) msg->msg_iov[i].iov_base;
|
||||||
tx_iov.iov.len = msg->msg_iov[i].iov_len;
|
tx_iov.iov.len = msg->msg_iov[i].iov_len;
|
||||||
tx_iov.iov.key = (uintptr_t) msg->desc[i];
|
|
||||||
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
||||||
dst_len += tx_iov.iov.len;
|
dst_len += tx_iov.iov.len;
|
||||||
}
|
}
|
||||||
@ -255,6 +255,7 @@ static ssize_t sock_ep_rma_writemsg(struct fid_ep *ep,
|
|||||||
if (!conn)
|
if (!conn)
|
||||||
return -FI_EAGAIN;
|
return -FI_EAGAIN;
|
||||||
|
|
||||||
|
SOCK_EP_SET_TX_OP_FLAGS(flags);
|
||||||
if (flags & SOCK_USE_OP_FLAGS)
|
if (flags & SOCK_USE_OP_FLAGS)
|
||||||
flags |= tx_ctx->attr.op_flags;
|
flags |= tx_ctx->attr.op_flags;
|
||||||
memset(&tx_op, 0, sizeof(struct sock_op));
|
memset(&tx_op, 0, sizeof(struct sock_op));
|
||||||
@ -304,7 +305,6 @@ static ssize_t sock_ep_rma_writemsg(struct fid_ep *ep,
|
|||||||
for (i = 0; i< msg->iov_count; i++) {
|
for (i = 0; i< msg->iov_count; i++) {
|
||||||
tx_iov.iov.addr = (uintptr_t) msg->msg_iov[i].iov_base;
|
tx_iov.iov.addr = (uintptr_t) msg->msg_iov[i].iov_base;
|
||||||
tx_iov.iov.len = msg->msg_iov[i].iov_len;
|
tx_iov.iov.len = msg->msg_iov[i].iov_len;
|
||||||
tx_iov.iov.key = (uintptr_t) msg->desc[i];
|
|
||||||
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
sock_tx_ctx_write(tx_ctx, &tx_iov, sizeof(tx_iov));
|
||||||
src_len += tx_iov.iov.len;
|
src_len += tx_iov.iov.len;
|
||||||
}
|
}
|
||||||
|
@ -456,7 +456,8 @@ ssize_t usdf_msg_ud_prefix_recv(struct fid_ep *ep, void *buf, size_t len, void *
|
|||||||
void *context);
|
void *context);
|
||||||
ssize_t usdf_msg_ud_prefix_recvv(struct fid_ep *ep, const struct iovec *iov,
|
ssize_t usdf_msg_ud_prefix_recvv(struct fid_ep *ep, const struct iovec *iov,
|
||||||
void **desc, size_t count, void *context);
|
void **desc, size_t count, void *context);
|
||||||
|
|
||||||
|
|
||||||
|
/* Fake IBV provider */
|
||||||
|
void usdf_setup_fake_ibv_provider(void);
|
||||||
|
|
||||||
#endif /* _USDF_H_ */
|
#endif /* _USDF_H_ */
|
||||||
|
@ -1093,5 +1093,8 @@ struct fi_provider usdf_ops = {
|
|||||||
|
|
||||||
USNIC_INI
|
USNIC_INI
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_VERBS
|
||||||
|
usdf_setup_fake_ibv_provider();
|
||||||
|
#endif
|
||||||
return (&usdf_ops);
|
return (&usdf_ops);
|
||||||
}
|
}
|
||||||
|
128
opal/mca/common/libfabric/libfabric/prov/usnic/src/usdf_fake_ibv.c
Обычный файл
128
opal/mca/common/libfabric/libfabric/prov/usnic/src/usdf_fake_ibv.c
Обычный файл
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Cisco Systems, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is available to you under a choice of one of two
|
||||||
|
* licenses. You may choose to be licensed under the terms of the GNU
|
||||||
|
* General Public License (GPL) Version 2, available from the file
|
||||||
|
* COPYING in the main directory of this source tree, or the
|
||||||
|
* BSD license below:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or
|
||||||
|
* without modification, are permitted provided that the following
|
||||||
|
* conditions are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer.
|
||||||
|
*
|
||||||
|
* - Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code in this file prevents spurious libibverbs warnings on
|
||||||
|
* stderr about devices that it doesn't recognize.
|
||||||
|
*
|
||||||
|
* Specifically, Cisco usNIC devices are exposed through the Linux
|
||||||
|
* InfiniBand kernel interface (i.e., they show up in
|
||||||
|
* /sys/class/infiniband). However, the userspace side of these
|
||||||
|
* drivers is not exposed through libibverbs (i.e., there is no
|
||||||
|
* libibverbs provider/plugin for usNIC). Therefore, when
|
||||||
|
* ibv_get_device_list() is invoked, libibverbs cannot find a plugin
|
||||||
|
* for usnic devices. This causes libibverbs to emit a spurious
|
||||||
|
* warning message on stderr.
|
||||||
|
*
|
||||||
|
* Since libfabric can have a verbs provider, libibverbs is invoked,
|
||||||
|
* triggering the sequence described above, resulting in warning
|
||||||
|
* messages about usnic devices. To avoid these extra stderr
|
||||||
|
* warnings, we insert a fake usnic verbs libibverbs provider that
|
||||||
|
* safely squelches these warnings.
|
||||||
|
*
|
||||||
|
* More specifically: the userspace side of usNIC is exposed through
|
||||||
|
* libfabric; we don't need libibverbs warnings about not being able
|
||||||
|
* to find a usnic driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <infiniband/verbs.h>
|
||||||
|
#include <infiniband/driver.h>
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
#ifndef PCI_VENDOR_ID_CISCO
|
||||||
|
#define PCI_VENDOR_ID_CISCO 0x1137
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct ibv_context *fake_alloc_context(struct ibv_device *ibdev,
|
||||||
|
int cmd_fd)
|
||||||
|
{
|
||||||
|
/* Nothing to do here */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fake_free_context(struct ibv_context *ibctx)
|
||||||
|
{
|
||||||
|
/* Nothing to do here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put just enough in here to convince libibverbs that this is a valid
|
||||||
|
device, and a little extra just in case someone looks at this
|
||||||
|
struct in a debugger. */
|
||||||
|
static struct ibv_device fake_dev = {
|
||||||
|
.ops = {
|
||||||
|
.alloc_context = fake_alloc_context,
|
||||||
|
.free_context = fake_free_context
|
||||||
|
},
|
||||||
|
.name = "fake ibv_device inserted by libfabric:usNIC"
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ibv_device *fake_driver_init(const char *uverbs_sys_path,
|
||||||
|
int abi_version)
|
||||||
|
{
|
||||||
|
char value[8];
|
||||||
|
int vendor;
|
||||||
|
|
||||||
|
/* This function should only be invoked for
|
||||||
|
/sys/class/infiniband/usnic_X devices, but double check just to
|
||||||
|
be absolutely sure: read the vendor ID and ensure that it is
|
||||||
|
Cisco. */
|
||||||
|
if (ibv_read_sysfs_file(uverbs_sys_path, "device/vendor",
|
||||||
|
value, sizeof(value)) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sscanf(value, "%i", &vendor);
|
||||||
|
|
||||||
|
if (vendor == PCI_VENDOR_ID_CISCO) {
|
||||||
|
return &fake_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find a device that we want to support */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void usdf_setup_fake_ibv_provider(void)
|
||||||
|
{
|
||||||
|
/* Register a fake driver for "usnic_verbs" devices */
|
||||||
|
ibv_register_driver("usnic_verbs", fake_driver_init);
|
||||||
|
}
|
@ -750,10 +750,12 @@ usdf_rdm_inject(struct fid_ep *fep, const void *buf, size_t len,
|
|||||||
wqe->rd_msg_id_be = htonl(msg_id);
|
wqe->rd_msg_id_be = htonl(msg_id);
|
||||||
|
|
||||||
memcpy(wqe->rd_inject_buf, buf, len);
|
memcpy(wqe->rd_inject_buf, buf, len);
|
||||||
|
wqe->rd_iov[0].iov_base = wqe->rd_inject_buf;
|
||||||
|
wqe->rd_iov[0].iov_len = len;
|
||||||
wqe->rd_last_iov = 0;
|
wqe->rd_last_iov = 0;
|
||||||
|
|
||||||
wqe->rd_cur_iov = 0;
|
wqe->rd_cur_iov = 0;
|
||||||
wqe->rd_cur_ptr = buf;
|
wqe->rd_cur_ptr = wqe->rd_inject_buf;
|
||||||
wqe->rd_iov_resid = len;
|
wqe->rd_iov_resid = len;
|
||||||
wqe->rd_resid = len;
|
wqe->rd_resid = len;
|
||||||
wqe->rd_length = len;
|
wqe->rd_length = len;
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#ifndef PCI_VENDOR_ID_CISCO
|
#ifndef PCI_VENDOR_ID_CISCO
|
||||||
#define PCI_VENDOR_ID_CISCO 0x1137
|
#define PCI_VENDOR_ID_CISCO 0x1137
|
||||||
@ -204,8 +205,19 @@ static inline bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys
|
|||||||
#endif /*LINUX >= 3.3.0*/
|
#endif /*LINUX >= 3.3.0*/
|
||||||
|
|
||||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
|
||||||
|
#if (!RHEL_RELEASE_CODE || (RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6, 6)))
|
||||||
|
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0))
|
||||||
|
enum pkt_hash_types {
|
||||||
|
PKT_HASH_TYPE_NONE, /* Undefined type */
|
||||||
|
PKT_HASH_TYPE_L2, /* Input: src_MAC, dest_MAC */
|
||||||
|
PKT_HASH_TYPE_L3, /* Input: src_IP, dst_IP */
|
||||||
|
PKT_HASH_TYPE_L4, /* Input: src_IP, dst_IP, src_port, dst_port */
|
||||||
|
};
|
||||||
|
#endif /*kernel < 3.13 */
|
||||||
|
#endif /* !rhel or rhel < 6.6 */
|
||||||
#define skb_get_hash_raw(skb) (skb)->rxhash
|
#define skb_get_hash_raw(skb) (skb)->rxhash
|
||||||
#endif
|
#define skb_set_hash(skb, hash, type) skb->rxhash = (type == PKT_HASH_TYPE_L4) ? hash : 0;
|
||||||
|
#endif /* kernel < 3.14 */
|
||||||
|
|
||||||
#if !defined(__VMKLNX__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
|
#if !defined(__VMKLNX__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24))
|
||||||
#define enic_wq_lock(wq_lock) spin_lock_irqsave(wq_lock, flags)
|
#define enic_wq_lock(wq_lock) spin_lock_irqsave(wq_lock, flags)
|
||||||
|
@ -130,6 +130,53 @@ _usd_post_send_two(
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
_usd_post_send_two_vlan(
|
||||||
|
struct usd_wq *wq,
|
||||||
|
const void *hdr,
|
||||||
|
size_t hdrlen,
|
||||||
|
const void *pkt,
|
||||||
|
size_t pktlen,
|
||||||
|
u_int8_t cq_entry,
|
||||||
|
u_int16_t vlan_tag)
|
||||||
|
{
|
||||||
|
struct vnic_wq *vwq;
|
||||||
|
uint32_t index;
|
||||||
|
struct wq_enet_desc *desc;
|
||||||
|
u_int8_t offload_mode = 0, eop;
|
||||||
|
u_int16_t mss = 7, header_length = 0;
|
||||||
|
u_int8_t vlan_tag_insert = 1, loopback = 0, fcoe_encap = 0;
|
||||||
|
|
||||||
|
vwq = &wq->uwq_vnic_wq;
|
||||||
|
desc = wq->uwq_next_desc;
|
||||||
|
index = wq->uwq_post_index;
|
||||||
|
|
||||||
|
eop = 0;
|
||||||
|
wq_enet_desc_enc(desc, (uintptr_t)hdr, hdrlen,
|
||||||
|
mss, header_length, offload_mode,
|
||||||
|
eop, 0, fcoe_encap,
|
||||||
|
vlan_tag_insert, vlan_tag, loopback);
|
||||||
|
|
||||||
|
desc = (struct wq_enet_desc *) ((uintptr_t)wq->uwq_desc_ring + (index<<4));
|
||||||
|
index = (index+1) & wq->uwq_post_index_mask;
|
||||||
|
|
||||||
|
eop = 1;
|
||||||
|
wq_enet_desc_enc(desc, (uintptr_t)pkt, pktlen,
|
||||||
|
mss, header_length, offload_mode,
|
||||||
|
eop, cq_entry, fcoe_encap,
|
||||||
|
vlan_tag_insert, vlan_tag, loopback);
|
||||||
|
wmb();
|
||||||
|
|
||||||
|
iowrite32(index, &vwq->ctrl->posted_index);
|
||||||
|
|
||||||
|
wq->uwq_next_desc = (struct wq_enet_desc *)
|
||||||
|
((uintptr_t)wq->uwq_desc_ring + (index<<4));
|
||||||
|
wq->uwq_post_index = (index+1) & wq->uwq_post_index_mask;
|
||||||
|
wq->uwq_send_credits -= 2;
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Consume iov count credits, assumes that iov[0] includes usnic header
|
* Consume iov count credits, assumes that iov[0] includes usnic header
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +78,50 @@ usd_post_send_one_udp_normal(
|
|||||||
qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
|
qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
|
||||||
|
|
||||||
last_post = _usd_post_send_two(wq, hdr, sizeof(*hdr), buf, len,
|
last_post = _usd_post_send_two(wq, hdr, sizeof(*hdr), buf, len,
|
||||||
USD_SF_ISSET(flags, SIGNAL));
|
USD_SF_ISSET(flags, SIGNAL));
|
||||||
|
|
||||||
|
info = &wq->uwq_post_info[last_post];
|
||||||
|
info->wp_context = context;
|
||||||
|
info->wp_len = len;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
usd_post_send_one_vlan_udp_normal(
|
||||||
|
struct usd_qp *uqp,
|
||||||
|
struct usd_dest *dest,
|
||||||
|
const void *buf,
|
||||||
|
size_t len,
|
||||||
|
uint16_t vlan,
|
||||||
|
uint32_t flags,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
struct usd_qp_impl *qp;
|
||||||
|
struct usd_udp_hdr *hdr;
|
||||||
|
struct usd_wq *wq;
|
||||||
|
uint32_t last_post;
|
||||||
|
uint8_t *copybuf;
|
||||||
|
struct usd_wq_post_info *info;
|
||||||
|
|
||||||
|
qp = to_qpi(uqp);
|
||||||
|
wq = &qp->uq_wq;
|
||||||
|
copybuf = wq->uwq_copybuf + wq->uwq_post_index * USD_SEND_MAX_COPY;
|
||||||
|
|
||||||
|
hdr = (struct usd_udp_hdr *)copybuf;
|
||||||
|
memcpy(hdr, &dest->ds_dest.ds_udp.u_hdr, sizeof(*hdr));
|
||||||
|
|
||||||
|
/* adjust lengths and insert source port */
|
||||||
|
hdr->uh_ip.tot_len = htons(len + sizeof(struct usd_udp_hdr) -
|
||||||
|
sizeof(struct ether_header));
|
||||||
|
hdr->uh_udp.len = htons((sizeof(struct usd_udp_hdr) -
|
||||||
|
sizeof(struct ether_header) -
|
||||||
|
sizeof(struct iphdr)) + len);
|
||||||
|
hdr->uh_udp.source =
|
||||||
|
qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
|
||||||
|
|
||||||
|
last_post = _usd_post_send_two_vlan(wq, hdr, sizeof(*hdr), buf, len,
|
||||||
|
USD_SF_ISSET(flags, SIGNAL), vlan);
|
||||||
|
|
||||||
info = &wq->uwq_post_info[last_post];
|
info = &wq->uwq_post_info[last_post];
|
||||||
info->wp_context = context;
|
info->wp_context = context;
|
||||||
@ -278,4 +321,5 @@ struct usd_qp_ops usd_qp_ops_udp_normal = {
|
|||||||
.qo_post_send_one_copy = usd_post_send_one_copy_udp_normal,
|
.qo_post_send_one_copy = usd_post_send_one_copy_udp_normal,
|
||||||
.qo_post_send_two_copy = usd_post_send_two_copy_udp_normal,
|
.qo_post_send_two_copy = usd_post_send_two_copy_udp_normal,
|
||||||
.qo_post_send_iov = usd_post_send_iov_udp_normal,
|
.qo_post_send_iov = usd_post_send_iov_udp_normal,
|
||||||
|
.qo_post_send_one_vlan = usd_post_send_one_vlan_udp_normal,
|
||||||
};
|
};
|
||||||
|
@ -134,6 +134,7 @@ struct usnic_vnic_barres_info {
|
|||||||
|
|
||||||
struct usnic_ib_create_qp_resp_v0 {
|
struct usnic_ib_create_qp_resp_v0 {
|
||||||
USNIC_IB_CREATE_QP_RESP_V0_FIELDS
|
USNIC_IB_CREATE_QP_RESP_V0_FIELDS
|
||||||
|
u32 reserved[9];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usnic_ib_create_qp_resp {
|
struct usnic_ib_create_qp_resp {
|
||||||
@ -146,6 +147,10 @@ struct usnic_ib_create_qp_resp {
|
|||||||
u32 pad_to_8byte;
|
u32 pad_to_8byte;
|
||||||
} v1;
|
} v1;
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
/* v0 had a "reserved[9]" field, must not shrink the response or we can
|
||||||
|
* corrupt newer clients running on older kernels */
|
||||||
|
u32 reserved[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define USNIC_CTX_RESP_VERSION 1
|
#define USNIC_CTX_RESP_VERSION 1
|
||||||
|
@ -151,6 +151,9 @@ struct usd_qp_ops {
|
|||||||
int (*qo_post_send_iov)(struct usd_qp *qp,
|
int (*qo_post_send_iov)(struct usd_qp *qp,
|
||||||
struct usd_dest *dest, const struct iovec* iov,
|
struct usd_dest *dest, const struct iovec* iov,
|
||||||
size_t iov_count, uint32_t flags, void *context);
|
size_t iov_count, uint32_t flags, void *context);
|
||||||
|
int (*qo_post_send_one_vlan)(struct usd_qp *qp,
|
||||||
|
struct usd_dest *dest, const void *buf, size_t len,
|
||||||
|
u_int16_t vlan, uint32_t flags, void *context);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -264,7 +267,7 @@ struct usd_device_entry {
|
|||||||
* Send flags
|
* Send flags
|
||||||
*/
|
*/
|
||||||
enum usd_send_flag_shift {
|
enum usd_send_flag_shift {
|
||||||
USD_SFS_SIGNAL
|
USD_SFS_SIGNAL,
|
||||||
};
|
};
|
||||||
#define USD_SF_SIGNAL (1 << USD_SFS_SIGNAL)
|
#define USD_SF_SIGNAL (1 << USD_SFS_SIGNAL)
|
||||||
|
|
||||||
@ -539,6 +542,28 @@ usd_post_send_one(
|
|||||||
qp, dest, buf, len, flags, context);
|
qp, dest, buf, len, flags, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* post a single-buffer send from registered memory to specified VLAN
|
||||||
|
* IN:
|
||||||
|
* qp
|
||||||
|
* dest
|
||||||
|
* buf -
|
||||||
|
* Requires 2 send credits
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
usd_post_send_one_vlan(
|
||||||
|
struct usd_qp *qp,
|
||||||
|
struct usd_dest *dest,
|
||||||
|
const void *buf,
|
||||||
|
size_t len,
|
||||||
|
u_int16_t vlan,
|
||||||
|
uint32_t flags,
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
return qp->uq_ops.qo_post_send_one_vlan(
|
||||||
|
qp, dest, buf, len, vlan, flags, context);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* post a single-buffer send from registered memory
|
* post a single-buffer send from registered memory
|
||||||
* Caller must allow sufficient space *before* the packet for usd header
|
* Caller must allow sufficient space *before* the packet for usd header
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include <infiniband/ib.h>
|
#include <infiniband/ib.h>
|
||||||
#include <infiniband/verbs.h>
|
#include <infiniband/verbs.h>
|
||||||
|
#include <infiniband/driver.h>
|
||||||
#include <rdma/rdma_cma.h>
|
#include <rdma/rdma_cma.h>
|
||||||
|
|
||||||
#include <rdma/fabric.h>
|
#include <rdma/fabric.h>
|
||||||
@ -174,6 +175,8 @@ const struct fi_domain_attr verbs_domain_attr = {
|
|||||||
.mr_mode = FI_MR_BASIC,
|
.mr_mode = FI_MR_BASIC,
|
||||||
.mr_key_size = sizeof_field(struct ibv_sge, lkey),
|
.mr_key_size = sizeof_field(struct ibv_sge, lkey),
|
||||||
.cq_data_size = sizeof_field(struct ibv_send_wr, imm_data),
|
.cq_data_size = sizeof_field(struct ibv_send_wr, imm_data),
|
||||||
|
.tx_ctx_cnt = 1024,
|
||||||
|
.rx_ctx_cnt = 1024,
|
||||||
.max_ep_tx_ctx = 1,
|
.max_ep_tx_ctx = 1,
|
||||||
.max_ep_rx_ctx = 1,
|
.max_ep_rx_ctx = 1,
|
||||||
};
|
};
|
||||||
@ -193,7 +196,6 @@ const struct fi_rx_attr verbs_rx_attr = {
|
|||||||
.mode = VERBS_RX_MODE,
|
.mode = VERBS_RX_MODE,
|
||||||
.msg_order = VERBS_MSG_ORDER,
|
.msg_order = VERBS_MSG_ORDER,
|
||||||
.total_buffered_recv = 0,
|
.total_buffered_recv = 0,
|
||||||
.size = 256,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct fi_tx_attr verbs_tx_attr = {
|
const struct fi_tx_attr verbs_tx_attr = {
|
||||||
@ -202,7 +204,7 @@ const struct fi_tx_attr verbs_tx_attr = {
|
|||||||
.op_flags = VERBS_TX_OP_FLAGS,
|
.op_flags = VERBS_TX_OP_FLAGS,
|
||||||
.msg_order = VERBS_MSG_ORDER,
|
.msg_order = VERBS_MSG_ORDER,
|
||||||
.inject_size = 0,
|
.inject_size = 0,
|
||||||
.size = 256,
|
.rma_iov_limit = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct fi_info *verbs_info = NULL;
|
static struct fi_info *verbs_info = NULL;
|
||||||
@ -603,8 +605,9 @@ static int fi_ibv_rai_to_fi(struct rdma_addrinfo *rai, struct fi_info *fi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int fi_ibv_get_inject_size(struct ibv_context *ctx,
|
static inline int fi_ibv_get_qp_cap(struct ibv_context *ctx,
|
||||||
const struct fi_info *hints, struct fi_info *info)
|
const struct fi_info *hints, struct ibv_device_attr *device_attr,
|
||||||
|
struct fi_info *info)
|
||||||
{
|
{
|
||||||
struct ibv_pd *pd;
|
struct ibv_pd *pd;
|
||||||
struct ibv_cq *cq;
|
struct ibv_cq *cq;
|
||||||
@ -622,13 +625,24 @@ static inline int fi_ibv_get_inject_size(struct ibv_context *ctx,
|
|||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: serialize access to string buffers */
|
||||||
|
fi_read_file(FI_CONF_DIR, "def_send_wr",
|
||||||
|
def_send_wr, sizeof def_send_wr);
|
||||||
|
fi_read_file(FI_CONF_DIR, "def_recv_wr",
|
||||||
|
def_recv_wr, sizeof def_recv_wr);
|
||||||
|
fi_read_file(FI_CONF_DIR, "def_send_sge",
|
||||||
|
def_send_sge, sizeof def_send_sge);
|
||||||
|
fi_read_file(FI_CONF_DIR, "def_recv_sge",
|
||||||
|
def_recv_sge, sizeof def_recv_sge);
|
||||||
|
|
||||||
memset(&init_attr, 0, sizeof init_attr);
|
memset(&init_attr, 0, sizeof init_attr);
|
||||||
init_attr.send_cq = cq;
|
init_attr.send_cq = cq;
|
||||||
init_attr.recv_cq = cq;
|
init_attr.recv_cq = cq;
|
||||||
init_attr.cap.max_send_wr = 1;
|
init_attr.cap.max_send_wr = atoi(def_send_wr);
|
||||||
init_attr.cap.max_recv_wr = 1;
|
init_attr.cap.max_recv_wr = atoi(def_recv_wr);
|
||||||
init_attr.cap.max_send_sge = 1;
|
init_attr.cap.max_send_sge = MIN(atoi(def_send_sge), device_attr->max_sge);
|
||||||
init_attr.cap.max_recv_sge = 1;
|
init_attr.cap.max_recv_sge = MIN(atoi(def_recv_sge), device_attr->max_sge);
|
||||||
|
|
||||||
if (hints && hints->tx_attr && hints->tx_attr->inject_size) {
|
if (hints && hints->tx_attr && hints->tx_attr->inject_size) {
|
||||||
init_attr.cap.max_inline_data = hints->tx_attr->inject_size;
|
init_attr.cap.max_inline_data = hints->tx_attr->inject_size;
|
||||||
@ -646,7 +660,12 @@ static inline int fi_ibv_get_inject_size(struct ibv_context *ctx,
|
|||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->tx_attr->inject_size = init_attr.cap.max_inline_data;
|
info->tx_attr->inject_size = init_attr.cap.max_inline_data;
|
||||||
|
info->tx_attr->iov_limit = init_attr.cap.max_send_sge;
|
||||||
|
info->tx_attr->size = init_attr.cap.max_send_wr;
|
||||||
|
|
||||||
|
info->rx_attr->iov_limit = init_attr.cap.max_recv_sge;
|
||||||
|
info->rx_attr->size = init_attr.cap.max_recv_wr;
|
||||||
|
|
||||||
ibv_destroy_qp(qp);
|
ibv_destroy_qp(qp);
|
||||||
err2:
|
err2:
|
||||||
@ -664,24 +683,20 @@ static int fi_ibv_get_device_attrs(struct ibv_context *ctx,
|
|||||||
struct ibv_port_attr port_attr;
|
struct ibv_port_attr port_attr;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
ret = fi_ibv_get_inject_size(ctx, hints, info);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = ibv_query_device(ctx, &device_attr);
|
ret = ibv_query_device(ctx, &device_attr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
info->domain_attr->cq_cnt = device_attr.max_cq;
|
info->domain_attr->cq_cnt = device_attr.max_cq;
|
||||||
info->domain_attr->ep_cnt = device_attr.max_qp;
|
info->domain_attr->ep_cnt = device_attr.max_qp;
|
||||||
/* TODO find correct optimum values for ctx_cnt */
|
info->domain_attr->tx_ctx_cnt = MIN(info->domain_attr->tx_ctx_cnt, device_attr.max_qp);
|
||||||
info->domain_attr->tx_ctx_cnt = device_attr.max_qp;
|
info->domain_attr->rx_ctx_cnt = MIN(info->domain_attr->rx_ctx_cnt, device_attr.max_qp);
|
||||||
info->domain_attr->rx_ctx_cnt = device_attr.max_qp;
|
|
||||||
info->domain_attr->max_ep_tx_ctx = device_attr.max_qp;
|
info->domain_attr->max_ep_tx_ctx = device_attr.max_qp;
|
||||||
info->domain_attr->max_ep_rx_ctx = device_attr.max_qp;
|
info->domain_attr->max_ep_rx_ctx = device_attr.max_qp;
|
||||||
info->tx_attr->iov_limit = device_attr.max_sge;
|
|
||||||
info->tx_attr->rma_iov_limit = device_attr.max_sge;
|
ret = fi_ibv_get_qp_cap(ctx, hints, &device_attr, info);
|
||||||
info->rx_attr->iov_limit = device_attr.max_sge;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = ibv_query_port(ctx, 1, &port_attr);
|
ret = ibv_query_port(ctx, 1, &port_attr);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -694,6 +709,33 @@ static int fi_ibv_get_device_attrs(struct ibv_context *ctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USNIC plugs into the verbs framework, but is not a usable device.
|
||||||
|
* Manually check for devices and fail gracefully if none are present.
|
||||||
|
* This avoids the lower libraries (libibverbs and librdmacm) from
|
||||||
|
* reporting error messages to stderr.
|
||||||
|
*/
|
||||||
|
static int fi_ibv_have_device(void)
|
||||||
|
{
|
||||||
|
struct ibv_device **devs;
|
||||||
|
struct ibv_context *verbs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
devs = ibv_get_device_list(NULL);
|
||||||
|
if (!devs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; devs[i]; i++) {
|
||||||
|
verbs = ibv_open_device(devs[i]);
|
||||||
|
if (verbs) {
|
||||||
|
ibv_close_device(verbs);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int fi_ibv_init_info(const struct fi_info *hints)
|
static int fi_ibv_init_info(const struct fi_info *hints)
|
||||||
{
|
{
|
||||||
struct ibv_context *ctx, **ctx_list;
|
struct ibv_context *ctx, **ctx_list;
|
||||||
@ -709,16 +751,23 @@ static int fi_ibv_init_info(const struct fi_info *hints)
|
|||||||
if (verbs_info)
|
if (verbs_info)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
|
if (!fi_ibv_have_device()) {
|
||||||
|
ret = -FI_ENODATA;
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO Handle the case where multiple devices are returned */
|
/* TODO Handle the case where multiple devices are returned */
|
||||||
ctx_list = rdma_get_devices(&num_devices);
|
ctx_list = rdma_get_devices(&num_devices);
|
||||||
if (!num_devices)
|
if (!num_devices) {
|
||||||
return -errno;
|
ret = (errno == ENODEV) ? -FI_ENODATA : -errno;
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
ctx = *ctx_list;
|
ctx = *ctx_list;
|
||||||
|
|
||||||
if (!(fi = fi_allocinfo())) {
|
if (!(fi = fi_allocinfo())) {
|
||||||
ret = -FI_ENOMEM;
|
ret = -FI_ENOMEM;
|
||||||
goto err1;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
fi->caps = VERBS_CAPS;
|
fi->caps = VERBS_CAPS;
|
||||||
@ -732,20 +781,20 @@ static int fi_ibv_init_info(const struct fi_info *hints)
|
|||||||
|
|
||||||
ret = fi_ibv_get_device_attrs(ctx, hints, fi);
|
ret = fi_ibv_get_device_attrs(ctx, hints, fi);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err2;
|
goto err3;
|
||||||
|
|
||||||
switch (ctx->device->transport_type) {
|
switch (ctx->device->transport_type) {
|
||||||
case IBV_TRANSPORT_IB:
|
case IBV_TRANSPORT_IB:
|
||||||
if(ibv_query_gid(ctx, 1, 0, &gid)) {
|
if(ibv_query_gid(ctx, 1, 0, &gid)) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
goto err2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
name_len = strlen(VERBS_IB_PREFIX) + INET6_ADDRSTRLEN;
|
name_len = strlen(VERBS_IB_PREFIX) + INET6_ADDRSTRLEN;
|
||||||
|
|
||||||
if (!(fi->fabric_attr->name = calloc(1, name_len + 1))) {
|
if (!(fi->fabric_attr->name = calloc(1, name_len + 1))) {
|
||||||
ret = -FI_ENOMEM;
|
ret = -FI_ENOMEM;
|
||||||
goto err2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(fi->fabric_attr->name, name_len, VERBS_IB_PREFIX "%lx",
|
snprintf(fi->fabric_attr->name, name_len, VERBS_IB_PREFIX "%lx",
|
||||||
@ -757,7 +806,7 @@ static int fi_ibv_init_info(const struct fi_info *hints)
|
|||||||
fi->fabric_attr->name = strdup(VERBS_IWARP_FABRIC);
|
fi->fabric_attr->name = strdup(VERBS_IWARP_FABRIC);
|
||||||
if (!fi->fabric_attr->name) {
|
if (!fi->fabric_attr->name) {
|
||||||
ret = -FI_ENOMEM;
|
ret = -FI_ENOMEM;
|
||||||
goto err2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
fi->ep_attr->protocol = FI_PROTO_IWARP;
|
fi->ep_attr->protocol = FI_PROTO_IWARP;
|
||||||
@ -766,25 +815,26 @@ static int fi_ibv_init_info(const struct fi_info *hints)
|
|||||||
default:
|
default:
|
||||||
FI_INFO(&fi_ibv_prov, FI_LOG_CORE, "Unknown transport type");
|
FI_INFO(&fi_ibv_prov, FI_LOG_CORE, "Unknown transport type");
|
||||||
ret = -FI_ENODATA;
|
ret = -FI_ENODATA;
|
||||||
goto err2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(fi->domain_attr->name = strdup(ctx->device->name))) {
|
if (!(fi->domain_attr->name = strdup(ctx->device->name))) {
|
||||||
ret = -FI_ENOMEM;
|
ret = -FI_ENOMEM;
|
||||||
goto err2;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
verbs_info = fi;
|
verbs_info = fi;
|
||||||
rdma_free_devices(ctx_list);
|
rdma_free_devices(ctx_list);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
pthread_mutex_unlock(&verbs_info_lock);
|
pthread_mutex_unlock(&verbs_info_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err2:
|
|
||||||
|
err3:
|
||||||
fi_freeinfo(fi);
|
fi_freeinfo(fi);
|
||||||
err1:
|
err2:
|
||||||
rdma_free_devices(ctx_list);
|
rdma_free_devices(ctx_list);
|
||||||
|
err1:
|
||||||
|
pthread_mutex_unlock(&verbs_info_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3176,6 +3226,7 @@ static int fi_ibv_pep_listen(struct fid_pep *pep)
|
|||||||
|
|
||||||
static struct fi_ops_cm fi_ibv_pep_cm_ops = {
|
static struct fi_ops_cm fi_ibv_pep_cm_ops = {
|
||||||
.size = sizeof(struct fi_ops_cm),
|
.size = sizeof(struct fi_ops_cm),
|
||||||
|
.setname = fi_no_setname,
|
||||||
.getname = fi_ibv_pep_getname,
|
.getname = fi_ibv_pep_getname,
|
||||||
.getpeer = fi_no_getpeer,
|
.getpeer = fi_no_getpeer,
|
||||||
.connect = fi_no_connect,
|
.connect = fi_no_connect,
|
||||||
@ -3254,6 +3305,7 @@ err:
|
|||||||
static int fi_ibv_fabric_close(fid_t fid)
|
static int fi_ibv_fabric_close(fid_t fid)
|
||||||
{
|
{
|
||||||
fi_freeinfo(verbs_info);
|
fi_freeinfo(verbs_info);
|
||||||
|
verbs_info = NULL;
|
||||||
free(fid);
|
free(fid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,8 @@
|
|||||||
* Indentation delineates lists and dictionaries (or they can be inline).
|
* Indentation delineates lists and dictionaries (or they can be inline).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define FI_BUFSIZ 8192
|
||||||
|
|
||||||
#define TAB " "
|
#define TAB " "
|
||||||
|
|
||||||
#define CASEENUMSTR(SYM) \
|
#define CASEENUMSTR(SYM) \
|
||||||
@ -77,11 +79,11 @@ static void fi_remove_comma(char *buffer)
|
|||||||
|
|
||||||
static void strcatf(char *dest, const char *fmt, ...)
|
static void strcatf(char *dest, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
size_t len = strlen(dest);
|
size_t len = strnlen(dest,FI_BUFSIZ);
|
||||||
va_list arglist;
|
va_list arglist;
|
||||||
|
|
||||||
va_start (arglist, fmt);
|
va_start (arglist, fmt);
|
||||||
vsnprintf(&dest[len], BUFSIZ - 1 - len, fmt, arglist);
|
vsnprintf(&dest[len], FI_BUFSIZ - 1 - len, fmt, arglist);
|
||||||
va_end (arglist);
|
va_end (arglist);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +557,7 @@ char *DEFAULT_SYMVER_PRE(fi_tostr)(const void *data, enum fi_type datatype)
|
|||||||
enumval = *(const int *) data;
|
enumval = *(const int *) data;
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
buf = calloc(BUFSIZ, 1);
|
buf = calloc(FI_BUFSIZ, 1);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user