* [PATCH 0/3] DAPL: SRQ support for ofa providers
@ 2014-12-15 18:35 arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
[not found] ` <1418668558-695-1-git-send-email-arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 4+ messages in thread
From: arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w @ 2014-12-15 18:35 UTC (permalink / raw)
To: linux-rdma-u79uwXL29TY76Z2rM5mHXA; +Cc: Arlin Davis
From: Arlin Davis <arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Amir Hanania (2):
common: add srq support for openib verbs providers
dtest: add dtestsrq for SRQ example and provider testing
Arlin Davis (1):
dtestx: update IB extension example test with new v2.0.9 features
Makefile.am | 4 +
dapl/common/dapl_adapter_util.h | 13 +
dapl/common/dapl_cr_callback.c | 2 +-
dapl/common/dapl_ep_create.c | 2 +-
dapl/common/dapl_ep_create_with_srq.c | 53 +-
dapl/common/dapl_ep_free.c | 5 +
dapl/common/dapl_ep_post_recv.c | 5 +
dapl/common/dapl_ep_util.c | 29 +-
dapl/common/dapl_ep_util.h | 3 +-
dapl/common/dapl_evd_qp_async_error_callb.c | 15 +-
dapl/common/dapl_evd_util.c | 49 +-
dapl/common/dapl_srq_create.c | 23 +-
dapl/common/dapl_srq_free.c | 36 +-
dapl/common/dapl_srq_post_recv.c | 6 +-
dapl/common/dapl_srq_query.c | 6 +-
dapl/common/dapl_srq_resize.c | 9 +-
dapl/common/dapl_srq_set_lw.c | 4 +-
dapl/common/dapl_srq_util.c | 2 -
dapl/include/dapl.h | 2 +
dapl/openib_common/cq.c | 3 +-
dapl/openib_common/dapl_ib_common.h | 1 +
dapl/openib_common/dapl_ib_dto.h | 48 +
dapl/openib_common/qp.c | 5 +
dapl/openib_common/srq.c | 147 +++
dapl/openib_common/util.c | 9 +-
dat/include/dat2/dat.h | 3 +-
dat/include/dat2/dat_error.h | 1 +
test/dtest/Makefile.am | 6 +-
test/dtest/dtestsrq.c | 1605 +++++++++++++++++++++++++++
test/dtest/dtestx.c | 581 ++++++++---
30 files changed, 2444 insertions(+), 233 deletions(-)
create mode 100644 dapl/openib_common/srq.c
create mode 100644 test/dtest/dtestsrq.c
--
1.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] common: add srq support for openib verbs providers
[not found] ` <1418668558-695-1-git-send-email-arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2014-12-15 18:35 ` arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 2/3] dtest: add dtestsrq for SRQ example and provider testing arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 3/3] dtestx: update IB extension example test with new v2.0.9 features arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2 siblings, 0 replies; 4+ messages in thread
From: arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w @ 2014-12-15 18:35 UTC (permalink / raw)
To: linux-rdma-u79uwXL29TY76Z2rM5mHXA; +Cc: Amir Hanania
From: Amir Hanania <amir.hanania-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Add necessary components and hooks to support ib_verbs shared
receive queues for both RC and UD QP's. External interfaces
were already provided per DAT 2.0 specification but internal
support was missing.
A new dtestsrq will be provided with package for testing and
example code.
Acked-by: Arlin Davis <arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
Makefile.am | 4 +
dapl/common/dapl_adapter_util.h | 13 +++
dapl/common/dapl_cr_callback.c | 2 +-
dapl/common/dapl_ep_create.c | 2 +-
dapl/common/dapl_ep_create_with_srq.c | 53 ++++++----
dapl/common/dapl_ep_free.c | 5 +
dapl/common/dapl_ep_post_recv.c | 5 +
dapl/common/dapl_ep_util.c | 29 ++++--
dapl/common/dapl_ep_util.h | 3 +-
dapl/common/dapl_evd_qp_async_error_callb.c | 15 ++-
dapl/common/dapl_evd_util.c | 49 ++++++++-
dapl/common/dapl_srq_create.c | 23 ++---
dapl/common/dapl_srq_free.c | 36 +++----
dapl/common/dapl_srq_post_recv.c | 6 +-
dapl/common/dapl_srq_query.c | 6 +-
dapl/common/dapl_srq_resize.c | 9 +-
dapl/common/dapl_srq_set_lw.c | 4 +-
dapl/common/dapl_srq_util.c | 2 -
dapl/include/dapl.h | 2 +
dapl/openib_common/cq.c | 3 +-
dapl/openib_common/dapl_ib_common.h | 1 +
dapl/openib_common/dapl_ib_dto.h | 48 +++++++++
dapl/openib_common/qp.c | 5 +
dapl/openib_common/srq.c | 147 +++++++++++++++++++++++++++
dapl/openib_common/util.c | 9 ++-
dat/include/dat2/dat.h | 3 +-
dat/include/dat2/dat_error.h | 1 +
test/dtest/Makefile.am | 6 +-
28 files changed, 388 insertions(+), 103 deletions(-)
create mode 100644 dapl/openib_common/srq.c
diff --git a/Makefile.am b/Makefile.am
index f9c4093..7ad5af1 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -273,6 +273,7 @@ dapl_udapl_libdaplofa_la_SOURCES = dapl/udapl/dapl_init.c \
dapl/openib_common/cq.c \
dapl/openib_common/qp.c \
dapl/openib_common/util.c \
+ dapl/openib_common/srq.c \
dapl/openib_cma/cm.c \
dapl/openib_cma/device.c $(XPROGRAMS)
@@ -389,6 +390,7 @@ dapl_udapl_libdaploscm_la_SOURCES = dapl/udapl/dapl_init.c \
dapl/openib_common/cq.c \
dapl/openib_common/qp.c \
dapl/openib_common/util.c \
+ dapl/openib_common/srq.c \
dapl/openib_scm/cm.c \
dapl/openib_scm/device.c $(XPROGRAMS)
@@ -505,6 +507,7 @@ dapl_udapl_libdaploucm_la_SOURCES = dapl/udapl/dapl_init.c \
dapl/openib_common/cq.c \
dapl/openib_common/qp.c \
dapl/openib_common/util.c \
+ dapl/openib_common/srq.c \
dapl/openib_ucm/cm.c \
dapl/openib_ucm/device.c $(XPROGRAMS)
@@ -622,6 +625,7 @@ dapl_udapl_libdaplomcm_la_SOURCES = dapl/udapl/dapl_init.c \
dapl/openib_common/cq.c \
dapl/openib_common/qp.c \
dapl/openib_common/util.c \
+ dapl/openib_common/srq.c \
dapl/openib_mcm/cm.c \
dapl/openib_mcm/mix.c \
dapl/openib_mcm/proxy.c \
diff --git a/dapl/common/dapl_adapter_util.h b/dapl/common/dapl_adapter_util.h
index 9b12b2d..ba4e73b 100755
--- a/dapl/common/dapl_adapter_util.h
+++ b/dapl/common/dapl_adapter_util.h
@@ -263,6 +263,19 @@ dapls_evd_dto_wait (
IN DAPL_EVD *evd_ptr,
IN uint32_t timeout);
+DAT_RETURN
+dapls_ib_srq_alloc (
+ IN DAPL_SRQ *srq_ptr);
+
+DAT_RETURN
+dapls_ib_srq_free (
+ IN DAPL_SRQ *srq_ptr);
+
+DAT_RETURN
+dapls_ib_srq_resize(
+ IN DAPL_SRQ *srq_ptr,
+ IN uint32_t new_max_wr);
+
#ifdef DAT_EXTENSIONS
void
dapls_cqe_to_event_extension(
diff --git a/dapl/common/dapl_cr_callback.c b/dapl/common/dapl_cr_callback.c
index 8bfbb3e..1b7e6be 100644
--- a/dapl/common/dapl_cr_callback.c
+++ b/dapl/common/dapl_cr_callback.c
@@ -366,7 +366,7 @@ dapli_connection_request(IN dp_ib_cm_handle_t ib_cm_handle,
* requestor that we cant help them.
*/
ia_ptr = sp_ptr->header.owner_ia;
- ep_ptr = dapl_ep_alloc(ia_ptr, NULL);
+ ep_ptr = dapl_ep_alloc(ia_ptr, NULL, DAT_FALSE);
if (ep_ptr == NULL) {
dapls_cr_free(cr_ptr);
/* Invoking function will call dapls_ib_cm_reject() */
diff --git a/dapl/common/dapl_ep_create.c b/dapl/common/dapl_ep_create.c
index ec11c7c..4001d26 100644
--- a/dapl/common/dapl_ep_create.c
+++ b/dapl/common/dapl_ep_create.c
@@ -237,7 +237,7 @@ dapl_ep_create(IN DAT_IA_HANDLE ia_handle,
}
/* Allocate EP */
- ep_ptr = dapl_ep_alloc(ia_ptr, ep_attr);
+ ep_ptr = dapl_ep_alloc(ia_ptr, ep_attr, DAT_FALSE);
if (ep_ptr == NULL) {
dat_status =
DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
diff --git a/dapl/common/dapl_ep_create_with_srq.c b/dapl/common/dapl_ep_create_with_srq.c
index b85abfd..1f489ff 100644
--- a/dapl/common/dapl_ep_create_with_srq.c
+++ b/dapl/common/dapl_ep_create_with_srq.c
@@ -84,6 +84,7 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
DAT_EP_ATTR ep_attr_limit;
DAPL_EVD *evd_ptr;
DAT_RETURN dat_status;
+ *ep_handle = NULL;
dat_status = DAT_SUCCESS;
dapl_dbg_log(DAPL_DBG_TYPE_API,
@@ -146,25 +147,37 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
goto bail;
}
+ if (ep_handle == NULL) {
+ dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG7);
+ goto bail;
+ }
+
+ if (DAPL_BAD_PTR(ep_attr)) {
+ dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);
+ goto bail;
+ }
+
/*
* Verify the SRQ handle. It is an error to invoke this call with
* a NULL handle
*/
+ dapl_os_lock(&ia_ptr->header.lock);
if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) {
dat_status =
DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_SRQ);
+ dapl_os_unlock(&ia_ptr->header.lock);
goto bail;
}
-
- if (ep_handle == NULL) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG7);
+ if (((DAPL_SRQ *) srq_handle)->param.srq_state ==
+ DAT_SRQ_STATE_SHUTDOWN) {
+ dat_status =
+ DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_SRQ_SHUTDOWN);
+ dapl_os_unlock(&ia_ptr->header.lock);
goto bail;
- }
- if (DAPL_BAD_PTR(ep_attr)) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);
- goto bail;
}
+ dapl_os_atomic_inc(&((DAPL_SRQ *) srq_handle)->srq_ref_count);
+ dapl_os_unlock(&ia_ptr->header.lock);
/*
* Qualify EP Attributes are legal and make sense. Note that if one
@@ -173,8 +186,7 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
* the respective queue.
*/
if (ep_attr != NULL &&
- (ep_attr->service_type != DAT_SERVICE_TYPE_RC ||
- (recv_evd_handle == DAT_HANDLE_NULL && ep_attr->max_recv_dtos != 0)
+ ((recv_evd_handle == DAT_HANDLE_NULL && ep_attr->max_recv_dtos != 0)
|| (recv_evd_handle != DAT_HANDLE_NULL
&& ep_attr->max_recv_dtos == 0)
|| (request_evd_handle == DAT_HANDLE_NULL
@@ -186,6 +198,7 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
dapl_ep_check_recv_completion_flags(ep_attr->
recv_completion_flags)))) {
dat_status = DAT_INVALID_PARAMETER | DAT_INVALID_ARG6;
+ dapl_os_atomic_dec(&((DAPL_SRQ *) srq_handle)->srq_ref_count);
goto bail;
}
@@ -195,6 +208,7 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
dat_status = dapls_ib_query_hca(ia_ptr->hca_ptr,
NULL, &ep_attr_limit, NULL);
if (dat_status != DAT_SUCCESS) {
+ dapl_os_atomic_dec(&((DAPL_SRQ *) srq_handle)->srq_ref_count);
goto bail;
}
if (ep_attr->max_mtu_size > ep_attr_limit.max_mtu_size ||
@@ -209,6 +223,8 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
ep_attr_limit.max_rdma_read_out)
{
dat_status = DAT_INVALID_PARAMETER | DAT_INVALID_ARG6;
+ dapl_os_atomic_dec(&((DAPL_SRQ *) srq_handle)->
+ srq_ref_count);
goto bail;
}
}
@@ -246,22 +262,12 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
}
}
- dat_status = DAT_NOT_IMPLEMENTED;
-
- /*
- * XXX The rest of the EP code is useful in this case too,
- * XXX but need to complete the SRQ implementation before
- * XXX committing resources
- */
- *ep_handle = ep_ptr = NULL;
- goto bail;
-#ifdef notdef
-
/* Allocate EP */
- ep_ptr = dapl_ep_alloc(ia_ptr, ep_attr);
+ ep_ptr = dapl_ep_alloc(ia_ptr, ep_attr, DAT_TRUE);
if (ep_ptr == NULL) {
dat_status =
DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
+ dapl_os_atomic_dec(&((DAPL_SRQ *) srq_handle)->srq_ref_count);
goto bail;
}
@@ -279,6 +285,7 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
ep_ptr->param.recv_evd_handle = recv_evd_handle;
ep_ptr->param.request_evd_handle = request_evd_handle;
ep_ptr->param.connect_evd_handle = connect_evd_handle;
+ ep_ptr->param.srq_handle = srq_handle;
/*
* Make sure we handle the NULL DTO EVDs
@@ -309,6 +316,8 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
if (dat_status != DAT_SUCCESS) {
dapl_os_atomic_dec(&((DAPL_PZ *) pz_handle)->
pz_ref_count);
+ dapl_os_atomic_dec(&((DAPL_SRQ *) srq_handle)->
+ srq_ref_count);
dapl_ep_dealloc(ep_ptr);
goto bail;
}
@@ -340,8 +349,6 @@ dapl_ep_create_with_srq(IN DAT_IA_HANDLE ia_handle,
*ep_handle = ep_ptr;
-#endif /* notdef */
-
bail:
return dat_status;
}
diff --git a/dapl/common/dapl_ep_free.c b/dapl/common/dapl_ep_free.c
index 178cae6..62d7eff 100644
--- a/dapl/common/dapl_ep_free.c
+++ b/dapl/common/dapl_ep_free.c
@@ -162,6 +162,11 @@ DAT_RETURN DAT_API dapl_ep_free(IN DAT_EP_HANDLE ep_handle)
evd_ref_count);
param->connect_evd_handle = NULL;
}
+ if (param->srq_handle != NULL) {
+ dapl_os_atomic_dec(&((DAPL_SRQ *) param->srq_handle)->
+ srq_ref_count);
+ param->srq_handle = NULL;
+ }
/*
* Finish tearing everything down.
diff --git a/dapl/common/dapl_ep_post_recv.c b/dapl/common/dapl_ep_post_recv.c
index fe3a605..0ed0181 100644
--- a/dapl/common/dapl_ep_post_recv.c
+++ b/dapl/common/dapl_ep_post_recv.c
@@ -90,6 +90,11 @@ dapl_ep_post_recv(IN DAT_EP_HANDLE ep_handle,
}
ep_ptr = (DAPL_EP *) ep_handle;
+ if (ep_ptr->param.srq_handle) {
+ dat_status =
+ DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_SRQ_IN_USE);
+ goto bail;
+ }
/*
* Synchronization ok since this buffer is only used for receive
diff --git a/dapl/common/dapl_ep_util.c b/dapl/common/dapl_ep_util.c
index 8ceb1be..42488d8 100644
--- a/dapl/common/dapl_ep_util.c
+++ b/dapl/common/dapl_ep_util.c
@@ -104,7 +104,8 @@ char *dapl_get_ep_state_str(DAT_EP_STATE state)
* none
*
*/
-DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)
+DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr,
+ IN DAT_BOOLEAN using_srq)
{
DAPL_EP *ep_ptr;
@@ -172,13 +173,16 @@ DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)
goto bail;
}
- if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->recv_buffer,
- ep_ptr,
- ep_ptr->param.ep_attr.max_recv_dtos))
- {
- dapl_ep_dealloc(ep_ptr);
- ep_ptr = NULL;
- goto bail;
+ /* SRQ case - don't allocate as we use the SRQ recv buffer */
+ if (using_srq == DAT_FALSE) {
+ if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->recv_buffer,
+ ep_ptr,
+ ep_ptr->param.ep_attr.max_recv_dtos))
+ {
+ dapl_ep_dealloc(ep_ptr);
+ ep_ptr = NULL;
+ goto bail;
+ }
}
dapls_io_trc_alloc(ep_ptr);
@@ -209,7 +213,8 @@ void dapl_ep_dealloc(IN DAPL_EP * ep_ptr)
ep_ptr->header.magic = DAPL_MAGIC_INVALID; /* reset magic to prevent reuse */
dapls_cb_free(&ep_ptr->req_buffer);
- dapls_cb_free(&ep_ptr->recv_buffer);
+ if (ep_ptr->recv_buffer.pool)
+ dapls_cb_free(&ep_ptr->recv_buffer);
if (NULL != ep_ptr->cxn_timer) {
dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));
@@ -627,8 +632,10 @@ void dapls_ep_flush_cqs(DAPL_EP * ep_ptr)
if (ep_ptr->param.request_evd_handle)
dapli_ep_flush_evd((DAPL_EVD *) ep_ptr->param.request_evd_handle);
if (ep_ptr->param.recv_evd_handle)
- while (dapls_cb_pending(&ep_ptr->recv_buffer))
- dapli_ep_flush_evd((DAPL_EVD *) ep_ptr->param.recv_evd_handle);
+ if (ep_ptr->recv_buffer.pool)
+ while (dapls_cb_pending(&ep_ptr->recv_buffer))
+ dapli_ep_flush_evd((DAPL_EVD *) ep_ptr->param.
+ recv_evd_handle);
}
/*
diff --git a/dapl/common/dapl_ep_util.h b/dapl/common/dapl_ep_util.h
index 37805d4..5cf6080 100644
--- a/dapl/common/dapl_ep_util.h
+++ b/dapl/common/dapl_ep_util.h
@@ -46,7 +46,8 @@
extern DAPL_EP *
dapl_ep_alloc (
IN DAPL_IA *ia,
- IN const DAT_EP_ATTR *ep_attr );
+ IN const DAT_EP_ATTR *ep_attr,
+ IN DAT_BOOLEAN using_srq );
extern void
dapl_ep_dealloc (
diff --git a/dapl/common/dapl_evd_qp_async_error_callb.c b/dapl/common/dapl_evd_qp_async_error_callb.c
index 6ea9edb..90767f5 100644
--- a/dapl/common/dapl_evd_qp_async_error_callb.c
+++ b/dapl/common/dapl_evd_qp_async_error_callb.c
@@ -67,10 +67,10 @@ dapl_evd_qp_async_error_callback(IN ib_hca_handle_t ib_hca_handle,
DAT_RETURN dat_status;
#ifdef _VENDOR_IBAL_
- dapl_dbg_log(DAPL_DBG_TYPE_ERR, "%s() IB err %s\n",
+ dapl_dbg_log(DAPL_DBG_TYPE_EXCEPTION, "%s() IB err %s\n",
__FUNCTION__, ib_get_async_event_str(cause_ptr->code));
#else
- dapl_dbg_log(DAPL_DBG_TYPE_ERR, "%s() IB async QP err - ctx=%p\n",
+ dapl_dbg_log(DAPL_DBG_TYPE_EXCEPTION, "%s() IB async QP err - ctx=%p\n",
__FUNCTION__, context);
#endif
@@ -85,16 +85,21 @@ dapl_evd_qp_async_error_callback(IN ib_hca_handle_t ib_hca_handle,
async_evd = (DAPL_EVD *) ia_ptr->async_error_evd;
DAPL_CNTR(ia_ptr, DCNT_IA_ASYNC_QP_ERROR);
- dapl_log(DAPL_DBG_TYPE_WARN, " -- %s: ep %p qp %p (%x) state %d\n",
+ dapl_log(DAPL_DBG_TYPE_EXCEPTION, " -- %s: ep %p qp %p (%x) state %d\n",
__FUNCTION__, ep_ptr, ep_ptr->qp_handle,
ep_ptr->qpn, ep_ptr->param.ep_state);
/*
* Transition to ERROR if we are connected; other states need to
- * complete first (e.g. pending states)
+ * complete first (e.g. pending states) unless it's SRQ LAST_WQE_REACHED
+ * which is a regular async event in case of disconnect.
*/
if (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED) {
- ep_ptr->param.ep_state = DAT_EP_STATE_ERROR;
+ if (!ep_ptr->param.srq_handle || cause_ptr->event_type != IBV_EVENT_QP_LAST_WQE_REACHED) {
+ dapl_os_lock(&ep_ptr->header.lock);
+ ep_ptr->param.ep_state = DAT_EP_STATE_ERROR;
+ dapl_os_unlock(&ep_ptr->header.lock);
+ }
}
dapl_os_assert(async_evd != NULL);
diff --git a/dapl/common/dapl_evd_util.c b/dapl/common/dapl_evd_util.c
index 6b9d1f7..85d8f64 100644
--- a/dapl/common/dapl_evd_util.c
+++ b/dapl/common/dapl_evd_util.c
@@ -738,8 +738,8 @@ dapls_evd_post_async_error_event(IN DAPL_EVD * evd_ptr,
{
DAT_EVENT *event_ptr;
- dapl_log(DAPL_DBG_TYPE_WARN,
- " WARNING: async event - %s evd=%p\n",
+ dapl_log(DAPL_DBG_TYPE_EXCEPTION,
+ " async event - %s evd=%p\n",
dapl_event_str(event_number), evd_ptr);
dapl_os_lock(&evd_ptr->header.lock);
@@ -975,7 +975,7 @@ dapls_evd_post_cr_event_ext(IN DAPL_SP * sp_ptr,
* requestor that we cant help them.
*/
ia_ptr = sp_ptr->header.owner_ia;
- ep_ptr = dapl_ep_alloc(ia_ptr, NULL);
+ ep_ptr = dapl_ep_alloc(ia_ptr, NULL, DAT_FALSE);
if (ep_ptr == NULL) {
dapls_cr_free(cr_ptr);
goto bail;
@@ -1086,6 +1086,7 @@ dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
DAPL_COOKIE *cookie;
DAT_DTO_COMPLETION_STATUS dto_status;
DAPL_COOKIE_BUFFER *buffer;
+ DAPL_SRQ *srq_ptr = NULL;
/*
* All that can be relied on if the status is bad is the status
@@ -1096,6 +1097,7 @@ dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
cookie = (DAPL_COOKIE *) (uintptr_t) DAPL_GET_CQE_WRID(cqe_ptr);
dapl_os_assert((NULL != cookie));
+ /* In case of RECV SRQ DTO cookie->ep holds pointer to the SRQ */
ep_ptr = cookie->ep;
dapl_os_assert((NULL != ep_ptr));
@@ -1125,8 +1127,13 @@ dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
break;
}
#endif
-
- if (DAPL_DTO_TYPE_RECV == cookie->val.dto.type)
+ if (DAPL_DTO_TYPE_RECV_SRQ == cookie->val.dto.type) {
+ /* in SRQ event we do NOT have ep pointer */
+ srq_ptr = (DAPL_SRQ *)ep_ptr;
+ buffer = &srq_ptr->recv_buffer;
+ ep_ptr = NULL;
+ }
+ else if (DAPL_DTO_TYPE_RECV == cookie->val.dto.type)
buffer = &ep_ptr->recv_buffer;
else
buffer = &ep_ptr->req_buffer;
@@ -1151,6 +1158,8 @@ dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
}
dapls_cookie_dealloc(buffer, cookie);
+ if (srq_ptr)
+ dapl_os_atomic_dec(&srq_ptr->recv_count);
break;
}
@@ -1198,6 +1207,36 @@ dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
(dto_status != DAT_DTO_ERR_FLUSHED)) {
DAPL_EVD *evd_ptr;
+ /* In SRQ case we need to look up the EP */
+ if (ep_ptr == NULL) {
+ DAT_UINT32 qp_num = DAPL_GET_CQE_QP_NUM(cqe_ptr);
+ DAPL_IA *ia_ptr = (DAPL_IA *)srq_ptr->param.ia_handle;
+
+ dapl_os_lock(&ia_ptr->header.lock);
+ ep_ptr = (dapl_llist_is_empty(&ia_ptr->ep_list_head)
+ ? NULL :
+ dapl_llist_peek_head(&ia_ptr->ep_list_head));
+
+ while (ep_ptr != NULL) {
+ if (ep_ptr->qp_handle->qp->qp_num == qp_num)
+ break;
+
+ ep_ptr =
+ dapl_llist_next_entry(&ia_ptr->ep_list_head,
+ &ep_ptr->header.
+ ia_list_entry);
+ }
+ dapl_os_unlock(&ia_ptr->header.lock);
+
+ if (ep_ptr == NULL ) {
+ dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,
+ " SRQ %p at ia %p - "
+ "EP with qpn %d was not found\n",
+ srq_ptr, ia_ptr, qp_num);
+ return;
+ }
+ }
+
/*
* If we are connected, generate disconnect and generate an
* event. We may be racing with other disconnect ops, so we
diff --git a/dapl/common/dapl_srq_create.c b/dapl/common/dapl_srq_create.c
index 77aeacd..43d1637 100644
--- a/dapl/common/dapl_srq_create.c
+++ b/dapl/common/dapl_srq_create.c
@@ -93,13 +93,7 @@ dapl_srq_create(IN DAT_IA_HANDLE ia_handle,
DAPL_CNTR(ia_ptr, DCNT_IA_SRQ_CREATE);
- /*
- * Verify non-required parameters.
- * N.B. Assumption: any parameter that can be
- * modified by dat_ep_modify() is not strictly
- * required when the EP is created
- */
- if (pz_handle != NULL && DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) {
+ if (DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) {
dat_status =
DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_PZ);
goto bail;
@@ -114,10 +108,6 @@ dapl_srq_create(IN DAT_IA_HANDLE ia_handle,
goto bail;
}
- /* SRQ provider not implemented */
- dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
- goto bail;
-
/* Allocate SRQ */
srq_ptr = dapl_srq_alloc(ia_ptr, srq_attr);
if (srq_ptr == NULL) {
@@ -127,18 +117,25 @@ dapl_srq_create(IN DAT_IA_HANDLE ia_handle,
}
srq_ptr->param.ia_handle = (DAT_IA_HANDLE) ia_ptr;
- srq_ptr->param.srq_state = DAT_SRQ_STATE_OPERATIONAL;
srq_ptr->param.pz_handle = pz_handle;
/*
- * XXX Allocate provider resource here!!!
+ * Get a SRQ from the IB provider
*/
+ dat_status = dapls_ib_srq_alloc(srq_ptr);
+ if (dat_status != DAT_SUCCESS) {
+ dapl_srq_dealloc(srq_ptr);
+ goto bail;
+ }
/* Link it onto the IA */
dapl_ia_link_srq(ia_ptr, srq_ptr);
*srq_handle = srq_ptr;
+ /* Ready */
+ srq_ptr->param.srq_state = DAT_SRQ_STATE_OPERATIONAL;
+
bail:
return dat_status;
}
diff --git a/dapl/common/dapl_srq_free.c b/dapl/common/dapl_srq_free.c
index d93e188..dcb1278 100644
--- a/dapl/common/dapl_srq_free.c
+++ b/dapl/common/dapl_srq_free.c
@@ -72,6 +72,16 @@ DAT_RETURN DAT_API dapl_srq_free(IN DAT_SRQ_HANDLE srq_handle)
srq_ptr = (DAPL_SRQ *) srq_handle;
param = &srq_ptr->param;
+ ia_ptr = srq_ptr->header.owner_ia;
+
+ /*
+ * Verify parameters
+ */
+ if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {
+ dat_status =
+ DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA);
+ goto bail;
+ }
/*
* Verify parameter & state
@@ -82,6 +92,7 @@ DAT_RETURN DAT_API dapl_srq_free(IN DAT_SRQ_HANDLE srq_handle)
goto bail;
}
+ dapl_os_lock(&ia_ptr->header.lock);
if (dapl_os_atomic_read(&srq_ptr->srq_ref_count) != 0) {
/*
* The DAPL 1.2 spec says to return DAT_SRQ_IN_USE, which does
@@ -89,32 +100,17 @@ DAT_RETURN DAT_API dapl_srq_free(IN DAT_SRQ_HANDLE srq_handle)
*/
dat_status =
DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_SRQ_IN_USE);
+ dapl_os_unlock(&ia_ptr->header.lock);
goto bail;
}
-
- ia_ptr = srq_ptr->header.owner_ia;
+ param->srq_state = DAT_SRQ_STATE_SHUTDOWN;
+ dapl_os_unlock(&ia_ptr->header.lock);
DAPL_CNTR(ia_ptr, DCNT_IA_SRQ_FREE);
- /*
- * Do verification of parameters and the state change atomically.
- */
- dapl_os_lock(&srq_ptr->header.lock);
-
- /* Remove the SRQ from the IA */
- dapl_ia_unlink_srq(ia_ptr, srq_ptr);
-
- dapl_os_unlock(&srq_ptr->header.lock);
-
- /*
- * Finish tearing everything down.
- */
-
- /*
- * Take care of the transport resource
- */
+ dapl_ia_unlink_srq(srq_ptr->header.owner_ia, srq_ptr);
- /* XXX Put provider code here!!! */
+ dapls_ib_srq_free(srq_ptr);
/* Free the resource */
dapl_srq_dealloc(srq_ptr);
diff --git a/dapl/common/dapl_srq_post_recv.c b/dapl/common/dapl_srq_post_recv.c
index d46f9bd..fbe714c 100644
--- a/dapl/common/dapl_srq_post_recv.c
+++ b/dapl/common/dapl_srq_post_recv.c
@@ -95,7 +95,7 @@ dapl_srq_post_recv(IN DAT_SRQ_HANDLE srq_handle,
* app must syncronize access to the SRQ.
*/
dat_status = dapls_dto_cookie_alloc(&srq_ptr->recv_buffer,
- DAPL_DTO_TYPE_RECV,
+ DAPL_DTO_TYPE_RECV_SRQ,
user_cookie, &cookie);
if (DAT_SUCCESS != dat_status) {
goto bail;
@@ -110,8 +110,8 @@ dapl_srq_post_recv(IN DAT_SRQ_HANDLE srq_handle,
/*
* Invoke provider specific routine to post DTO
*/
- /* XXX Put code here XXX */
- /* XXX */ dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
+ dat_status = dapls_ib_post_srq_recv(srq_ptr, cookie,
+ num_segments, local_iov);
if (dat_status != DAT_SUCCESS) {
dapl_os_atomic_dec(&srq_ptr->recv_count);
diff --git a/dapl/common/dapl_srq_query.c b/dapl/common/dapl_srq_query.c
index f9ad443..6761095 100644
--- a/dapl/common/dapl_srq_query.c
+++ b/dapl/common/dapl_srq_query.c
@@ -84,11 +84,9 @@ dapl_srq_query(IN DAT_SRQ_HANDLE srq_handle,
srq_ptr = (DAPL_SRQ *) srq_handle;
- /*
- * XXX Need to calculate available_dto_count and outstanding_dto_count
- */
srq_ptr->param.available_dto_count = DAT_VALUE_UNKNOWN;
- srq_ptr->param.outstanding_dto_count = DAT_VALUE_UNKNOWN;
+ srq_ptr->param.outstanding_dto_count =
+ dapl_os_atomic_read(&srq_ptr->recv_count);
*srq_param = srq_ptr->param;
dats_get_ia_handle(srq_ptr->header.owner_ia, &srq_param->ia_handle);
diff --git a/dapl/common/dapl_srq_resize.c b/dapl/common/dapl_srq_resize.c
index 32386ff..aadc35e 100644
--- a/dapl/common/dapl_srq_resize.c
+++ b/dapl/common/dapl_srq_resize.c
@@ -66,7 +66,6 @@
DAT_RETURN DAT_API
dapl_srq_resize(IN DAT_SRQ_HANDLE srq_handle, IN DAT_COUNT srq_max_recv_dto)
{
- DAPL_IA *ia_ptr;
DAPL_SRQ *srq_ptr;
DAT_RETURN dat_status;
@@ -82,19 +81,17 @@ dapl_srq_resize(IN DAT_SRQ_HANDLE srq_handle, IN DAT_COUNT srq_max_recv_dto)
}
srq_ptr = (DAPL_SRQ *) srq_handle;
- ia_ptr = srq_ptr->header.owner_ia;
/*
* Check for nonsense requests per the spec
*/
- if (srq_max_recv_dto <= srq_ptr->param.low_watermark) {
+ if (srq_max_recv_dto <= srq_ptr->param.low_watermark ||
+ srq_max_recv_dto < dapl_os_atomic_read(&srq_ptr->recv_count)) {
dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_NO_SUBTYPE);
goto bail;
}
- /* XXX Put implementation here XXX */
-
- /* XXX */ dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
+ dat_status = dapls_ib_srq_resize(srq_ptr, (uint32_t)srq_max_recv_dto);
bail:
return dat_status;
diff --git a/dapl/common/dapl_srq_set_lw.c b/dapl/common/dapl_srq_set_lw.c
index 1e4254f..8202e4f 100644
--- a/dapl/common/dapl_srq_set_lw.c
+++ b/dapl/common/dapl_srq_set_lw.c
@@ -82,9 +82,7 @@ dapl_srq_set_lw(IN DAT_SRQ_HANDLE srq_handle, IN DAT_COUNT low_watermark)
srq_ptr = (DAPL_SRQ *) srq_handle;
- /* XXX Put implementation here XXX */
-
- /* XXX */ dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
+ dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
bail:
return dat_status;
diff --git a/dapl/common/dapl_srq_util.c b/dapl/common/dapl_srq_util.c
index 3b29890..4cf30ef 100644
--- a/dapl/common/dapl_srq_util.c
+++ b/dapl/common/dapl_srq_util.c
@@ -84,7 +84,6 @@ DAPL_SRQ *dapl_srq_alloc(IN DAPL_IA * ia_ptr, IN const DAT_SRQ_ATTR * srq_attr)
/*
* Initialize the body.
- * XXX Assume srq_attrs is required
*/
srq_ptr->param.max_recv_dtos = srq_attr->max_recv_dtos;
srq_ptr->param.max_recv_iov = srq_attr->max_recv_iov;
@@ -122,7 +121,6 @@ void dapl_srq_dealloc(IN DAPL_SRQ * srq_ptr)
dapl_os_assert(srq_ptr->header.magic == DAPL_MAGIC_SRQ);
srq_ptr->header.magic = DAPL_MAGIC_INVALID; /* reset magic to prevent reuse */
- dapl_ia_unlink_srq(srq_ptr->header.owner_ia, srq_ptr);
dapls_cb_free(&srq_ptr->recv_buffer);
dapl_os_lock_destroy(&srq_ptr->header.lock);
diff --git a/dapl/include/dapl.h b/dapl/include/dapl.h
index df4b099..60de914 100755
--- a/dapl/include/dapl.h
+++ b/dapl/include/dapl.h
@@ -479,6 +479,7 @@ struct dapl_srq
DAPL_ATOMIC srq_ref_count;
DAPL_COOKIE_BUFFER recv_buffer;
DAPL_ATOMIC recv_count;
+ ib_srq_handle_t srq_handle;
};
/* DAPL_PZ maps to DAT_PZ_HANDLE */
@@ -580,6 +581,7 @@ typedef enum dapl_dto_type
{
DAPL_DTO_TYPE_SEND,
DAPL_DTO_TYPE_RECV,
+ DAPL_DTO_TYPE_RECV_SRQ,
DAPL_DTO_TYPE_RDMA_WRITE,
DAPL_DTO_TYPE_RDMA_READ,
#ifdef DAT_EXTENSIONS
diff --git a/dapl/openib_common/cq.c b/dapl/openib_common/cq.c
index 254f907..feffded 100644
--- a/dapl/openib_common/cq.c
+++ b/dapl/openib_common/cq.c
@@ -114,7 +114,8 @@ DAT_RETURN dapls_ib_get_async_event(IN ib_error_record_t * err_record,
DAT_RETURN dat_status = DAT_SUCCESS;
int err_code = err_record->event_type;
- dapl_log(DAPL_DBG_TYPE_WARN, " WARNING: %s\n", dapl_ib_async_str(err_code));
+ dapl_log(DAPL_DBG_TYPE_EXCEPTION, " %s %s\n", __FUNCTION__,
+ dapl_ib_async_str(err_code));
switch (err_code)
{
diff --git a/dapl/openib_common/dapl_ib_common.h b/dapl/openib_common/dapl_ib_common.h
index 42391b2..453f437 100644
--- a/dapl/openib_common/dapl_ib_common.h
+++ b/dapl/openib_common/dapl_ib_common.h
@@ -90,6 +90,7 @@ typedef struct ibv_mw *ib_mw_handle_t;
typedef struct ibv_wc ib_work_completion_t;
typedef struct ibv_ah *ib_ah_handle_t;
typedef union ibv_gid *ib_gid_handle_t;
+typedef struct ibv_srq *ib_srq_handle_t;
/* HCA context type maps to IB verbs */
typedef struct ibv_context *ib_hca_handle_t;
diff --git a/dapl/openib_common/dapl_ib_dto.h b/dapl/openib_common/dapl_ib_dto.h
index e9f6cfb..8801db4 100644
--- a/dapl/openib_common/dapl_ib_dto.h
+++ b/dapl/openib_common/dapl_ib_dto.h
@@ -112,6 +112,53 @@ dapls_ib_post_recv (
}
/*
+ * dapls_ib_post_srq_recv
+ *
+ * Provider specific Post SRQ RECV function
+ */
+STATIC _INLINE_ DAT_RETURN
+dapls_ib_post_srq_recv (
+ IN DAPL_SRQ *srq_ptr,
+ IN DAPL_COOKIE *cookie,
+ IN DAT_COUNT segments,
+ IN DAT_LMR_TRIPLET *local_iov )
+{
+ struct ibv_recv_wr wr;
+ struct ibv_recv_wr *bad_wr;
+ ib_data_segment_t *ds = (ib_data_segment_t *)local_iov;
+ DAT_COUNT i, total_len;
+ int ret;
+
+ dapl_dbg_log(DAPL_DBG_TYPE_SRQ,
+ " post_srq_rcv: srq %p cookie %p segs %d l_iov %p\n",
+ srq_ptr, cookie, segments, local_iov);
+
+ /* setup work request */
+ total_len = 0;
+ wr.next = 0;
+ wr.num_sge = segments;
+ wr.wr_id = (uint64_t)(uintptr_t)cookie;
+ wr.sg_list = ds;
+
+ if (cookie != NULL) {
+ for (i = 0; i < segments; i++) {
+ dapl_dbg_log(DAPL_DBG_TYPE_SRQ,
+ " post_srq_rcv: l_key 0x%x va %p len %d\n",
+ ds->lkey, ds->addr, ds->length );
+ total_len += ds->length;
+ ds++;
+ }
+ cookie->val.dto.size = total_len;
+ }
+
+ ret = ibv_post_srq_recv(srq_ptr->srq_handle, &wr, &bad_wr);
+ if (ret)
+ return(dapl_convert_errno(errno,"ibv_recv"));
+
+ return DAT_SUCCESS;
+}
+
+/*
* dapls_ib_post_send
*
* Provider specific Post SEND function
@@ -504,6 +551,7 @@ STATIC _INLINE_ int dapls_cqe_opcode(ib_work_completion_t *cqe_p)
#define DAPL_GET_CQE_OPTYPE(cqe_p) dapls_cqe_opcode(cqe_p)
#define DAPL_GET_CQE_WRID(cqe_p) ((ib_work_completion_t*)cqe_p)->wr_id
+#define DAPL_GET_CQE_QP_NUM(cqe_p) ((ib_work_completion_t*)cqe_p)->qp_num
#define DAPL_GET_CQE_STATUS(cqe_p) ((ib_work_completion_t*)cqe_p)->status
#define DAPL_GET_CQE_VENDOR_ERR(cqe_p) ((ib_work_completion_t*)cqe_p)->vendor_err
#define DAPL_GET_CQE_BYTESNUM(cqe_p) ((ib_work_completion_t*)cqe_p)->byte_len
diff --git a/dapl/openib_common/qp.c b/dapl/openib_common/qp.c
index 24a2790..16dd5f0 100644
--- a/dapl/openib_common/qp.c
+++ b/dapl/openib_common/qp.c
@@ -61,8 +61,10 @@ dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,
{
DAT_EP_ATTR *attr;
DAPL_EVD *rcv_evd, *req_evd;
+ DAPL_SRQ *dapl_srq = (DAPL_SRQ *)ep_ptr->param.srq_handle;
ib_cq_handle_t rcv_cq, req_cq;
ib_pd_handle_t ib_pd_handle;
+ ib_srq_handle_t ib_srq_handle = NULL;
int ret = EINVAL;
int max_inline = ia_ptr->hca_ptr->ib_trans.max_inline_send;
struct ibv_qp_init_attr qp_create;
@@ -72,6 +74,8 @@ dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,
attr = &ep_ptr->param.ep_attr;
ib_pd_handle = ((DAPL_PZ *) ep_ptr->param.pz_handle)->pd_handle;
+ if (dapl_srq)
+ ib_srq_handle = dapl_srq->srq_handle;
rcv_evd = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;
req_evd = (DAPL_EVD *) ep_ptr->param.request_evd_handle;
@@ -167,6 +171,7 @@ dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,
qp_create.cap.max_inline_data = max_inline;
qp_create.qp_type = IBV_QPT_RC;
qp_create.qp_context = (void *)ep_ptr;
+ qp_create.srq = ib_srq_handle;
#ifdef DAT_EXTENSIONS
if ((int)attr->service_type == (int)DAT_IB_SERVICE_TYPE_UD) {
diff --git a/dapl/openib_common/srq.c b/dapl/openib_common/srq.c
new file mode 100644
index 0000000..3b6a38b
--- /dev/null
+++ b/dapl/openib_common/srq.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2009-2014 Intel Corporation. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ * available from the Open Source Initiative, see
+ * http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ * available from the Open Source Initiative, see
+ * http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ * copy of which is available from the Open Source Initiative, see
+ * http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_ep_util.h"
+
+/*
+ * dapl_ib_srq_alloc
+ *
+ * Alloc a SRQ
+ *
+ * Input:
+ * ia_handle SRQ handle
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INSUFFICIENT_RESOURCES
+ *
+ */
+DAT_RETURN
+dapls_ib_srq_alloc(IN DAPL_SRQ *srq_ptr)
+{
+ struct ibv_srq_init_attr srq_init_attr;
+ ib_pd_handle_t ib_pd_handle;
+
+ dapl_dbg_log(DAPL_DBG_TYPE_SRQ,
+ " srq alloc: srq %p\n", srq_ptr);
+
+ ib_pd_handle = ((DAPL_PZ *) srq_ptr->param.pz_handle)->pd_handle;
+ srq_init_attr.srq_context = NULL;
+ srq_init_attr.attr.max_wr = srq_ptr->param.max_recv_dtos;
+ srq_init_attr.attr.max_sge = srq_ptr->param.max_recv_iov;
+ srq_init_attr.attr.srq_limit = 0;
+
+ srq_ptr->srq_handle = ibv_create_srq(ib_pd_handle, &srq_init_attr);
+ if (!srq_ptr->srq_handle)
+ goto err;
+
+ return DAT_SUCCESS;
+
+err:
+ dapl_log(DAPL_DBG_TYPE_ERR, "ib_srq_alloc ERR %s\n", strerror(errno));
+
+ return dapl_convert_errno(ENOMEM, "srq_allocate" );
+}
+
+/*
+ * dapl_ib_srq_free
+ *
+ * Free a SRQ
+ *
+ * Input:
+ * ia_handle SRQ handle
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INVALID_PARAMETER
+ * dapl_convert_errno
+ */
+DAT_RETURN
+dapls_ib_srq_free(IN DAPL_SRQ *srq_ptr)
+{
+
+ dapl_dbg_log(DAPL_DBG_TYPE_SRQ, " srq free: srq %p\n", srq_ptr);
+
+ if (srq_ptr->srq_handle == IB_INVALID_HANDLE)
+ return DAT_INVALID_PARAMETER;
+
+ if (ibv_destroy_srq(srq_ptr->srq_handle)) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " srq_free: ibv_destroy_srq error - %s\n",
+ strerror(errno));
+ return (dapl_convert_errno(errno, "srq_free"));
+ }
+
+ return DAT_SUCCESS;
+}
+
+/*
+ * dapl_ib_srq_resize
+ *
+ *Resize a SRQ
+ *
+ * Input:
+ * SRQ handle
+ * New size
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INSUFFICIENT_RESOURCES
+ *
+ */
+DAT_RETURN
+dapls_ib_srq_resize(IN DAPL_SRQ *srq_ptr, IN uint32_t new_max_wr)
+{
+ struct ibv_srq_attr srq_attr;
+
+ dapl_dbg_log(DAPL_DBG_TYPE_SRQ, " srq resize: srq %p\n", srq_ptr);
+
+ srq_attr.max_wr = new_max_wr;
+
+ if (ibv_modify_srq(srq_ptr->srq_handle, &srq_attr, IBV_SRQ_MAX_WR)) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " srq_resize: ibv_modify_srq error - %s\n",
+ strerror(errno));
+ return (dapl_convert_errno(errno, "srq_resize"));
+ }
+
+ return DAT_SUCCESS;
+}
diff --git a/dapl/openib_common/util.c b/dapl/openib_common/util.c
index b924b64..ad59f8f 100644
--- a/dapl/openib_common/util.c
+++ b/dapl/openib_common/util.c
@@ -638,11 +638,16 @@ void dapli_async_event_cb(struct _ib_hca_transport *hca)
case IBV_EVENT_SRQ_LIMIT_REACHED:
case IBV_EVENT_SQ_DRAINED:
{
+ DAPL_DBG_TYPE dbg_type = DAPL_DBG_TYPE_ERR;
struct dapl_ep *ep_ptr =
event.element.qp->qp_context;
- dapl_log(DAPL_DBG_TYPE_ERR,
- "dapl async_event QP (%p) ERR %d\n",
+ if (event.event_type == IBV_EVENT_QP_LAST_WQE_REACHED &&
+ ep_ptr->param.srq_handle) {
+ dbg_type = DAPL_DBG_TYPE_EVD;
+ }
+
+ dapl_log(dbg_type, "dapl async_event QP (%p) Event %d\n",
ep_ptr, event.event_type);
/* report up if async callback still setup */
diff --git a/dat/include/dat2/dat.h b/dat/include/dat2/dat.h
index 261c56a..b74b778 100755
--- a/dat/include/dat2/dat.h
+++ b/dat/include/dat2/dat.h
@@ -577,8 +577,9 @@ typedef DAT_UINT64 DAT_EP_PARAM_MASK;
typedef enum dat_srq_state
{
+ DAT_SRQ_STATE_ERROR,
DAT_SRQ_STATE_OPERATIONAL,
- DAT_SRQ_STATE_ERROR
+ DAT_SRQ_STATE_SHUTDOWN
} DAT_SRQ_STATE;
#define DAT_VALUE_UNKNOWN (((DAT_COUNT) ~0)-1)
diff --git a/dat/include/dat2/dat_error.h b/dat/include/dat2/dat_error.h
index 251e6c4..48e0a0e 100644
--- a/dat/include/dat2/dat_error.h
+++ b/dat/include/dat2/dat_error.h
@@ -319,6 +319,7 @@ typedef enum dat_return_subtype
DAT_INVALID_STATE_SRQ_OPERATIONAL,
DAT_INVALID_STATE_SRQ_ERROR,
DAT_INVALID_STATE_SRQ_IN_USE,
+ DAT_INVALID_STATE_SRQ_SHUTDOWN,
/* DAT_LENGTH_ERROR has no subtypes */
diff --git a/test/dtest/Makefile.am b/test/dtest/Makefile.am
index 801d704..b5f7574 100755
--- a/test/dtest/Makefile.am
+++ b/test/dtest/Makefile.am
@@ -1,10 +1,13 @@
-bin_PROGRAMS = dtest dtestcm
+bin_PROGRAMS = dtest dtestcm dtestsrq
dtest_SOURCES = dtest.c
dtest_CFLAGS = -g -Wall -D_GNU_SOURCE
dtestcm_SOURCES = dtestcm.c
dtestcm_CFLAGS = -g -Wall -D_GNU_SOURCE
+dtestsrq_SOURCES = dtestsrq.c
+dtestsrq_CFLAGS = -g -Wall -D_GNU_SOURCE
+
if EXT_TYPE_IB
bin_PROGRAMS += dtestx
dtestx_SOURCES = dtestx.c
@@ -15,4 +18,5 @@ endif
INCLUDES = -I $(srcdir)/../../dat/include
dtest_LDADD = $(top_builddir)/dat/udat/libdat2.la
dtestcm_LDADD = $(top_builddir)/dat/udat/libdat2.la
+dtestsrq_LDADD = $(top_builddir)/dat/udat/libdat2.la
--
1.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] dtest: add dtestsrq for SRQ example and provider testing
[not found] ` <1418668558-695-1-git-send-email-arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-12-15 18:35 ` [PATCH 1/3] common: add srq support for openib verbs providers arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
@ 2014-12-15 18:35 ` arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 3/3] dtestx: update IB extension example test with new v2.0.9 features arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2 siblings, 0 replies; 4+ messages in thread
From: arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w @ 2014-12-15 18:35 UTC (permalink / raw)
To: linux-rdma-u79uwXL29TY76Z2rM5mHXA; +Cc: Amir Hanania, Arlin Davis
From: Amir Hanania <amir.hanania-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Arlin Davis <arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
test/dtest/dtestsrq.c | 1605 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1605 insertions(+), 0 deletions(-)
create mode 100644 test/dtest/dtestsrq.c
diff --git a/test/dtest/dtestsrq.c b/test/dtest/dtestsrq.c
new file mode 100644
index 0000000..2bc2596
--- /dev/null
+++ b/test/dtest/dtestsrq.c
@@ -0,0 +1,1605 @@
+/*
+ * Copyright (c) 2009 Intel Corporation. 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
+ * OpenIB.org 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: $
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DAPL_PROVIDER
+#undef DAPL_PROVIDER
+#endif
+
+#if defined(_WIN32) || defined(_WIN64)
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <process.h>
+#include <complib/cl_types.h>
+#include "..\..\..\..\etc\user\getopt.c"
+
+#define getpid() ((int)GetCurrentProcessId())
+#define F64x "%I64x"
+#define F64d "%I64d"
+
+#ifdef DBG
+#define DAPL_PROVIDER "ibnic0v2d"
+#else
+#define DAPL_PROVIDER "ibnic0v2"
+#endif
+
+#define ntohll _byteswap_uint64
+#define htonll _byteswap_uint64
+
+#else // _WIN32 || _WIN64
+
+#include <endian.h>
+#include <byteswap.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/mman.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define DAPL_PROVIDER "ofa-v2-ib0"
+
+#define F64x "%"PRIx64""
+#define F64d "%"PRId64""
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define htonll(x) (x)
+#define ntohll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define htonll(x) bswap_64(x)
+#define ntohll(x) bswap_64(x)
+#endif
+
+#endif // _WIN32 || _WIN64
+
+/* Header files needed for DAT/uDAPL */
+#include "dat2/udat.h"
+#include "dat2/dat_ib_extensions.h"
+
+/* definitions */
+#define SERVER_CONN_QUAL 45248
+#define CONN_TIMEOUT (1000*1000*100)
+#define DTO_TIMEOUT (1000*1000*5)
+#define CR_TIMEOUT DAT_TIMEOUT_INFINITE
+#define MAX_CONN 100
+#define MAX_BURST 100
+#define MSG_IOV_COUNT 1
+
+/* Global DAT vars */
+static DAT_IA_HANDLE h_ia = DAT_HANDLE_NULL;
+static DAT_PZ_HANDLE h_pz = DAT_HANDLE_NULL;
+static DAT_SRQ_HANDLE h_srq = DAT_HANDLE_NULL;
+static DAT_CR_HANDLE h_cr = DAT_HANDLE_NULL;
+static DAT_PSP_HANDLE h_psp = DAT_HANDLE_NULL;
+static DAT_IB_ADDR_HANDLE *remote_ah = DAT_HANDLE_NULL;
+static DAT_EP_HANDLE *h_ep;
+
+static DAT_EVD_HANDLE h_async_evd = DAT_HANDLE_NULL;
+static DAT_EVD_HANDLE h_dto_req_evd = DAT_HANDLE_NULL;
+static DAT_EVD_HANDLE h_dto_rcv_evd = DAT_HANDLE_NULL;
+static DAT_EVD_HANDLE h_cr_evd = DAT_HANDLE_NULL;
+static DAT_EVD_HANDLE h_conn_evd = DAT_HANDLE_NULL;
+
+static DAT_EP_ATTR ep_attr;
+char hostname[256] = { 0 };
+char provider[64] = DAPL_PROVIDER;
+char addr_str[INET_ADDRSTRLEN];
+
+int status;
+
+/* defaults */
+static int server = 1;
+static int verbose = 0;
+static int connections = 1;
+static int bursts_number = 3;
+static int burst_size = 1;
+static int server_port_id = SERVER_CONN_QUAL;
+static int client_port_id = SERVER_CONN_QUAL + 1;
+static int ucm = 0;
+static int ud_test = 0;
+static int srq_test = 1;
+
+/* RDMA buffers */
+static DAT_LMR_HANDLE h_lmr_send = DAT_HANDLE_NULL;
+static DAT_LMR_HANDLE h_lmr_recv = DAT_HANDLE_NULL;
+static DAT_LMR_CONTEXT lmr_context_send;
+static DAT_LMR_CONTEXT lmr_context_recv;
+static DAT_RMR_CONTEXT rmr_context_send;
+static DAT_RMR_CONTEXT rmr_context_recv;
+static DAT_VLEN registered_size_send;
+static DAT_VLEN registered_size_recv;
+static DAT_VADDR registered_addr_send;
+static DAT_VADDR registered_addr_recv;
+
+static int tx_buf_len = 0, rx_buf_len;
+static int connected = 0;
+char *rbuf = NULL;
+char *sbuf = NULL;
+static DAT_SOCK_ADDR6 remote;
+
+/* forward prototypes */
+const char *DT_RetToString(DAT_RETURN ret_value);
+const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code);
+void print_usage(void);
+void flush_evds(void);
+static void print_ia_address(struct sockaddr *sa);
+DAT_RETURN conn_client(void);
+DAT_RETURN conn_server(void);
+DAT_RETURN disconnect_eps(void);
+DAT_RETURN create_events(void);
+DAT_RETURN destroy_events(void);
+DAT_RETURN register_rdma_memory(void);
+void unregister_rdma_memory(void);
+DAT_RETURN send_msg(char *buff, char msg_head, DAT_UINT32 ep_num, DAT_UINT32 msg_num);
+DAT_RETURN process_cr(void);
+DAT_RETURN process_conn(void);
+#define LOGPRINTF if (verbose) printf
+
+int main(int argc, char **argv)
+{
+ int i, j, c, ep_post_num;
+ DAT_RETURN ret;
+ DAT_IA_ATTR ia_attr;
+ DAT_SRQ_ATTR srq_attr;
+ DAT_DTO_COOKIE cookie;
+ DAT_LMR_TRIPLET l_iov;
+ DAT_COUNT nmore;
+ DAT_EVENT event;
+ int tx_before = 0, ep_num, b_num, ib_mtu = 0;
+ char *snd_buf;
+ char *rcv_buf, *msg_buf;
+ char incoming_header, recv_expected_header;
+ DAT_UINT32 incoming_ep_num, incoming_msg_num;
+ DAT_UINT32 *last_msg_num_from_ep;
+ DAT_UINT64 recv_buf_index;
+ DAT_PROVIDER_ATTR pr_attr;
+
+ /* parse arguments */
+ while ((c = getopt(argc, argv, "svuB:c:t:h:P:p:q:l:b:S:")) != -1) {
+ switch (c) {
+ case 's':
+ server = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ fflush(stdout);
+ break;
+ case 'c':
+ connections = atoi(optarg);
+ if (connections > MAX_CONN) {
+ printf("Too many connections. Max %d.\n",
+ MAX_CONN);
+ exit(-12);
+ }
+ break;
+ case 'b':
+ tx_buf_len = atoi(optarg);
+ if (tx_buf_len <= 0) {
+ printf(" Buffer size need to be positive\n");
+ exit(-12);
+ }
+ break;
+ case 't':
+ bursts_number = atoi(optarg);
+ if (bursts_number < 0) {
+ printf("Bursts number (%d) can't be negative.\n",
+ bursts_number);
+ exit(-12);
+ }
+ break;
+ case 'p':
+ server_port_id = atoi(optarg);
+ client_port_id = server_port_id + 1;
+ break;
+ case 'S':
+ srq_test = atoi(optarg);
+ break;
+ case 'B':
+ burst_size = atoi(optarg);
+ if (burst_size > MAX_BURST) {
+ printf("Burst size is too big. Max %d\n",
+ MAX_BURST);
+ exit(-12);
+ }
+ break;
+ case 'h':
+ server = 0;
+ strcpy(hostname, optarg);
+ break;
+ case 'P':
+ strcpy(provider, optarg);
+ break;
+ case 'q':
+ /* map UCM qpn into AF_INET6 sin6_flowinfo */
+ remote.sin6_family = AF_INET6;
+ remote.sin6_flowinfo = htonl(strtol(optarg,NULL,0));
+ ucm = 1;
+ server = 0;
+ break;
+ case 'l':
+ /* map UCM lid into AF_INET6 sin6_port */
+ remote.sin6_family = AF_INET6;
+ remote.sin6_port = htons(strtol(optarg,NULL,0));
+ ucm = 1;
+ server = 0;
+ break;
+ case 'u':
+ ud_test = 1;
+ break;
+ default:
+ print_usage();
+ exit(-12);
+ }
+ }
+
+#if defined(_WIN32) || defined(_WIN64)
+ {
+ WSADATA wsaData;
+
+ i = WSAStartup(MAKEWORD(2, 2), &wsaData);
+ if (i != 0) {
+ printf("%s WSAStartup(2.2) failed? (0x%x)\n", argv[0],
+ i);
+ fflush(stdout);
+ exit(1);
+ }
+ }
+#endif
+
+ printf(" Running %s %s test as %s on %s with %d connections,"
+ " %d burst%s of %d messages\n", ud_test ? "UD":"RC",
+ srq_test ? "SRQ":"none SRQ",
+ server ? "SERVER:" : "CLIENT:", provider, connections,
+ bursts_number, bursts_number> 1 ? "s" : "", burst_size);
+ fflush(stdout);
+
+ /* allocate EP handles for all connections */
+ h_ep = (DAT_EP_HANDLE*)malloc(connections * sizeof(DAT_EP_HANDLE));
+ if (h_ep == NULL) {
+ perror("malloc ep");
+ exit(1);
+ }
+ memset(h_ep, 0, (connections * sizeof(DAT_EP_HANDLE)));
+
+ if (ud_test) {
+ remote_ah = (DAT_IB_ADDR_HANDLE*)malloc(connections * sizeof(DAT_IB_ADDR_HANDLE));
+ if (remote_ah == NULL) {
+ perror("malloc remote ah");
+ exit(1);
+ }
+ memset(remote_ah, 0, connections * sizeof(DAT_IB_ADDR_HANDLE));
+ }
+
+ /* Save last message number for each ep */
+ last_msg_num_from_ep = malloc(connections * sizeof(DAT_UINT32));
+ if (last_msg_num_from_ep == NULL) {
+ perror("malloc last_msg_num_from_ep");
+ exit(1);
+ }
+ memset(last_msg_num_from_ep, 0, (connections * sizeof(DAT_UINT32)));
+
+ /* dat_ia_open, dat_pz_create */
+ h_async_evd = DAT_HANDLE_NULL;
+ ret = dat_ia_open(provider, 8, &h_async_evd, &h_ia);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error Adaptor open: %s\n",
+ DT_RetToString(ret));
+ exit(1);
+ } else
+ LOGPRINTF(" Opened Interface Adaptor %p\n", h_ia);
+
+ /* query for UCM addressing */
+ ret = dat_ia_query(h_ia, 0, DAT_IA_FIELD_ALL, &ia_attr,
+ DAT_PROVIDER_FIELD_PROVIDER_SPECIFIC_ATTR,
+ &pr_attr);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Err Adaptor query: %s\n", DT_RetToString(ret));
+ exit(1);
+ }
+
+ /* Set tx_buf_len to IB_MTU if it was not specified by the user */
+ for (i = 0; i < pr_attr.num_provider_specific_attr; i++) {
+ if (!strcmp (pr_attr.provider_specific_attr[i].name,
+ "DAT_IB_TRANSPORT_MTU"))
+ {
+ ib_mtu = atoi(pr_attr.provider_specific_attr[i].value);
+ break;
+ }
+ }
+
+ if (ud_test) {
+ if (!ib_mtu) {
+ fprintf(stderr, " Error: ud test: IB_MTU was not found"
+ " in provider attr\n");
+ exit(1);
+ }
+ if (tx_buf_len > ib_mtu) {
+ fprintf(stderr, " Error: ud test: user buf len (%d)"
+ "bigger than IB_MTU (%d)\n", tx_buf_len, ib_mtu);
+ exit(1);
+ }
+ }
+
+ if (!tx_buf_len) {
+ /* no user input - set tx_buf_len to IB_MTU */
+ if (!ib_mtu) {
+ fprintf(stderr, " Error: no user input and IB_MTU was"
+ " not found in provider attr\n");
+ exit(1);
+ }
+ tx_buf_len = ib_mtu;
+ }
+
+ LOGPRINTF(" Tx buffer len set to device MTU %d\n", tx_buf_len);
+ rx_buf_len = tx_buf_len;
+ if (ud_test)
+ rx_buf_len = tx_buf_len + 40;
+ LOGPRINTF(" Rx buffer len set to %d\n", rx_buf_len);
+
+ print_ia_address(ia_attr.ia_address_ptr);
+
+ /* Create Protection Zone */
+ LOGPRINTF(" Create Protection Zone\n");
+ ret = dat_pz_create(h_ia, &h_pz);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error creating Protection Zone: %s\n",
+ DT_RetToString(ret));
+ exit(1);
+ } else
+ LOGPRINTF(" Created Protection Zone\n");
+
+ LOGPRINTF(" Create events\n");
+ ret = create_events();
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error creating events: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else {
+ LOGPRINTF(" Create events done\n");
+ }
+
+ /* Create SRQ */
+ if (srq_test) {
+ LOGPRINTF(" Create SRQ\n");
+ srq_attr.max_recv_dtos = connections * burst_size;
+ srq_attr.max_recv_iov = MSG_IOV_COUNT;
+ srq_attr.low_watermark = 0;
+
+ ret = dat_srq_create(h_ia, h_pz, &srq_attr, &h_srq);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_srq_create: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF(" SRQ created %p \n", h_srq);
+ }
+
+ /* allocate send and receive buffers */
+ if (((rbuf = malloc(connections * rx_buf_len * burst_size)) == NULL) ||
+ ((sbuf = malloc(connections * tx_buf_len * burst_size)) == NULL)) {
+ fprintf(stderr, " Error allocating snd/rcv buffers\n");
+ goto cleanup;
+ }
+
+ /* Register memory */
+ LOGPRINTF(" Register RDMA memory\n");
+ ret = register_rdma_memory();
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error registering RDMA memory: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF(" Register RDMA memory done\n");
+
+ /* create EP */
+ memset(&ep_attr, 0, sizeof(ep_attr));
+ if (ud_test) {
+ ep_attr.service_type = DAT_IB_SERVICE_TYPE_UD;
+ ep_attr.max_message_size = tx_buf_len;
+ } else {
+ ep_attr.service_type = DAT_SERVICE_TYPE_RC;
+ ep_attr.max_message_size = 0;
+ }
+ ep_attr.max_request_dtos = (server ? burst_size : (connections * burst_size));
+ ep_attr.max_recv_dtos = (server ? burst_size : (connections * burst_size));
+ ep_attr.max_rdma_size = 0;
+ ep_attr.qos = 0;
+ ep_attr.recv_completion_flags = 0;
+ ep_attr.max_recv_iov = MSG_IOV_COUNT;
+ ep_attr.max_request_iov = MSG_IOV_COUNT;
+ ep_attr.max_rdma_read_in = 0;
+ ep_attr.max_rdma_read_out = 0;
+ ep_attr.request_completion_flags = DAT_COMPLETION_DEFAULT_FLAG;
+ ep_attr.ep_transport_specific_count = 0;
+ ep_attr.ep_transport_specific = NULL;
+ ep_attr.ep_provider_specific_count = 0;
+ ep_attr.ep_provider_specific = NULL;
+
+ for (i = 0; i < connections; i++) {
+ if (srq_test)
+ ret = dat_ep_create_with_srq(h_ia, h_pz, h_dto_rcv_evd,
+ h_dto_req_evd, h_conn_evd, h_srq,
+ &ep_attr, &h_ep[i]);
+ else
+ ret = dat_ep_create(h_ia, h_pz, h_dto_rcv_evd,
+ h_dto_req_evd, h_conn_evd,
+ &ep_attr, &h_ep[i]);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_ep_create: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF(" EP %d created %p\n", i, h_ep[i]);
+
+ /* For client in UD test we use one EP to many EPs on server */
+ if (!server && ud_test)
+ break;
+ }
+
+ /* pre-post all buffers */
+ rcv_buf = rbuf;
+ for (i = 0; i < connections; i++) {
+ for (j = 0; j < burst_size; j++) {
+ cookie.as_64 = i * burst_size + j;
+ l_iov.lmr_context = lmr_context_recv;
+ l_iov.virtual_address = (DAT_VADDR) (uintptr_t) rcv_buf;
+ l_iov.segment_length = rx_buf_len;
+
+ if (srq_test) {
+ LOGPRINTF(" Pre SRQ post receive msg buff %p cookie %ld.....",
+ rcv_buf, cookie.as_64);
+ ret = dat_srq_post_recv(h_srq, 1, &l_iov, cookie);
+ } else {
+ if(server || !ud_test)
+ ep_post_num = i;
+ else
+ ep_post_num = 0;
+
+ LOGPRINTF(" Pre post receive for EP %d msg buff %p.....",
+ ep_post_num, rcv_buf);
+ ret = dat_ep_post_recv(h_ep[ep_post_num], 1, &l_iov,
+ cookie, DAT_COMPLETION_DEFAULT_FLAG);
+ }
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, "\n Error posting recv msg buffer: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF("Done\n");
+
+ /* next buffer */
+ rcv_buf += rx_buf_len;
+ }
+ }
+
+ /* create the service point for server listen */
+ if (server) {
+ LOGPRINTF(" Creating server service point\n");
+ ret = dat_psp_create(h_ia,
+ server ? server_port_id : client_port_id,
+ h_cr_evd,
+ DAT_PSP_CONSUMER_FLAG,
+ &h_psp);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR psp_create: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ printf(" %s ready on port %d\n",
+ server ? "server" : "client",
+ server ? server_port_id : client_port_id);
+ }
+
+ /* Connect all */
+ if (server)
+ ret = conn_server();
+ else
+ ret = conn_client();
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error %s: %s\n",
+ server ? "server()" : "client()",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ printf("\n ALL %d CONNECTED on %s!\n\n",
+ connections, server ? "server" : "client");
+
+ connected = 1;
+
+ /*
+ * Client ping: 0x55, ep_num, ep msg_num
+ * Server pong: 0xAA, ep, ep smg_num
+ */
+ if (server)
+ recv_expected_header = 0x55;
+ else
+ recv_expected_header = 0xaa;
+
+ for (b_num = 0; b_num < bursts_number; b_num++) {
+ /* Initialize snd_buf to the beginning */
+ snd_buf = sbuf;
+
+ if (!server) { /* Send Ping */
+ for (ep_num = 0; ep_num < connections; ep_num++) {
+ for (i = 0; i < burst_size; i++) {
+ /* walk the send */
+ ret = send_msg(snd_buf, 0x55, ep_num,
+ tx_before + i + 1);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr,
+ " ERR: dat_ep_post_send() %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF(" send_msg completed\n");
+ /* next buffers */
+ snd_buf += tx_buf_len;
+ }
+ }
+ }
+
+ for (ep_num = 0; ep_num < connections; ep_num++) {
+ for (i = 0; i < burst_size; i++) {
+ /* walk the rcv */
+ ret = dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1,
+ &event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr,
+ " Error waiting on h_dto_evd %p: %s\n",
+ h_dto_rcv_evd, DT_RetToString(ret));
+ goto cleanup;
+ }
+
+ /* validate event number and status */
+ LOGPRINTF(" inbound message; message arrived!\n");
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT &&
+ ud_test && event.event_number != DAT_IB_DTO_EVENT) {
+ fprintf(stderr, " Error unexpected DTO event (%d): %s\n",
+ event.event_number,
+ DT_EventToSTr(event.event_number));
+ goto cleanup;
+ }
+
+ if (event.event_data.dto_completion_event_data.
+ transfered_length != rx_buf_len) {
+ fprintf(stderr, " ERR: recv event: len=%d "
+ "cookie=" F64x " exp len %d\n",
+ (int)event.event_data.dto_completion_event_data.
+ transfered_length,
+ event.event_data.dto_completion_event_data.
+ user_cookie.as_64, (int)rx_buf_len);
+ goto cleanup;
+ }
+
+ /* Check data */
+ recv_buf_index = event.event_data.dto_completion_event_data.
+ user_cookie.as_64;
+ rcv_buf = rbuf + recv_buf_index * rx_buf_len;
+ if (ud_test)
+ msg_buf = rcv_buf + 40;
+ else
+ msg_buf = rcv_buf;
+
+ incoming_header = *msg_buf;
+ incoming_ep_num = ntohl(*((DAT_UINT32 *)(msg_buf + 4)));
+ incoming_msg_num = ntohl(*((DAT_UINT32 *)(msg_buf + 8)));
+ LOGPRINTF(" %s recv buffer %p (index %ld) buf len %d "
+ " incoming data: header %d, ep num %d, ep msg num %d "
+ " (nmore = %d)\n",
+ server ? "SERVER:" : "CLIENT:", rcv_buf,
+ recv_buf_index, rx_buf_len, incoming_header,
+ incoming_ep_num, incoming_msg_num, nmore);
+
+ /* May have race condition between EPs therefore
+ * need to track each ep last message number */
+ if (last_msg_num_from_ep[incoming_ep_num] + 1 != incoming_msg_num) {
+ fprintf(stderr, " ERR: ep %d recv msg %d exp %d\n",
+ incoming_ep_num, incoming_msg_num,
+ last_msg_num_from_ep[incoming_ep_num] + 1);
+ goto cleanup;
+ }
+ last_msg_num_from_ep[incoming_ep_num] = incoming_msg_num;
+
+ if (incoming_header != recv_expected_header) {
+ fprintf(stderr, " ERR: ep %d recv header"
+ " 0x%x exp 0x%x\n",
+ incoming_ep_num, incoming_header,
+ recv_expected_header);
+ goto cleanup;
+ }
+
+ /* Done with Recv buffer - post the buffer back */
+ cookie.as_64 = recv_buf_index;
+ l_iov.lmr_context = lmr_context_recv;
+ l_iov.virtual_address = (DAT_VADDR) (uintptr_t) rcv_buf;
+ l_iov.segment_length = rx_buf_len;
+
+ if (srq_test) {
+ LOGPRINTF(" Pre SRQ post receive msg buff %p.....",
+ (DAT_PVOID)l_iov.virtual_address);
+ ret = dat_srq_post_recv(h_srq, 1, &l_iov, cookie);
+ } else {
+ LOGPRINTF(" Pre osted receive msg, "
+ "from ep %p buffer %p.....",
+ event.event_data.
+ dto_completion_event_data.
+ ep_handle , rcv_buf);
+ ret = dat_ep_post_recv(event.event_data.
+ dto_completion_event_data.
+ ep_handle, 1, &l_iov, cookie,
+ DAT_COMPLETION_DEFAULT_FLAG);
+ }
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, "\n Error posting recv "
+ "msg buffer: %s\n",
+ DT_RetToString(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF("Done\n");
+ }
+ }
+
+ if (server) { /* Send pong */
+ for (ep_num = 0; ep_num < connections; ep_num++) {
+ for (i = 0; i < burst_size; i++) {
+ /* walk the send */
+ ret = send_msg(snd_buf, 0xaa, ep_num,
+ tx_before + i + 1);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERROR: dat_ep_post_send() %s\n",
+ DT_EventToSTr(ret));
+ goto cleanup;
+ } else
+ LOGPRINTF(" send_msg completed\n");
+ /* next buffers */
+ snd_buf += tx_buf_len;
+ }
+ }
+ }
+
+ tx_before += burst_size;
+ /* clean req evd */
+ for (ep_num = 0; ep_num < connections; ep_num++) {
+ for (i = 0; i < burst_size; i++) {
+ ret = dat_evd_wait(h_dto_req_evd, DTO_TIMEOUT, 1,
+ &event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr,
+ " Error waiting on h_req_evd %p: %s\n",
+ h_dto_req_evd, DT_RetToString(ret));
+ goto cleanup;
+ }
+
+ if ((event.event_data.dto_completion_event_data.
+ transfered_length != tx_buf_len)
+ || event.event_data.dto_completion_event_data.
+ status != DAT_SUCCESS) {
+ fprintf(stderr, " ERROR: DTO REQ size %d, status %d\n",
+ event.event_data.dto_completion_event_data.
+ transfered_length,
+ event.event_data.
+ dto_completion_event_data.status);
+ goto cleanup;
+ }
+ }
+ }
+ }
+
+ goto complete;
+cleanup:
+ flush_evds();
+ goto bail;
+complete:
+
+ /* disconnect and free EP resources */
+ if (h_ep[0]) {
+ /* unregister message buffers and tear down connection */
+ LOGPRINTF(" Disconnect EPs\n");
+ ret = disconnect_eps();
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error disconnect_eps: %s\n",
+ DT_RetToString(ret));
+ goto bail;
+ } else {
+ LOGPRINTF(" disconnect_eps complete\n");
+ }
+ }
+
+ /* destroy server service point(s) */
+ if (h_psp != DAT_HANDLE_NULL) {
+ ret = dat_psp_free(h_psp);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_psp_free: %s\n",
+ DT_RetToString(ret));
+ goto bail;
+ } else {
+ LOGPRINTF(" psp_free complete\n");
+ }
+ }
+
+ unregister_rdma_memory();
+
+ /* Free SRQ */
+ if (h_srq != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Free SRQ %p \n", h_srq);
+ ret = dat_srq_free(h_srq);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Err freeing SRQ: %s\n",
+ DT_RetToString(ret));
+ } else {
+ LOGPRINTF(" SRQ Freed\n");
+ h_srq = DAT_HANDLE_NULL;
+ }
+ }
+
+ /* free EVDs */
+ LOGPRINTF(" destroy events\n");
+ ret = destroy_events();
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error destroy_events: %s\n",
+ DT_RetToString(ret));
+ goto bail;
+ } else
+ LOGPRINTF(" destroy events done\n");
+
+ /* Free protection domain */
+ LOGPRINTF(" Freeing pz\n");
+ ret = dat_pz_free(h_pz);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error freeing PZ: %s\n", DT_RetToString(ret));
+ goto bail;
+ } else {
+ LOGPRINTF(" Freed pz\n");
+ h_pz = NULL;
+ }
+
+ /* close the device */
+ LOGPRINTF(" Closing Interface Adaptor\n");
+ ret = dat_ia_close(h_ia, DAT_CLOSE_ABRUPT_FLAG);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error Adaptor close: %s\n",
+ DT_RetToString(ret));
+ goto bail;
+ } else
+ LOGPRINTF(" Closed Interface Adaptor\n");
+
+ printf(" DAPL %s %s Test Complete.\n\n",
+ ud_test ? "UD" : "RC", srq_test ? "SRQ" : "none SRQ");
+
+ fflush(stderr); fflush(stdout);
+bail:
+ free(h_ep);
+ if(remote_ah)
+ free(remote_ah);
+
+#if defined(_WIN32) || defined(_WIN64)
+ WSACleanup();
+#endif
+ return (0);
+}
+
+DAT_RETURN process_cr()
+{
+ DAT_RETURN ret;
+ DAT_EVENT event;
+ DAT_COUNT nmore;
+ DAT_CR_PARAM cr_param;
+ int i, pdata;
+ DAT_CR_ARRIVAL_EVENT_DATA *cr_event =
+ &event.event_data.cr_arrival_event_data;
+
+ printf(" Accepting...\n");
+ fflush(stdout);
+ for (i = 0; i < connections; i++) {
+ /* Wait for CR's */
+ ret = dat_evd_wait(h_cr_evd, CR_TIMEOUT, 1, &event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR: CR dat_evd_wait() %s\n",
+ DT_RetToString(ret));
+ return ret;
+ }
+
+ if (event.event_number != DAT_CONNECTION_REQUEST_EVENT &&
+ (ud_test && event.event_number !=
+ DAT_IB_UD_CONNECTION_REQUEST_EVENT)) {
+ fprintf(stderr, " Error unexpected cr event : %s\n",
+ DT_EventToSTr(event.event_number));
+ return (DAT_ABORT);
+ }
+
+ if ((event.event_data.cr_arrival_event_data.conn_qual !=
+ (server ? server_port_id : client_port_id))
+ || (event.event_data.cr_arrival_event_data.sp_handle.
+ psp_handle != h_psp)) {
+ fprintf(stderr, " Error wrong cr event data : %s\n",
+ DT_EventToSTr(event.event_number));
+ return (DAT_ABORT);
+ }
+
+ /* accept connect request from client */
+ h_cr = cr_event->cr_handle;
+ ret = dat_cr_query(h_cr, DAT_CSP_FIELD_ALL, &cr_param);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error: unable to query cr\n");
+ return (DAT_ABORT);
+ }
+
+ /* use private data to select EP */
+ pdata = ntohl(*((int *)cr_param.private_data));
+
+ LOGPRINTF(" Accepting connect request %d from client:\n", pdata);
+
+ ret = dat_cr_accept(h_cr, h_ep[pdata], 4, cr_param.private_data);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR dat_cr_accept: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else
+ LOGPRINTF(" Accept[%d] complete\n", i);
+
+ event.event_number = 0;
+ }
+ return DAT_SUCCESS;
+}
+
+DAT_RETURN process_conn()
+{
+ DAT_RETURN ret;
+ DAT_EVENT event;
+ DAT_COUNT nmore;
+ int i, exp_event, pdata;
+ DAT_IB_EXTENSION_EVENT_DATA *ext_event = (DAT_IB_EXTENSION_EVENT_DATA *)
+ & event.event_extension_data[0];
+ DAT_CONNECTION_EVENT_DATA *conn_event =
+ &event.event_data.connect_event_data;
+
+ if (ud_test)
+ exp_event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;
+ else
+ exp_event = DAT_CONNECTION_EVENT_ESTABLISHED;
+
+ /* process the RTU, ESTABLISHMENT event */
+ printf(" Completing...\n");
+ for (i = 0; i < connections; i++) {
+
+ /* process completions */
+ ret = dat_evd_wait(h_conn_evd, CONN_TIMEOUT, 1, &event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR: CONN evd_wait() %s\n",
+ DT_RetToString(ret));
+ return ret;
+ }
+ if (event.event_number != exp_event) {
+ fprintf(stderr, " Err unexpected conn event : 0x%x %s\n",
+ event.event_number,
+ DT_EventToSTr(event.event_number));
+ return (DAT_ABORT);
+ }
+ event.event_number = 0;
+ LOGPRINTF(" CONN_EST[%d] complete\n", i);
+
+ /* RC we are done */
+ if (!ud_test)
+ continue;
+
+ /* store each remote_ah according to remote EP index */
+ pdata = ntohl(*((int *)conn_event->private_data));
+ LOGPRINTF(" Got private data=0x%x\n", pdata);
+
+ /* UD, get AH for sends.
+ * NOTE: bi-directional AH resolution results in a CONN_EST
+ * for both outbound connect and inbound CR.
+ * Use Active CONN_EST which includes server's CR
+ * pdata for remote_ah idx to send.
+ *
+ * DAT_IB_UD_PASSIVE_REMOTE_AH == passive side CONN_EST
+ * DAT_IB_UD_REMOTE_AH == active side CONN_EST
+ */
+ if (ext_event->type == DAT_IB_UD_REMOTE_AH) {
+ remote_ah[pdata] = ext_event->remote_ah;
+ LOGPRINTF(" Active side - remote_ah[%d]: ah=%p, qpn=0x%x "
+ "addr=%s\n", pdata, remote_ah[pdata].ah,
+ remote_ah[pdata].qpn, inet_ntoa(((struct sockaddr_in *)
+ &remote_ah[pdata].
+ ia_addr)->sin_addr));
+ } else if (ext_event->type == DAT_IB_UD_PASSIVE_REMOTE_AH) {
+ remote_ah[pdata] = ext_event->remote_ah;
+ LOGPRINTF(" Passive side - remote_ah[%d]: ah=%p, qpn=0x%x "
+ "addr=%s\n", pdata, remote_ah[pdata].ah,
+ remote_ah[pdata].qpn, inet_ntoa(((struct sockaddr_in *)
+ &remote_ah[pdata].
+ ia_addr)->sin_addr));
+ } else {
+ printf(" Error - unexpected UD ext_event type: 0x%x\n",
+ ext_event->type);
+ exit(1);
+ }
+ }
+ return DAT_SUCCESS;
+}
+
+DAT_RETURN conn_server()
+{
+ DAT_RETURN ret;
+
+ /* wait for conn REQ and accept */
+ ret = process_cr();
+ if (ret != DAT_SUCCESS)
+ return ret;
+
+ /* wait for conn EST */
+ ret = process_conn();
+ if (ret != DAT_SUCCESS)
+ return ret;
+
+ return DAT_SUCCESS;
+}
+
+DAT_RETURN conn_client()
+{
+ DAT_IA_ADDRESS_PTR raddr = (DAT_IA_ADDRESS_PTR)&remote;
+ DAT_RETURN ret;
+ struct addrinfo *target;
+ int rval, i, pdata;
+
+ if (ucm)
+ goto no_resolution;
+
+#if defined(_WIN32) || defined(_WIN64)
+ if ((rval = getaddrinfo(hostname, "ftp", NULL, &target)) != 0) {
+ printf("\n remote name resolution failed! %s\n",
+ gai_strerror(rval));
+ exit(1);
+ }
+ rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;
+#else
+ if (getaddrinfo(hostname, NULL, NULL, &target) != 0) {
+ perror("\n remote name resolution failed!");
+ exit(1);
+ }
+ rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;
+#endif
+ printf(" Connecting to Server: %s \n", hostname);
+ printf(" Address: %d.%d.%d.%d port %d\n",
+ (rval >> 0) & 0xff, (rval >> 8) & 0xff,
+ (rval >> 16) & 0xff, (rval >> 24) & 0xff,
+ server_port_id);
+
+ raddr = (DAT_IA_ADDRESS_PTR)target->ai_addr;
+
+no_resolution:
+
+ printf(" Connecting...\n");
+ for (i = 0; i < connections; i++) {
+ /* Client in UD test is one EP to many */
+ pdata = htonl(i);
+ ret = dat_ep_connect(ud_test ? h_ep[0]: h_ep[i],
+ raddr, server_port_id, CONN_TIMEOUT,
+ 4, &pdata, 0, DAT_CONNECT_DEFAULT_FLAG);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR dat_ep_connect: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else
+ LOGPRINTF(" dat_ep_connect [%d] complete\n", i);
+ }
+
+ /* wait for conn EST */
+ ret = process_conn();
+ if (ret != DAT_SUCCESS)
+ return ret;
+
+ if (!ucm)
+ freeaddrinfo(target);
+
+ return (DAT_SUCCESS);
+}
+
+/* validate disconnected EP's and free them */
+DAT_RETURN disconnect_eps(void)
+{
+ DAT_RETURN ret;
+ DAT_EVENT event, async_event;
+ DAT_COUNT nmore;
+ int i,ii;
+ DAT_CONNECTION_EVENT_DATA *conn_event =
+ &event.event_data.connect_event_data;
+
+ if (!connected)
+ return DAT_SUCCESS;
+
+ if (ud_test) {
+ for (ii = 0; ii < connections; ii++) {
+ LOGPRINTF(" Free EP[%d] %p\n", ii, h_ep[ii]);
+ ret = dat_ep_free(h_ep[ii]);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, "ERR free EP[%d] %p: %s\n",
+ ii, h_ep[ii], DT_RetToString(ret));
+ } else {
+ LOGPRINTF(" Freed EP[%d] %p\n", ii, h_ep[ii]);
+ h_ep[ii] = DAT_HANDLE_NULL;
+ }
+ /* Client use only EP zero in UD test */
+ if (!server)
+ break;
+ }
+ return DAT_SUCCESS;
+ }
+ /*
+ * Only the client needs to call disconnect. The server _should_ be able
+ * to just wait on the EVD associated with connection events for a
+ * disconnect request and then exit.
+ */
+ for (i = 0; i < connections; i++) {
+ if (!server) {
+ LOGPRINTF(" dat_ep_disconnect[%d]\n",i);
+
+ ret = dat_ep_disconnect(h_ep[i], DAT_CLOSE_DEFAULT);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error disconnect: %s\n",
+ DT_RetToString(ret));
+ return ret;
+ } else {
+ LOGPRINTF(" disconnect completed[%d]\n", i);
+ }
+ }
+ else {
+ LOGPRINTF(" Server waiting for disconnect...\n");
+ }
+
+ LOGPRINTF(" Wait for Disc event\n");
+ nmore = 0;
+ event.event_number = 0;
+ conn_event->ep_handle = NULL;
+ ret = dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE, 1, &event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_wait: %s\n", DT_RetToString(ret));
+ return ret;
+ } else
+ LOGPRINTF(" disc event[%d] complete\n", i);
+
+ if (srq_test) {
+ LOGPRINTF(" Wait for EP async event\n");
+ async_event.event_number = 0;
+ ret = dat_evd_wait(h_async_evd, DAT_TIMEOUT_INFINITE,
+ 1, &async_event, &nmore);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_wait async evd: %s\n",
+ DT_RetToString(ret));
+ return ret;
+ } else
+ LOGPRINTF(" Async event 0x%x received for EP %p\n",
+ async_event.event_number,
+ async_event.event_data.asynch_error_event_data.dat_handle);
+
+ if (async_event.event_number != DAT_ASYNC_ERROR_EP_BROKEN) {
+ LOGPRINTF(" Invalid async event number 0x%x expected 0x%x\n",
+ async_event.event_number, DAT_ASYNC_ERROR_EP_BROKEN);
+ return DAT_INVALID_HANDLE;
+ }
+
+ if (conn_event->ep_handle != async_event.
+ event_data.asynch_error_event_data.dat_handle) {
+ LOGPRINTF(" Invalid EP via async event. conn event EP = %p,"
+ " async event EP = %p\n", conn_event->ep_handle,
+ async_event.event_data.asynch_error_event_data.dat_handle);
+ return DAT_INVALID_HANDLE;
+ }
+ }
+
+ LOGPRINTF(" Check for valid EP and free it\n");
+ /* check for valid EP in creation list */
+ for (ii = 0; ii < connections; ii++) {
+ if (h_ep[ii] == conn_event->ep_handle) {
+ LOGPRINTF(" valid EP[%d] %p\n", ii, h_ep[ii]);
+ ret = dat_ep_free(h_ep[ii]);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " ERR free EP[%d] %p: %s\n",
+ ii, h_ep[ii], DT_RetToString(ret));
+ return ret;
+ } else {
+ LOGPRINTF(" Freed EP[%d] %p\n", ii, h_ep[ii]);
+ h_ep[ii] = DAT_HANDLE_NULL;
+ }
+ break;
+ }
+ }
+ if (ii == connections) {
+ LOGPRINTF(" %s: invalid EP[%d] %p via DISC event!\n",
+ server ? "Server" : "Client",
+ i, conn_event->ep_handle);
+ return DAT_INVALID_HANDLE;
+ }
+ }
+
+ /* free EPs */
+ LOGPRINTF(" Successfully disconnected all %d EP's\n", connections);
+ return DAT_SUCCESS;
+}
+
+ /*
+ * Create CR, CONN, and DTO events
+ */
+DAT_RETURN create_events(void)
+{
+ DAT_RETURN ret;
+ DAT_EVD_PARAM param;
+ DAT_COUNT evd_min_qlen;
+
+ /*** create CR EVD ***/
+ evd_min_qlen = connections;
+ ret = dat_evd_create(h_ia,
+ evd_min_qlen,
+ DAT_HANDLE_NULL,
+ DAT_EVD_CR_FLAG,
+ &h_cr_evd);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_create CR: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ }
+
+ /* query and check size */
+ ret = dat_evd_query(h_cr_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Err dat_evd_query CR evd: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else if (param.evd_qlen < evd_min_qlen) {
+ fprintf(stderr, " Error dat_evd qsize too small: %d < %d\n",
+ param.evd_qlen, evd_min_qlen);
+ return (ret);
+ }
+
+ LOGPRINTF(" cr_evd created (%p). QLEN - requested %d and actual %d\n",
+ h_cr_evd, evd_min_qlen, param.evd_qlen);
+
+ /*** create conn EVD ***/
+ evd_min_qlen = connections * 2;
+ ret = dat_evd_create(h_ia,
+ evd_min_qlen,
+ DAT_HANDLE_NULL,
+ DAT_EVD_CONNECTION_FLAG,
+ &h_conn_evd);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_create CONN: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ }
+
+ /* query and check size */
+ ret = dat_evd_query(h_conn_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_query CONN evd: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else if (param.evd_qlen < evd_min_qlen) {
+ fprintf(stderr, " Error dat_evd qsize too small: %d < %d\n",
+ param.evd_qlen, evd_min_qlen);
+ return (ret);
+ }
+
+ LOGPRINTF(" conn_evd created (%p). QLEN - requested %d and actual %d\n",
+ h_conn_evd, evd_min_qlen, param.evd_qlen);
+
+ /*** create dto SND EVD ***/
+ evd_min_qlen = connections * burst_size;
+ ret = dat_evd_create(h_ia,
+ evd_min_qlen,
+ NULL,
+ DAT_EVD_DTO_FLAG,
+ &h_dto_req_evd);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_create REQ: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ }
+
+ /* query and check size */
+ ret = dat_evd_query(h_dto_req_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_query REQ evd: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else if (param.evd_qlen < evd_min_qlen) {
+ fprintf(stderr, " Error dat_evd qsize too small: %d < %d\n",
+ param.evd_qlen, evd_min_qlen);
+ return (ret);
+ }
+
+ LOGPRINTF(" req_evd created (%p). QLEN - requested %d and actual %d\n",
+ h_dto_req_evd, evd_min_qlen, param.evd_qlen);
+
+ /*** create dto RCV EVD ***/
+ evd_min_qlen = connections * burst_size;
+ ret = dat_evd_create(h_ia,
+ evd_min_qlen,
+ NULL,
+ DAT_EVD_DTO_FLAG,
+ &h_dto_rcv_evd);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_create RCV: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ }
+
+ /* query and check size */
+ ret = dat_evd_query(h_dto_rcv_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error dat_evd_query RCV evd: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else if (param.evd_qlen < evd_min_qlen) {
+ fprintf(stderr, " Error dat_evd qsize too small: %d < %d\n",
+ param.evd_qlen, evd_min_qlen);
+ return (ret);
+ }
+
+ LOGPRINTF(" rcv_evd created (%p). QLEN - requested %d and actual %d\n",
+ h_dto_rcv_evd, evd_min_qlen, param.evd_qlen);
+
+ return DAT_SUCCESS;
+}
+
+/*
+ * Destroy CR, CONN, CNO, and DTO events
+ */
+DAT_RETURN destroy_events(void)
+{
+ DAT_RETURN ret;
+
+ /* free cr EVD */
+ if (h_cr_evd != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Free cr EVD %p \n", h_cr_evd);
+ ret = dat_evd_free(h_cr_evd);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error freeing cr EVD: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Freed cr EVD\n");
+ h_cr_evd = DAT_HANDLE_NULL;
+ }
+ }
+
+ /* free conn EVD */
+ if (h_conn_evd != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Free conn EVD %p\n", h_conn_evd);
+ ret = dat_evd_free(h_conn_evd);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error freeing conn EVD: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Freed conn EVD\n");
+ h_conn_evd = DAT_HANDLE_NULL;
+ }
+ }
+
+ /* free RCV dto EVD */
+ if (h_dto_rcv_evd != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Free RCV dto EVD %p\n", h_dto_rcv_evd);
+ ret = dat_evd_free(h_dto_rcv_evd);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error freeing dto EVD: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Freed dto EVD\n");
+ h_dto_rcv_evd = DAT_HANDLE_NULL;
+ }
+ }
+
+ /* free REQ dto EVD */
+ if (h_dto_req_evd != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Free REQ dto EVD %p\n", h_dto_req_evd);
+ ret = dat_evd_free(h_dto_req_evd);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error freeing dto EVD: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Freed dto EVD\n");
+ h_dto_req_evd = DAT_HANDLE_NULL;
+ }
+ }
+
+ return DAT_SUCCESS;
+}
+
+/*
+ * Map DAT_RETURN values to readable strings,
+ * but don't assume the values are zero-based or contiguous.
+ */
+char errmsg[512] = { 0 };
+const char *DT_RetToString(DAT_RETURN ret_value)
+{
+ const char *major_msg, *minor_msg;
+
+ dat_strerror(ret_value, &major_msg, &minor_msg);
+
+ strcpy(errmsg, major_msg);
+ strcat(errmsg, " ");
+ strcat(errmsg, minor_msg);
+
+ return errmsg;
+}
+
+/*
+ * Map DAT_EVENT_CODE values to readable strings
+ */
+const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code)
+{
+ unsigned int i;
+ static struct {
+ const char *name;
+ DAT_RETURN value;
+ } dat_events[] = {
+# define DATxx(x) { # x, x }
+ DATxx(DAT_DTO_COMPLETION_EVENT),
+ DATxx(DAT_RMR_BIND_COMPLETION_EVENT),
+ DATxx(DAT_CONNECTION_REQUEST_EVENT),
+ DATxx(DAT_CONNECTION_EVENT_ESTABLISHED),
+ DATxx(DAT_CONNECTION_EVENT_PEER_REJECTED),
+ DATxx(DAT_CONNECTION_EVENT_NON_PEER_REJECTED),
+ DATxx(DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR),
+ DATxx(DAT_CONNECTION_EVENT_DISCONNECTED),
+ DATxx(DAT_CONNECTION_EVENT_BROKEN),
+ DATxx(DAT_CONNECTION_EVENT_TIMED_OUT),
+ DATxx(DAT_CONNECTION_EVENT_UNREACHABLE),
+ DATxx(DAT_ASYNC_ERROR_EVD_OVERFLOW),
+ DATxx(DAT_ASYNC_ERROR_IA_CATASTROPHIC),
+ DATxx(DAT_ASYNC_ERROR_EP_BROKEN),
+ DATxx(DAT_ASYNC_ERROR_TIMED_OUT),
+ DATxx(DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR),
+ DATxx(DAT_SOFTWARE_EVENT)
+# undef DATxx
+ };
+# define NUM_EVENTS (sizeof(dat_events)/sizeof(dat_events[0]))
+
+ for (i = 0; i < NUM_EVENTS; i++) {
+ if (dat_events[i].value == event_code) {
+ return (dat_events[i].name);
+ }
+ }
+
+ return ("Invalid_DAT_EVENT_NUMBER");
+}
+
+void flush_evds(void)
+{
+ DAT_EVENT event;
+
+ /* Flush async error queue */
+ printf(" ERR: Checking ASYNC EVD...\n");
+ while (dat_evd_dequeue(h_async_evd, &event) == DAT_SUCCESS) {
+ printf(" ASYNC EVD ENTRY: handle=%p reason=%d\n",
+ event.event_data.asynch_error_event_data.dat_handle,
+ event.event_data.asynch_error_event_data.reason);
+ }
+}
+
+static void print_ia_address(struct sockaddr *sa)
+{
+ char str[INET6_ADDRSTRLEN] = {" ??? "};
+
+ switch(sa->sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr, str, INET6_ADDRSTRLEN);
+ printf(" Local Address AF_INET - %s port %d\n", str, server_port_id);
+ break;
+ case AF_INET6:
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr, str, INET6_ADDRSTRLEN);
+ printf(" Local Address AF_INET6 - %s flowinfo(QPN)=0x%x, port(LID)=0x%x\n",
+ str,
+ ntohl(((struct sockaddr_in6 *)sa)->sin6_flowinfo),
+ ntohs(((struct sockaddr_in6 *)sa)->sin6_port));
+ break;
+ default:
+ printf(" Local Address UNKOWN FAMILY - port %d\n", server_port_id);
+ }
+}
+
+/* Register RDMA Receive buffer */
+DAT_RETURN register_rdma_memory(void)
+{
+ DAT_RETURN ret;
+ DAT_REGION_DESCRIPTION region;
+
+ region.for_va = rbuf;
+ ret = dat_lmr_create(h_ia,
+ DAT_MEM_TYPE_VIRTUAL,
+ region,
+ connections * rx_buf_len * burst_size,
+ h_pz,
+ DAT_MEM_PRIV_ALL_FLAG,
+ DAT_VA_TYPE_VA,
+ &h_lmr_recv,
+ &lmr_context_recv,
+ &rmr_context_recv,
+ ®istered_size_recv, ®istered_addr_recv);
+
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error registering Receive RDMA buffer: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Registered RCV RDMA Buffer %p\n", region.for_va);
+ }
+
+ /* Register RDMA Send buffer */
+ region.for_va = sbuf;
+ ret = dat_lmr_create(h_ia,
+ DAT_MEM_TYPE_VIRTUAL,
+ region,
+ connections * tx_buf_len * burst_size,
+ h_pz,
+ DAT_MEM_PRIV_ALL_FLAG,
+ DAT_VA_TYPE_VA,
+ &h_lmr_send,
+ &lmr_context_send,
+ &rmr_context_send,
+ ®istered_size_send, ®istered_addr_send);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr, " Error registering send RDMA buffer: %s\n",
+ DT_RetToString(ret));
+ return (ret);
+ } else {
+ LOGPRINTF(" Registered Send RDMA Buffer %p\n", region.for_va);
+ }
+
+ return DAT_SUCCESS;
+}
+
+void unregister_rdma_memory()
+{
+ DAT_RETURN ret;
+
+ /* Unregister Send message Buffer */
+ if (h_lmr_send != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Unregister send message h_lmr %p \n", h_lmr_send);
+ ret = dat_lmr_free(h_lmr_send);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr,
+ " Error deregistering send msg mr: %s\n",
+ DT_RetToString(ret));
+ } else {
+ LOGPRINTF(" Unregistered send message Buffer\n");
+ h_lmr_send = NULL;
+ }
+ }
+
+ /* Unregister recv message Buffer */
+ if (h_lmr_recv != DAT_HANDLE_NULL) {
+ LOGPRINTF(" Unregister recv message h_lmr %p \n", h_lmr_recv);
+ ret = dat_lmr_free(h_lmr_recv);
+ if (ret != DAT_SUCCESS) {
+ fprintf(stderr,
+ " Error deregistering recv msg mr: %s\n",
+ DT_RetToString(ret));
+ } else {
+ LOGPRINTF(" Unregistered recv message Buffer\n");
+ h_lmr_recv = NULL;
+ }
+ }
+}
+
+DAT_RETURN send_msg(char *buff, char msg_head, DAT_UINT32 ep_num,
+ DAT_UINT32 msg_num)
+{
+ DAT_DTO_COOKIE cookie;
+ DAT_LMR_TRIPLET l_iov;
+
+ *buff = msg_head;
+ *((DAT_UINT32 *)(buff + 4)) = htonl(ep_num);
+ *((DAT_UINT32 *)(buff + 8)) = htonl(msg_num);
+
+ l_iov.lmr_context = lmr_context_send;
+#if defined(_WIN32)
+ l_iov.virtual_address = (DAT_VADDR) buff;
+#else
+ l_iov.virtual_address = (DAT_VADDR)(unsigned long)buff;
+#endif
+ l_iov.segment_length = tx_buf_len;
+
+ if (!ud_test) {
+ LOGPRINTF(" %s RC SEND, ep %d, msg num %d, buffer %p len=%d\n",
+ server ? "SERVER:" : "CLIENT:",
+ ep_num, msg_num, buff, tx_buf_len);
+
+ return dat_ep_post_send(h_ep[ep_num], 1, &l_iov, cookie,
+ DAT_COMPLETION_DEFAULT_FLAG);
+ } else {
+ /* UD section */
+ int ep_idx = (server ? ep_num : 0);
+ int ah_idx = (server ? 0 : ep_num);
+ LOGPRINTF(" %s UD SND, from ep %d to ep %d, msg num %d, buffer %p len %d\n",
+ server ? "SERVER:" : "CLIENT:",
+ ep_idx, ah_idx, msg_num, buff, tx_buf_len);
+ LOGPRINTF(" %s sending on ep=%p to remote_ah %p"
+ " qpn=0x%x addr=%s\n",
+ server ? "Server" : "Client", h_ep[ep_idx], remote_ah[ah_idx].ah,
+ remote_ah[ah_idx].qpn, inet_ntoa(((struct sockaddr_in *)
+ &remote_ah[ah_idx].ia_addr)->sin_addr));
+
+ /* client use all data in on first EP */
+ return dat_ib_post_send_ud(h_ep[ep_idx],
+ 1,
+ &l_iov,
+ &remote_ah[ah_idx],
+ cookie,
+ DAT_COMPLETION_DEFAULT_FLAG);
+ }
+}
+
+void print_usage(void)
+{
+ printf("\n DAPL SRQ USAGE \n\n");
+ printf("s: server\n");
+ printf("c: connections (default = 1, max = 100)\n");
+ printf("B: burst messages per connection (default = 1, max = 100)\n");
+ printf("t: bursts number per connection (default = 3)\n");
+ printf("b: buffer length to allocate (default DAT_IB_TRANSPORT_MTU)\n");
+ printf("v: verbose\n");
+ printf("h: hostname/address of server, specified on client\n");
+ printf("P: provider name (default = OpenIB-cma)\n");
+ printf("l: server lid (required ucm provider)\n");
+ printf("q: server qpn (required ucm provider)\n");
+ printf("u unreliable datagram test (default false)\n");
+ printf("S use SRQ (default = 1 = use SQR)\n");
+ printf("\n");
+}
--
1.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] dtestx: update IB extension example test with new v2.0.9 features
[not found] ` <1418668558-695-1-git-send-email-arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-12-15 18:35 ` [PATCH 1/3] common: add srq support for openib verbs providers arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 2/3] dtest: add dtestsrq for SRQ example and provider testing arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
@ 2014-12-15 18:35 ` arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2 siblings, 0 replies; 4+ messages in thread
From: arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w @ 2014-12-15 18:35 UTC (permalink / raw)
To: linux-rdma-u79uwXL29TY76Z2rM5mHXA; +Cc: Arlin Davis
From: Arlin Davis <arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Add support for new IB extensions for CM and AH resource cleanup.
Check for v2.0.9 and call dat_ib_ud_cm_free after connection
establishment and dat_ib_ud_ah_free after all data has been
transfered on UD endpoints.
Also add socket based address exchange to eliminate the need
to include lid and qpn parameters on the client side.
Change the multiple EP mode to send from EP 0 to EP[0-3] on
server side and EP[0-3] to EP[0-3] on client side.
Signed-off-by: Arlin Davis <arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
test/dtest/dtestx.c | 581 +++++++++++++++++++++++++++++++++++++++------------
1 files changed, 451 insertions(+), 130 deletions(-)
diff --git a/test/dtest/dtestx.c b/test/dtest/dtestx.c
index 32ffe33..8b3294a 100755
--- a/test/dtest/dtestx.c
+++ b/test/dtest/dtestx.c
@@ -60,7 +60,7 @@
#include <string.h>
#include <unistd.h>
-#define DAPL_PROVIDER "ofa-v2-ib0"
+#define DAPL_PROVIDER "ofa-v2-mlx4_0-1u"
#define F64x "%"PRIx64""
#define F64u "%"PRIu64""
@@ -144,6 +144,7 @@ int disconnect_ep(void);
#define SEND_BUF_INDEX 2
#define RECV_BUF_INDEX 3
#define MAX_EP_COUNT 8
+#define MAX_AH_COUNT (MAX_EP_COUNT * 2)
DAT_VADDR *atomic_buf;
DAT_LMR_HANDLE lmr_atomic;
@@ -174,16 +175,22 @@ int buf_size = BUF_SIZE;
int msg_size = sizeof(DAT_RMR_TRIPLET);
char provider[64] = DAPL_PROVIDER;
char hostname[256] = { 0 };
-DAT_IB_ADDR_HANDLE remote_ah[MAX_EP_COUNT];
+static DAT_IB_ADDR_HANDLE remote_ah[MAX_EP_COUNT][MAX_AH_COUNT];
int eps = 1;
int verbose = 0;
int counters = 0;
int counters_ok = 0;
static int ucm = 0;
static DAT_SOCK_ADDR6 remote;
+static DAT_IA_ATTR ia_attr;
+static DAT_PROVIDER_ATTR prov_attrs;
#define LOGPRINTF if (verbose) printf
+#define CONN_PORT 15828
+#define CONN_MSG_SIZE 128
+#define CONN_MSG_FMT "%04hx:%08x:%08x:%08x:%s"
+
void print_usage(void)
{
printf("\n dtestx usage \n\n");
@@ -196,7 +203,7 @@ void print_usage(void)
printf("h: hostname/address of Server, client and UDP server\n");
printf("c: Client\n");
printf("s: Server, default\n");
- printf("P: provider name (default = ofa-v2-ib0)\n");
+ printf("P: provider name (default = ofa-v2-mlx4_0-1u)\n");
printf("\n");
}
@@ -232,6 +239,265 @@ static void print_ia_address(struct sockaddr *sa)
}
}
+int conn_client_connect(const char *servername, int port)
+{
+
+ struct addrinfo *res, *t;
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM
+ };
+ char *service;
+ int n;
+ int sockfd = -1;
+
+ if (asprintf(&service, "%d", port) < 0)
+ return -1;
+
+ n = getaddrinfo(servername, service, &hints, &res);
+
+ if (n < 0) {
+ fprintf(stderr, "%s for %s:%d\n",
+ gai_strerror(n), servername, port);
+ return n;
+ }
+
+ for (t = res; t; t = t->ai_next) {
+ sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
+ if (sockfd >= 0) {
+ if (!connect(sockfd, t->ai_addr, t->ai_addrlen))
+ break;
+ close(sockfd);
+ sockfd = -1;
+ }
+ }
+
+ freeaddrinfo(res);
+
+ if (sockfd < 0) {
+ fprintf(stderr, "Couldn't connect to %s:%d\n",
+ servername, port);
+ return sockfd;
+ }
+ return sockfd;
+}
+
+int conn_server_connect(int port)
+{
+ struct addrinfo *res, *t;
+ struct addrinfo hints = {
+ .ai_flags = AI_PASSIVE,
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM
+ };
+ char *service;
+ int sockfd = -1, connfd;
+ int n;
+
+ if (asprintf(&service, "%d", port) < 0)
+ return -1;
+
+ n = getaddrinfo(NULL, service, &hints, &res);
+
+ if (n < 0) {
+ fprintf(stderr, "%s for port %d\n", gai_strerror(n), port);
+ return n;
+ }
+
+ for (t = res; t; t = t->ai_next) {
+ sockfd = socket(t->ai_family, t->ai_socktype, t->ai_protocol);
+ if (sockfd >= 0) {
+ n = 1;
+
+ setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &n,
+ sizeof n);
+
+ if (!bind(sockfd, t->ai_addr, t->ai_addrlen))
+ break;
+
+ close(sockfd);
+ sockfd = -1;
+ }
+ }
+
+ freeaddrinfo(res);
+
+ if (sockfd < 0) {
+ fprintf(stderr, "Couldn't listen to port %d\n", port);
+ return sockfd;
+ }
+
+ listen(sockfd, 1);
+ connfd = accept(sockfd, NULL, 0);
+ if (connfd < 0) {
+ perror("server accept");
+ fprintf(stderr, "accept() failed\n");
+ close(sockfd);
+ return connfd;
+ }
+
+ close(sockfd);
+ return connfd;
+}
+
+static int get_server_params(struct sockaddr *my_sa)
+{
+ int connfd, parsed;
+ in_port_t ser_lid = 0;
+ uint32_t scope_id = 0, ser_qpn = 0, ser_scope_id = 0, ser_sin_addr = 0;
+ struct in_addr sin_addr; /* Internet address. */
+ char msg[CONN_MSG_SIZE];
+
+ connfd = conn_client_connect(hostname, CONN_PORT);
+ if (connfd < 0) {
+ fprintf(stderr, "%d Could not connect to %s\n",
+ getpid(), hostname);
+ return -1;
+ }
+
+ if (read(connfd, msg, sizeof msg) != sizeof msg) {
+ fprintf(stderr, "%d Couldn't read remote address\n", getpid());
+ return -1;
+ }
+
+ parsed = sscanf(msg, CONN_MSG_FMT, &ser_lid, &ser_qpn, &ser_scope_id,
+ &ser_sin_addr, provider);
+
+ if (parsed != 5) {
+ fprintf(stderr, "%d Couldn't parse line <%.*s>\n",
+ getpid(), (int)sizeof msg, msg);
+ return -1;
+ }
+
+ if (ser_sin_addr) {
+ sin_addr.s_addr = ser_sin_addr;
+ inet_ntop(AF_INET, &sin_addr, hostname, INET6_ADDRSTRLEN);
+ LOGPRINTF("%d remote data: provider %s hostname %s\n",
+ getpid(), provider, hostname);
+ } else if (ser_lid && ser_qpn) {
+ remote.sin6_family = AF_INET6;
+ remote.sin6_port = ser_lid;
+ remote.sin6_flowinfo = ser_qpn;
+ remote.sin6_scope_id = ntohl(ser_scope_id);
+ ucm = 1;
+ LOGPRINTF("%d remote data: provider %s Client QPN 0x%x,"
+ " LID = 0x%x, scope_id 0x%x\n",
+ getpid(), provider, ntohl(ser_qpn), ntohs(ser_lid),
+ ntohl(ser_scope_id));
+ } else {
+ fprintf(stderr, "%d No valid data was received"
+ " from the server\n",
+ getpid());
+ return -1;
+ }
+
+ /* send client addr back to server */
+ if (my_sa->sa_family == AF_INET6) {
+ ser_qpn = ((struct sockaddr_in6 *)my_sa)->sin6_flowinfo;
+ ser_lid = ((struct sockaddr_in6 *)my_sa)->sin6_port;
+ scope_id = htonl(((struct sockaddr_in6 *)my_sa)->sin6_scope_id);
+ LOGPRINTF("%d Client data to server: provider %s QPN 0x%x LID"
+ " = 0x%x SCCOPE_ID 0x%x\n",
+ getpid(), provider, ntohl(ser_qpn), ntohs(ser_lid),
+ ntohl(scope_id));
+ } else if (my_sa->sa_family == AF_INET) {
+ ser_sin_addr = ((struct sockaddr_in *)my_sa)->sin_addr.s_addr;
+ LOGPRINTF("%d Server data to client: provider %s SIN_ADDR"
+ " 0x%x\n", getpid(), provider, ser_sin_addr);
+ }
+
+ sprintf(msg, CONN_MSG_FMT, ser_lid, ser_qpn, scope_id,
+ ser_sin_addr, provider);
+ if (write(connfd, msg, sizeof msg) != sizeof msg) {
+ fprintf(stderr, "%d Couldn't send data", getpid());
+ return -1;
+ }
+ return 0;
+}
+
+static int send_server_params(struct sockaddr *ser_sa)
+{
+ in_port_t ser_lid = 0;
+ uint32_t scope_id = 0, ser_qpn = 0, ser_scope_id = 0, ser_sin_addr = 0;
+ int parsed, connfd;
+ struct in_addr sin_addr; /* Internet address. */
+ char msg[CONN_MSG_SIZE];
+
+ if (!ser_sa) {
+ printf("%d no address\n", getpid());
+ return -1;
+ }
+
+ if (ser_sa->sa_family == AF_INET6) {
+ ser_qpn = ((struct sockaddr_in6 *)ser_sa)->sin6_flowinfo;
+ ser_lid = ((struct sockaddr_in6 *)ser_sa)->sin6_port;
+ scope_id =
+ htonl(((struct sockaddr_in6 *)ser_sa)->sin6_scope_id);
+ LOGPRINTF("%d Server data to client: provider %s QPN 0x%x LID"
+ " = 0x%x SCCOPE_ID 0x%x\n",
+ getpid(), provider, ntohl(ser_qpn), ntohs(ser_lid),
+ ntohl(scope_id));
+ } else if (ser_sa->sa_family == AF_INET) {
+ ser_sin_addr = ((struct sockaddr_in *)ser_sa)->sin_addr.s_addr;
+ LOGPRINTF("%d Server data to client: provider %s SIN_ADDR"
+ " 0x%x\n",
+ getpid(), provider, ser_sin_addr);
+ }
+
+ connfd = conn_server_connect(CONN_PORT);
+ if (connfd < 0) {
+ fprintf(stderr, "%d Failed to connect to client\n", getpid());
+ return -1;
+ }
+
+ sprintf(msg, CONN_MSG_FMT, ser_lid, ser_qpn, scope_id,
+ ser_sin_addr, provider);
+ if (write(connfd, msg, sizeof msg) != sizeof msg) {
+ fprintf(stderr, "%d Couldn't send data", getpid());
+ return -1;
+ }
+
+ ser_lid = ser_qpn = ser_scope_id = ser_sin_addr = 0;
+
+ /* get remote address from Client */
+ if (read(connfd, msg, sizeof msg) != sizeof msg) {
+ fprintf(stderr, "%d Couldn't read remote address\n", getpid());
+ return -1;
+ }
+
+ parsed = sscanf(msg, CONN_MSG_FMT, &ser_lid, &ser_qpn, &ser_scope_id,
+ &ser_sin_addr, provider);
+
+ if (parsed != 5) {
+ fprintf(stderr, "%d Couldn't parse line <%.*s>\n",
+ getpid(), (int)sizeof msg, msg);
+ return -1;
+ }
+
+ if (ser_sin_addr) {
+ sin_addr.s_addr = ser_sin_addr;
+ inet_ntop(AF_INET, &sin_addr, hostname, INET6_ADDRSTRLEN);
+ LOGPRINTF("%d remote data: provider %s hostname %s\n",
+ getpid(), provider, hostname);
+ } else if (ser_lid && ser_qpn) {
+ remote.sin6_family = AF_INET6;
+ remote.sin6_port = ser_lid;
+ remote.sin6_flowinfo = ser_qpn;
+ remote.sin6_scope_id = ntohl(ser_scope_id);
+ ucm = 1;
+ LOGPRINTF("%d remote data: provider %s Client QPN 0x%x,"
+ " LID = 0x%x, scope_id 0x%x\n",
+ getpid(), provider, ntohl(ser_qpn), ntohs(ser_lid),
+ ntohl(ser_scope_id));
+ } else {
+ fprintf(stderr, "%d No valid data was received"
+ " from the server\n",
+ getpid());
+ return -1;
+ }
+ return 0;
+}
+
void
send_msg(void *data,
DAT_COUNT size,
@@ -253,27 +519,28 @@ send_msg(void *data,
for (i = 0; i < eps; i++) {
if (ud_test) {
/*
- * Client and Server: ep[0] and ah[0] on single
- * and ep[i] on multiple (-m) endpoint options.
+ * single QP - ep[0] and ah[0] for client and server
+ * multi QP - ep[i]->ah[i] for client, to 0
+ * ep[0]->ah[i] for server, to all
*/
if (multi_eps) {
- ep_idx = i;
- ah_idx = server ? 0 : i;
+ ah_idx = i;
+ if (!server)
+ ep_idx = i;
}
- printf("%s sending on ep=%p to remote_ah: ah=%p"
- " qpn=0x%x addr=%s\n",
- server ? "Server" : "Client", ep[ep_idx],
- remote_ah[ah_idx].ah,
- remote_ah[ah_idx].qpn,
- inet_ntoa(((struct sockaddr_in *)
- &remote_ah[ah_idx].ia_addr)->
- sin_addr));
+
+ printf("%s send on ep=%p -> remote_ah[%d][%d]: ah=%p"
+ " qpn=0x%x\n",
+ server ? "Server" : "Client",
+ ep[ep_idx], ep_idx, ah_idx,
+ remote_ah[ep_idx][ah_idx].ah,
+ remote_ah[ep_idx][ah_idx].qpn);
/* client expects all data in on first EP */
status = dat_ib_post_send_ud(ep[ep_idx],
1,
&iov,
- &remote_ah[ah_idx],
+ &remote_ah[ep_idx][ah_idx],
cookie, flags);
} else {
@@ -356,9 +623,9 @@ void process_conn(int idx)
DAT_EVENT event;
DAT_COUNT nmore;
DAT_RETURN status;
- int pdata, exp_event;
+ int i, ep_r = 0, ep_l = 0, exp_event;
DAT_IB_EXTENSION_EVENT_DATA *ext_event = (DAT_IB_EXTENSION_EVENT_DATA *)
- & event.event_extension_data[0];
+ &event.event_extension_data[0];
DAT_CONNECTION_EVENT_DATA *conn_event =
&event.event_data.connect_event_data;
@@ -379,9 +646,7 @@ void process_conn(int idx)
exp_event = DAT_CONNECTION_EVENT_ESTABLISHED;
/* Waiting on CR's or CONN_EST */
- if (event.event_number != exp_event ||
- (ud_test && event.event_number !=
- DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED)) {
+ if (event.event_number != exp_event) {
printf("unexpected event, !conn established: 0x%x\n",
event.event_number);
exit(1);
@@ -391,39 +656,64 @@ void process_conn(int idx)
if (!ud_test)
return;
- /* store each remote_ah according to remote EP index */
- pdata = ntoh32(*((int *)conn_event->private_data));
- LOGPRINTF(" Client got private data=0x%x\n", pdata);
+ /* Initialize local EP index */
+ for (i=0;i<eps;i++) {
+ if (ep[i] == conn_event->ep_handle) {
+ ep_l = i;
+ break;
+ }
+ }
+
+ LOGPRINTF(" Client got private data: ep_idx = %d\n", ep_r);
- /* UD, get AH for sends.
+ /* UD, save AH for sends, active side only
* NOTE: bi-directional AH resolution results in a CONN_EST
* for both outbound connect and inbound CR.
- * Use Active CONN_EST which includes server's CR
- * pdata for remote_ah idx to send on and ignore PASSIVE CONN_EST.
+ * Active pdata includes remote_ah EP idx.
*
* DAT_IB_UD_PASSIVE_REMOTE_AH == passive side CONN_EST
* DAT_IB_UD_REMOTE_AH == active side CONN_EST
*/
if (ext_event->type == DAT_IB_UD_REMOTE_AH) {
- remote_ah[pdata] = ext_event->remote_ah;
- printf("remote_ah[%d]: ah=%p, qpn=0x%x "
- "addr=%s\n",
- pdata, remote_ah[pdata].ah,
- remote_ah[pdata].qpn, inet_ntoa(((struct sockaddr_in *)
- &remote_ah[pdata].
- ia_addr)->sin_addr));
-
- } else if (ext_event->type != DAT_IB_UD_PASSIVE_REMOTE_AH) {
- printf("unexpected UD ext_event type: 0x%x\n", ext_event->type);
+ ep_r = ntoh32(*((int *)conn_event->private_data));
+
+ /* AH exists for this remote EP, FREE if provider supports */
+ if (remote_ah[ep_l][ep_r].ah &&
+ ia_attr.extension_version >= 209)
+ dat_ib_ud_ah_free(ep[ep_l], &ext_event->remote_ah);
+ else
+ remote_ah[ep_l][ep_r] = ext_event->remote_ah;
+
+ printf("CONNECT EP_L[%d]=%p (%p) -> remote_ah[%d][%d]: ah=%p,"
+ "qpn=0x%x cm_ctx %p %lu\n",
+ ep_l, ep[ep_l], conn_event->ep_handle, ep_l, ep_r,
+ remote_ah[ep_l][ep_r].ah, remote_ah[ep_l][ep_r].qpn,
+ ext_event->context.as_ptr, sizeof(*ext_event));
+
+ } else if (ext_event->type == DAT_IB_UD_PASSIVE_REMOTE_AH) {
+ if (ia_attr.extension_version >= 209) {
+ LOGPRINTF("PASSIVE EP_L[%d]=%p -> remote_ah %p qpn %d"
+ " AH_FREE\n",
+ ep_l, ep[ep_l], ext_event->remote_ah.ah,
+ ext_event->remote_ah.qpn);
+ dat_ib_ud_ah_free(ep[ep_l], &ext_event->remote_ah);
+ }
+ } else {
+ printf("wrong UD ext_event type: 0x%x\n", ext_event->type);
exit(1);
}
+
+ if (ia_attr.extension_version >= 209) {
+ /* Destroy CM resources for AH resolution */
+ dat_ib_ud_cm_free(ep[ep_l], ext_event->context.as_ptr);
+ }
+
}
-int connect_ep(char *hostname)
+int connect_ep(char *hostname, struct sockaddr *ser_sa)
{
DAT_IA_ADDRESS_PTR remote_addr = (DAT_IA_ADDRESS_PTR)&remote;
DAT_EP_ATTR ep_attr;
- DAT_IA_ATTR ia_attr;
DAT_RETURN status;
DAT_REGION_DESCRIPTION region;
DAT_EVENT event;
@@ -434,40 +724,9 @@ int connect_ep(char *hostname)
DAT_CONN_QUAL conn_qual;
DAT_BOOLEAN in, out;
int i, ii, pdata, ctx;
- DAT_PROVIDER_ATTR prov_attrs;
DAT_DTO_COMPLETION_EVENT_DATA *dto_event =
&event.event_data.dto_completion_event_data;
- status = dat_ia_open(provider, 8, &async_evd, &ia);
- _OK(status, "dat_ia_open");
-
- memset(&prov_attrs, 0, sizeof(prov_attrs));
- status = dat_ia_query(ia, NULL,
- DAT_IA_FIELD_ALL, &ia_attr,
- DAT_PROVIDER_FIELD_ALL, &prov_attrs);
- _OK(status, "dat_ia_query");
-
- print_ia_address(ia_attr.ia_address_ptr);
-
- if (ucm && ud_test) {
- printf("%d UD test over UCM provider not supported\n",
- getpid());
- exit(1);
- }
-
- /* Print provider specific attributes */
- for (i = 0; i < prov_attrs.num_provider_specific_attr; i++) {
- LOGPRINTF(" Provider Specific Attribute[%d] %s=%s\n",
- i, prov_attrs.provider_specific_attr[i].name,
- prov_attrs.provider_specific_attr[i].value);
-
- /* check for counter support */
- status = strcmp(prov_attrs.provider_specific_attr[i].name,
- "DAT_COUNTERS");
- if (!status)
- counters_ok = 1;
- }
-
/* make sure provider supports counters */
if ((counters) && (!counters_ok)) {
printf("Disable dat_query_counters:"
@@ -561,13 +820,13 @@ int connect_ep(char *hostname)
cookie.as_64 = (ii * REG_MEM_COUNT) + i;
iov.lmr_context = lmr_context[(ii * REG_MEM_COUNT) + i];
iov.virtual_address =
- (DAT_VADDR) (uintptr_t) buf[(ii * REG_MEM_COUNT) +
- i];
+ (DAT_VADDR) (uintptr_t) buf[(ii * REG_MEM_COUNT) + i];
iov.segment_length = buf_size;
- LOGPRINTF(" post_recv (%p) on ep[%d]=%p\n",
- buf[(ii * REG_MEM_COUNT) + i], ii, ep[ii]);
- /* ep[0], unless testing Server and multi EP's */
- if (server && multi_eps) {
+ LOGPRINTF(" post_recv buf[%d]=(%p) on ep[%d]=%p\n",
+ (ii * REG_MEM_COUNT) + i,
+ buf[(ii * REG_MEM_COUNT) + i], ii, ep[ii]);
+ /* ep[0], unless multi EP's */
+ if (multi_eps) {
ep_idx = ii;
cookie.as_64 = i;
}
@@ -582,6 +841,15 @@ int connect_ep(char *hostname)
/* setup receive buffer to initial string to be overwritten */
strcpy((char *)buf[RCV_RDMA_BUF_INDEX], "blah, blah, blah\n");
+ if (server) {
+ /* Exchange info with client */
+ printf("%d Server - Client: waiting to snd addr\n", getpid());
+ if (send_server_params(ser_sa)) {
+ printf("%d Failed to send server params\n", getpid());
+ return -1;
+ }
+ }
+
/* ud can resolve_ah and connect both ways, same EP */
if (server || (!server && ud_test)) {
if (server) {
@@ -630,21 +898,31 @@ no_resolution:
* use private data to select EP on Server
*/
for (i = 0; i < eps; i++) {
+ int ep_l = 0;
+
/* pdata selects Server EP,
* support both muliple Server and single EP's
*/
- if (multi_eps)
+ if (multi_eps) {
+ if (!server)
+ ep_l = i;
pdata = hton32(i);
- else
+ } else
pdata = 0; /* just use first EP */
- status = dat_ep_connect(ep[0],
+ status = dat_ep_connect(ep[ep_l],
remote_addr,
(server ? CLIENT_ID :
SERVER_ID), CONN_TIMEOUT, 4,
- (DAT_PVOID) & pdata, 0,
+ (DAT_PVOID) &pdata, 0,
DAT_CONNECT_DEFAULT_FLAG);
_OK(status, "dat_ep_connect");
+
+ printf("%s EP_L[%d]=%p connect to EP_R[%d]\n",
+ server ? "Server" : "Client",
+ ep_l, ep[ep_l],
+ ntoh32(pdata));
+
}
if (!ucm)
@@ -700,7 +978,7 @@ no_resolution:
LOGPRINTF("Waiting for remote to send RMR data\n");
status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);
- _OK(status, "dat_evd_wait after dat_ep_post_send");
+ _OK(status, "dat_evd_wait for receive message");
if ((event.event_number != DAT_DTO_COMPLETION_EVENT) &&
(ud_test && event.event_number != DAT_IB_DTO_EVENT)) {
@@ -710,11 +988,11 @@ no_resolution:
}
_OK(dto_event->status, "event status for post_recv");
- /* careful when checking cookies:
- * Client - receiving multi messages on a single EP
- * Server - not receiving on multiple EP's
+ /*
+ * multi_eps - receive multi messages on single EP
+ * !mutli_eps - receive one message across multiple EPs
*/
- if (!server || (server && !multi_eps)) {
+ if (!multi_eps) {
if (dto_event->transfered_length != msg_size ||
dto_event->user_cookie.as_64 != ctx) {
printf("unexpected event data on recv: len=%d"
@@ -724,12 +1002,11 @@ no_resolution:
msg_size, ctx);
exit(1);
}
- /* Server - receiving one message each across many EP's */
} else {
if (dto_event->transfered_length != msg_size ||
dto_event->user_cookie.as_64 != RECV_BUF_INDEX) {
printf("unexpected event data on recv: len=%d"
- "cookie=" F64x " expected %d/%d\n",
+ " cookie=" F64x " expected %d/%d\n",
(int)dto_event->transfered_length,
dto_event->user_cookie.as_64,
msg_size, RECV_BUF_INDEX);
@@ -738,12 +1015,10 @@ no_resolution:
}
/* swap RMR,address info to host order */
- if (!server || (server && !multi_eps))
+ if (!multi_eps)
r_iov = (DAT_RMR_TRIPLET *) buf[ctx];
else
- r_iov =
- (DAT_RMR_TRIPLET *) buf[(i * REG_MEM_COUNT) +
- RECV_BUF_INDEX];
+ r_iov = (DAT_RMR_TRIPLET *) buf[((i * REG_MEM_COUNT) + RECV_BUF_INDEX)];
if (ud_test)
r_iov = (DAT_RMR_TRIPLET *) ((char *)r_iov + 40);
@@ -752,11 +1027,14 @@ no_resolution:
r_iov->virtual_address = ntoh64(r_iov->virtual_address);
r_iov->segment_length = ntoh32(r_iov->segment_length);
- printf("Recv RMR message: r_iov(%p):"
- " r_key_ctx=%x,va=" F64x ",len=0x%x on EP=%p\n",
+ printf("Recv RMR message: buf[%d] r_iov(%p):"
+ " r_key_ctx=%x,va=" F64x ","
+ " len=0x%x on EP=%p ck=" F64x " \n",
+ multi_eps ? ((i * REG_MEM_COUNT) + RECV_BUF_INDEX):ctx,
r_iov, r_iov->rmr_context,
r_iov->virtual_address,
- r_iov->segment_length, dto_event->ep_handle);
+ r_iov->segment_length, dto_event->ep_handle,
+ dto_event->user_cookie.as_64);
}
return (0);
}
@@ -766,7 +1044,7 @@ int disconnect_ep(void)
DAT_RETURN status;
DAT_EVENT event;
DAT_COUNT nmore;
- int i;
+ int i, ii;
if (counters) { /* examples of query and print */
int ii;
@@ -788,6 +1066,7 @@ int disconnect_ep(void)
&event, &nmore);
_OK(status, "dat_evd_wait");
}
+
if (psp) {
status = dat_psp_free(psp);
_OK2(status, "dat_psp_free");
@@ -813,6 +1092,22 @@ int disconnect_ep(void)
printf("\n");
dat_print_counters(ep[i], DCNT_EP_ALL_COUNTERS, 0);
}
+
+ /* free UD AH resources */
+ if (ia_attr.extension_version >= 209) {
+ for (ii = 0; ii < MAX_AH_COUNT; ii++) {
+ if (remote_ah[i][ii].ah) {
+ printf( "UD_AH_FREE on EP %p, AH EP[%d][%d]"
+ "ib_ah = %p\n",
+ ep[i], i, ii,
+ remote_ah[i][ii].ah);
+ dat_ib_ud_ah_free(ep[i],
+ &remote_ah[i][ii]);
+ }
+ remote_ah[i][ii].ah = NULL;
+ }
+ }
+
status = dat_ep_free(ep[i]);
_OK2(status, "dat_ep_free");
}
@@ -1242,12 +1537,14 @@ int do_fetch_add()
return (0);
}
+
int main(int argc, char **argv)
{
- int rc;
+ int i, rc;
+ DAT_RETURN status;
/* parse arguments */
- while ((rc = getopt(argc, argv, "csvumpU:h:b:P:q:l:")) != -1) {
+ while ((rc = getopt(argc, argv, "csvumpU:h:b:P:")) != -1) {
switch (rc) {
case 'u':
ud_test = 1;
@@ -1282,20 +1579,6 @@ int main(int argc, char **argv)
case 'v':
verbose = 1;
break;
- case 'q':
- /* map UCM qpn into AF_INET6 sin6_flowinfo */
- remote.sin6_family = AF_INET6;
- remote.sin6_flowinfo = htonl(strtol(optarg,NULL,0));
- ucm = 1;
- server = 0;
- break;
- case 'l':
- /* map UCM lid into AF_INET6 sin6_port */
- remote.sin6_family = AF_INET6;
- remote.sin6_port = htons(strtol(optarg,NULL,0));
- ucm = 1;
- server = 0;
- break;
default:
print_usage();
exit(-12);
@@ -1315,42 +1598,80 @@ int main(int argc, char **argv)
}
}
#endif
+ status = dat_ia_open(provider, 8, &async_evd, &ia);
+ _OK(status, "dat_ia_open");
+
+ memset(&prov_attrs, 0, sizeof(prov_attrs));
+ status = dat_ia_query(ia, NULL,
+ DAT_IA_FIELD_ALL, &ia_attr,
+ DAT_PROVIDER_FIELD_ALL, &prov_attrs);
+ _OK(status, "dat_ia_query");
+
+ if (ia_attr.extension_supported != DAT_EXTENSION_IB) {
+ printf("%d ERROR: IB extension not supported\n", getpid());
+ exit(1);
+ }
+
+ print_ia_address(ia_attr.ia_address_ptr);
+
+ /* Print provider specific attributes */
+ for (i = 0; i < prov_attrs.num_provider_specific_attr; i++) {
+ LOGPRINTF(" Provider Specific Attribute[%d] %s=%s\n",
+ i, prov_attrs.provider_specific_attr[i].name,
+ prov_attrs.provider_specific_attr[i].value);
+
+ rc = strcmp(prov_attrs.provider_specific_attr[i].name,
+ "DAT_COUNTERS");
+ if (!rc)
+ counters_ok = 1;
+ }
+
+
/* for non UD tests, -h is always client */
if (remote_host && !ud_test)
server = 0;
if (!server) {
- printf("\nRunning as Client - %s %s %d endpoint(s)\n",
- provider, ud_test ? "UD test" : "", eps);
+ printf("%d Client: waiting for server input\n", getpid());
+ if (get_server_params(ia_attr.ia_address_ptr)) {
+ printf("%d Failed to get server parameters\n",
+ getpid());
+ exit(1);
+ }
+ printf("\nRunning as Client - %s %s %d endpoint(s) v%d\n",
+ provider, ud_test ? "UD test" : "", eps,
+ ia_attr.extension_version);
} else {
- printf("\nRunning as Server - %s %s %d endpoint(s)\n",
- provider, ud_test ? "UD test" : "", eps);
+ printf("\nRunning as Server - %s %s %d endpoint(s) v%d\n",
+ provider, ud_test ? "UD test" : "", eps,
+ ia_attr.extension_version);
}
/*
* connect
*/
- if (connect_ep(hostname)) {
+ if (connect_ep(hostname, ia_attr.ia_address_ptr)) {
_WSACleanup();
exit(1);
}
- if (ud_test)
- goto bail;
- if (do_immediate()) {
- _WSACleanup();
- exit(1);
- }
- if (do_cmp_swap()) {
- _WSACleanup();
- exit(1);
- }
- if (do_fetch_add()) {
- _WSACleanup();
- exit(1);
+ if (!ud_test) {
+ if (do_immediate()) {
+ _WSACleanup();
+ exit(1);
+ }
+ if (do_cmp_swap()) {
+ _WSACleanup();
+ exit(1);
+ }
+ if (do_fetch_add()) {
+ _WSACleanup();
+ exit(1);
+ }
}
- bail:
+
rc = disconnect_ep();
+ dat_ia_close(ia, DAT_CLOSE_DEFAULT);
_WSACleanup();
if (!rc)
--
1.7.3
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-12-15 18:35 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-15 18:35 [PATCH 0/3] DAPL: SRQ support for ofa providers arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
[not found] ` <1418668558-695-1-git-send-email-arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2014-12-15 18:35 ` [PATCH 1/3] common: add srq support for openib verbs providers arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 2/3] dtest: add dtestsrq for SRQ example and provider testing arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
2014-12-15 18:35 ` [PATCH 3/3] dtestx: update IB extension example test with new v2.0.9 features arlin.r.davis-ral2JQCrhuEAvxtiuMwx3w
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox