]> git.openfabrics.org - ~ardavis/dapl.git/commitdiff
Added IB extensions and dtestx as an example program using
authorArlin Davis <arlin.r.davis@intel.com>
Thu, 3 May 2007 00:27:44 +0000 (17:27 -0700)
committerArlin Davis <arlin.r.davis@intel.com>
Thu, 3 May 2007 00:27:44 +0000 (17:27 -0700)
rdma write with immediate and atomic operations

15 files changed:
Makefile.am
configure.in
dapl/openib_cma/dapl_ib_extensions.c [new file with mode: 0755]
dapl/udapl/libdaplcma.map [changed mode: 0644->0755]
dapl/udapl/linux/dapl_osd.h
dat/common/dat_api.c [changed mode: 0644->0755]
dat/common/dat_sr.c [changed mode: 0644->0755]
dat/include/dat/dat.h [changed mode: 0644->0755]
dat/include/dat/dat_redirection.h [changed mode: 0644->0755]
dat/include/dat/udat.h [changed mode: 0644->0755]
dat/include/dat/udat_redirection.h [changed mode: 0644->0755]
dat/udat/libdat.map [changed mode: 0644->0755]
dat/udat/udat.c [changed mode: 0644->0755]
test/dtest/Makefile.am
test/dtest/dtestx.c [new file with mode: 0755]

index ccb874454e60069eff6c802de7a0874040bf8f69..e8dc066c45d02b52d894439df96ebc26ccd3e7f1 100644 (file)
@@ -2,10 +2,13 @@
 
 OSFLAGS = -DOS_RELEASE=$(shell expr `uname -r | cut -f1 -d.` \* 65536 + `uname -r | cut -f2 -d.`)
 # Check for RedHat, needed for ia64 udapl atomic operations (IA64_FETCHADD syntax)
-if OS_RHEL
+# and built-in atomics for RedHat EL5
+if OS_RHEL4
 OSFLAGS += -DREDHAT_EL4
-else
-OSFLAGS +=
+endif
+
+if OS_RHEL5
+OSFLAGS += -DREDHAT_EL5
 endif
 
 if EXT_TYPE_IB
@@ -167,7 +170,8 @@ dapl_udapl_libdaplcma_la_SOURCES = dapl/udapl/dapl_init.c \
        dapl/openib_cma/dapl_ib_cq.c                \
        dapl/openib_cma/dapl_ib_qp.c                \
        dapl/openib_cma/dapl_ib_cm.c                \
-        dapl/openib_cma/dapl_ib_mem.c               
+        dapl/openib_cma/dapl_ib_mem.c               \
+        dapl/openib_cma/dapl_ib_extensions.c
 
 dapl_udapl_libdaplcma_la_LDFLAGS = -version-info 2:0:0 $(daplcma_version_script) \
                                   -Wl,-init,dapl_init -Wl,-fini,dapl_fini \
index 972bd3706a8aed3393cb9b6f6518bc441f6e2958..7608e643d9a60f01ed5272bacb7e3a109d68e9f1 100644 (file)
@@ -66,15 +66,25 @@ AC_ARG_ENABLE(ext-type,
  ])
 AM_CONDITIONAL(EXT_TYPE_IB, test "$ext_type" = "ib")
 
-dnl Check for Redhat EL release 
-AC_CACHE_CHECK(whether this is an RHEL system, ac_cv_rhel,
-    if test -f /etc/redhat-release && 
-       test -n "`grep -v Fedora /etc/redhat-release`"; then
-        ac_cv_rhel=yes
+dnl Check for Redhat EL release 4
+AC_CACHE_CHECK(Check for RHEL4 system, ac_cv_rhel4,
+    if test -f /etc/redhat-release &&
+       test -n "`grep -e "release 4" /etc/redhat-release`"; then
+        ac_cv_rhel4=yes
     else
-        ac_cv_rhel=no
+        ac_cv_rhel4=no
     fi)
-AM_CONDITIONAL(OS_RHEL, test "$ac_cv_rhel" = "yes")
+AM_CONDITIONAL(OS_RHEL4, test "$ac_cv_rhel4" = "yes")
+
+dnl Check for Redhat EL release 5
+AC_CACHE_CHECK(Check for RHEL5 system, ac_cv_rhel5,
+    if test -f /etc/redhat-release &&
+       test -n "`grep -e "release 5" /etc/redhat-release`"; then
+        ac_cv_rhel5=yes
+    else
+        ac_cv_rhel5=no
+    fi)
+AM_CONDITIONAL(OS_RHEL5, test "$ac_cv_rhel5" = "yes")
 
 AC_CONFIG_FILES([Makefile test/dtest/Makefile test/dapltest/Makefile libdat.spec])
 
diff --git a/dapl/openib_cma/dapl_ib_extensions.c b/dapl/openib_cma/dapl_ib_extensions.c
new file mode 100755 (executable)
index 0000000..6c298fb
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+/**********************************************************************
+ * 
+ * MODULE: dapl_ib_extensions.c
+ *
+ * PURPOSE:  Extensions routines for OpenIB uCMA provider
+ *
+ * $Id: $
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_ib_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_cookie.h"
+#include <stdarg.h>
+
+
+DAT_RETURN
+dapli_post_ext( IN       DAT_EP_HANDLE         ep_handle,
+               IN       DAT_UINT64             cmp_add,        
+               IN       DAT_UINT64             swap,
+               IN       DAT_UINT32             immed_data,
+               IN       DAT_COUNT              segments,
+               IN       DAT_LMR_TRIPLET        *local_iov,
+               IN       DAT_DTO_COOKIE         user_cookie,
+               IN const DAT_RMR_TRIPLET        *remote_iov,
+               IN       int                    op_type, 
+               IN       DAT_COMPLETION_FLAGS   flags );
+
+
+/*
+ * dapl_extensions
+ *
+ * Process extension requests
+ *
+ * Input:
+ *     ext_type,
+ *     ...
+ *
+ * Output:
+ *     Depends....
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_NOT_IMPLEMENTED
+ *      .....
+ *
+ */
+DAT_RETURN
+dapl_extensions(IN DAT_HANDLE  dat_handle, 
+               IN DAT_IB_OP    ext_op, 
+               IN va_list      args)
+{
+       DAT_EP_HANDLE           ep;
+       DAT_LMR_TRIPLET         *lmr_p;
+       DAT_DTO_COOKIE          cookie;
+       const DAT_RMR_TRIPLET   *rmr_p;
+       DAT_UINT64              dat_uint64a, dat_uint64b;
+       DAT_UINT32              dat_uint32;
+       DAT_COUNT               segments = 1;
+       DAT_COMPLETION_FLAGS    comp_flags;
+       DAT_RETURN              status = DAT_NOT_IMPLEMENTED;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_API,
+                    "dapl_extensions(hdl %p operation %d, ...)\n",
+                    dat_handle, ext_op);
+
+       DAPL_CNTR(DCNT_EXTENSION);
+
+       switch ((int)ext_op)
+       {
+       
+       case DAT_IB_RDMA_WRITE_IMMED_OP:
+               dapl_dbg_log(DAPL_DBG_TYPE_RTN, 
+                            " WRITE_IMMED_DATA extension call\n");
+               
+               ep          = dat_handle;                /* ep_handle */
+               segments    = va_arg( args, DAT_COUNT);  /* num segments */
+               lmr_p       = va_arg( args, DAT_LMR_TRIPLET*);  
+               cookie      = va_arg( args, DAT_DTO_COOKIE);
+               rmr_p       = va_arg( args, const DAT_RMR_TRIPLET*); 
+               dat_uint32  = va_arg( args, DAT_UINT32); /* immed data */
+               comp_flags  = va_arg( args, DAT_COMPLETION_FLAGS);   
+               
+               status = dapli_post_ext(ep, 0, 0, dat_uint32, segments, lmr_p,
+                                       cookie, rmr_p, OP_RDMA_WRITE_IMM,
+                                       comp_flags );
+               break;
+
+       case DAT_IB_CMP_AND_SWAP_OP:
+               dapl_dbg_log(DAPL_DBG_TYPE_RTN, 
+                            " CMP_AND_SWAP extension call\n");
+
+               ep          = dat_handle;               /* ep_handle */
+               dat_uint64a = va_arg( args, DAT_UINT64); /* cmp_value */
+               dat_uint64b = va_arg( args, DAT_UINT64); /* swap_value */
+               lmr_p       = va_arg( args, DAT_LMR_TRIPLET*); 
+               cookie      = va_arg( args, DAT_DTO_COOKIE);  
+               rmr_p       = va_arg( args, const DAT_RMR_TRIPLET*);
+               comp_flags  = va_arg( args, DAT_COMPLETION_FLAGS);
+
+               status = dapli_post_ext(ep, dat_uint64a, dat_uint64b,
+                                       0, segments, lmr_p, cookie, rmr_p, 
+                                       OP_COMP_AND_SWAP, comp_flags );
+               break;
+
+       case DAT_IB_FETCH_AND_ADD_OP:
+               dapl_dbg_log(DAPL_DBG_TYPE_RTN, 
+                            " FETCH_AND_ADD extension call\n");
+               
+               ep          = dat_handle;               /* ep_handle */
+               dat_uint64a = va_arg( args, DAT_UINT64); /* add value */
+               lmr_p       = va_arg( args, DAT_LMR_TRIPLET*);  
+               cookie      = va_arg( args, DAT_DTO_COOKIE);
+               rmr_p       = va_arg( args, const DAT_RMR_TRIPLET*); 
+               comp_flags  = va_arg( args, DAT_COMPLETION_FLAGS);   
+               
+               status = dapli_post_ext(ep, dat_uint64a, 0, 0, segments, 
+                                       lmr_p, cookie, rmr_p, 
+                                       OP_FETCH_AND_ADD, comp_flags );
+
+               break;
+
+       default:
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR, 
+                            "unsupported extension(%d)\n", (int)ext_op);
+       }
+       
+       return(status);
+}
+
+
+DAT_RETURN
+dapli_post_ext( IN       DAT_EP_HANDLE         ep_handle,
+               IN       DAT_UINT64             cmp_add,        
+               IN       DAT_UINT64             swap,
+               IN       DAT_UINT32             immed_data,
+               IN       DAT_COUNT              segments,
+               IN       DAT_LMR_TRIPLET        *local_iov,
+               IN       DAT_DTO_COOKIE         user_cookie,
+               IN const DAT_RMR_TRIPLET        *remote_iov,
+               IN       int                    op_type, 
+               IN       DAT_COMPLETION_FLAGS   flags )
+{
+       DAPL_EP         *ep_ptr;
+       ib_qp_handle_t  qp_ptr;
+       DAPL_COOKIE     *cookie;
+       DAT_RETURN      dat_status = DAT_SUCCESS;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_API,
+                    " post_ext_op: ep %p cmp_val %d "
+                    "swap_val %d cookie 0x%x, r_iov %p, flags 0x%x\n",
+                    ep_handle, (unsigned)cmp_add, (unsigned)swap, 
+                    (unsigned)user_cookie.as_64, remote_iov, flags);
+
+       if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP))
+               return(DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP));
+
+       if ((NULL == remote_iov) || (NULL == local_iov))
+               return DAT_INVALID_PARAMETER;
+
+       ep_ptr = (DAPL_EP *) ep_handle;
+       qp_ptr = ep_ptr->qp_handle;
+
+       /*
+        * Synchronization ok since this buffer is only used for send
+        * requests, which aren't allowed to race with each other.
+        * only if completion is expected
+        */
+       if (!(DAT_COMPLETION_SUPPRESS_FLAG & flags)) {
+
+               dat_status = dapls_dto_cookie_alloc(
+                                               &ep_ptr->req_buffer,
+                                               DAPL_COOKIE_TYPE_EXTENSION,
+                                               user_cookie,
+                                               &cookie );
+
+               if ( dat_status != DAT_SUCCESS )
+                       goto bail;
+               
+               /*
+                * Take reference before posting to avoid race conditions with
+                * completions
+                */
+               dapl_os_atomic_inc(&ep_ptr->req_count);
+       }
+
+       /*
+        * Invoke provider specific routine to post DTO
+        */
+       dat_status = dapls_ib_post_ext_send(ep_ptr,     
+                                           op_type,
+                                           cookie,     
+                                           segments,   /* data segments */
+                                           local_iov, 
+                                           remote_iov,
+                                           immed_data, /* immed data */
+                                           cmp_add,    /* compare or add */
+                                           swap,       /* swap */
+                                           flags);
+
+       if (dat_status != DAT_SUCCESS) {
+               if ( cookie != NULL ) {
+                       dapl_os_atomic_dec(&ep_ptr->req_count);
+                       dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
+               }
+       }
+
+bail:
+       return dat_status;
+
+}
+
+
+/* 
+ * New provider routine to process extended DTO events 
+ */
+void
+dapls_cqe_to_event_extension(IN DAPL_EP                        *ep_ptr,
+                            IN DAPL_COOKIE             *cookie,
+                            IN ib_work_completion_t    *cqe_ptr,
+                            IN DAT_EVENT               *event_ptr)
+{
+       uint32_t ibtype;
+       DAT_DTO_COMPLETION_EVENT_DATA *dto = 
+                       &event_ptr->event_data.dto_completion_event_data;
+       DAT_IB_EXTENSION_EVENT_DATA *ext_data = 
+                       (DAT_IB_EXTENSION_EVENT_DATA *)
+                       &event_ptr->event_extension_data[0];
+       DAT_DTO_COMPLETION_STATUS dto_status;
+
+       /* Get status from cqe */
+        dto_status = dapls_ib_get_dto_status(cqe_ptr);
+       
+       dapl_dbg_log(DAPL_DBG_TYPE_EVD,
+                    " cqe_to_event_ext: dto_ptr %p ext_ptr %p\n",
+                    dto, ext_data);
+
+       event_ptr->event_number = DAT_IB_DTO_EVENT;
+       dto->ep_handle = cookie->ep;
+       dto->user_cookie = cookie->val.dto.cookie;
+       dto->operation = DAPL_GET_CQE_DTOS_OPTYPE(cqe_ptr); /* new for 2.0 */
+       dto->status = ext_data->status = dto_status;
+
+       if (dto_status != DAT_DTO_SUCCESS)
+               return;
+       
+       /* 
+        * Get operation type from CQ work completion entry and
+        * if extented operation then set extended event data
+         */
+       ibtype = DAPL_GET_CQE_OPTYPE(cqe_ptr);
+        
+       switch (ibtype) {
+
+       case OP_RDMA_WRITE_IMM:
+               dapl_dbg_log (DAPL_DBG_TYPE_EVD,
+                                " cqe_to_event_ext: OP_RDMA_WRITE_IMMED\n");
+               
+               /* type and outbound rdma write transfer size */
+               dto->transfered_length = cookie->val.dto.size;
+               ext_data->type = DAT_IB_RDMA_WRITE_IMMED;
+               break;
+       case OP_RECEIVE_IMM:
+               dapl_dbg_log (DAPL_DBG_TYPE_EVD,
+                                " cqe_to_event_ext: OP_RECEIVE_RDMA_IMMED\n");
+               
+               /* immed recvd, type and inbound rdma write transfer size */
+               dto->transfered_length = DAPL_GET_CQE_BYTESNUM(cqe_ptr);
+               ext_data->type = DAT_IB_RDMA_WRITE_IMMED_DATA;
+               ext_data->val.immed.data = DAPL_GET_CQE_IMMED_DATA(cqe_ptr);
+               break;
+       case OP_COMP_AND_SWAP:
+                dapl_dbg_log (DAPL_DBG_TYPE_EVD,
+                                " cqe_to_event_ext: COMP_AND_SWAP_RESP\n");
+
+                /* original data is returned in LMR provided with post */
+               ext_data->type = DAT_IB_CMP_AND_SWAP;
+               dto->transfered_length = DAPL_GET_CQE_BYTESNUM(cqe_ptr);
+               break;
+       case OP_FETCH_AND_ADD:
+                dapl_dbg_log (DAPL_DBG_TYPE_EVD,
+                                " cqe_to_event_ext: FETCH_AND_ADD_RESP\n");
+
+               /* original data is returned in LMR provided with post */
+               ext_data->type = DAT_IB_FETCH_AND_ADD;
+               dto->transfered_length = DAPL_GET_CQE_BYTESNUM(cqe_ptr);
+               break;
+       default:
+               /* not extended operation */
+               ext_data->status = DAT_IB_OP_ERR;
+               dto->status = DAT_DTO_ERR_TRANSPORT;
+               break;
+       }
+}
old mode 100644 (file)
new mode 100755 (executable)
index f97dfac..68c5f4a
@@ -1,4 +1,4 @@
-DAPL_CMA_1.2 {
+DAPL_CMA_2.0 {
         global:
                dat_provider_fini;
                dat_provider_init;
index efa967dac188efad1c8f1b273d79a2146e122114..cfc85d1473b36cb292769fceeb12b89fcefeef45 100644 (file)
@@ -78,7 +78,7 @@
 #include <sys/socket.h>
 #include <ctype.h>
 
-#if defined(__ia64__) || defined(__PPC64__)
+#if !defined(REDHAT_EL5) && (defined(__ia64__) || defined(__PPC64__))
 #include <asm/atomic.h>
 #endif
 #if defined(__PPC64__)
@@ -155,14 +155,14 @@ dapl_os_atomic_inc (
        INOUT   DAPL_ATOMIC *v)
 {
 #ifdef __ia64__
-    DAT_COUNT  old_value;
-
-#   if !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))
+       DAT_COUNT       old_value;
+#if defined(REDHAT_EL5)
+       old_value = __sync_fetch_and_add(v, 1); 
+#elif !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))
        IA64_FETCHADD(old_value,v,1,4,rel);
-#   else
+#else
        IA64_FETCHADD(old_value,v,1,4);
-#   endif
-
+#endif
 #elif defined(__PPC64__)
    atomic_inc((atomic_t *) v);
 #else  /* !__ia64__ */
@@ -185,14 +185,14 @@ dapl_os_atomic_dec (
        INOUT   DAPL_ATOMIC *v)
 {
 #ifdef __ia64__
-    DAT_COUNT  old_value;
-
-#   if !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))
+       DAT_COUNT       old_value;
+#if defined(REDHAT_EL5)
+       old_value = __sync_fetch_and_sub(v, 1); 
+#elif !defined(REDHAT_EL4) && (OS_RELEASE >= LINUX_VERSION(2,6))
        IA64_FETCHADD(old_value,v,-1,4,rel);
-#   else
+#else
        IA64_FETCHADD(old_value,v,-1,4);
-#   endif
-
+#endif
 #elif defined (__PPC64__)
    atomic_dec((atomic_t *)v);
 
@@ -233,7 +233,9 @@ dapl_os_atomic_assign (
      */
 
 #ifdef __ia64__
-#ifdef REDHAT_EL4
+#if defined(REDHAT_EL5)
+    current_value = __sync_val_compare_and_swap(v,match_value,new_value); 
+#elif defined(REDHAT_EL4) 
     current_value = ia64_cmpxchg("acq",v,match_value,new_value,4);
 #else
     current_value = ia64_cmpxchg(acq,v,match_value,new_value,4);
old mode 100644 (file)
new mode 100755 (executable)
index d04b1d9..4b98da5
@@ -1269,6 +1269,33 @@ DAT_RETURN dat_srq_set_lw(
                           low_watermark);
 }
 
+#ifdef DAT_EXTENSIONS\r
+extern int g_dat_extensions;\r
+DAT_RETURN dat_extension_op(\r
+        IN      DAT_HANDLE              handle,\r
+        IN      DAT_EXTENDED_OP         ext_op,\r
+        IN      ... )\r
+\r
+{\r
+     DAT_RETURN status;\r
+     va_list args;\r
+\r
+     /* verify provider extension support */\r
+     if (!g_dat_extensions)\r
+     {\r
+        return DAT_ERROR(DAT_NOT_IMPLEMENTED, 0);\r
+     }\r
+   \r
+     /* extension will validate the handle based on op */\r
+     va_start(args, ext_op);\r
+     status = DAT_HANDLE_EXTENDEDOP(handle, ext_op, args);\r
+     va_end(args);\r
+\r
+     return status;\r
+}\r
+#endif\r
+
+
 /*
  * Local variables:
  *  c-indent-level: 4
old mode 100644 (file)
new mode 100755 (executable)
index 9568ab9..f62f16b
@@ -348,6 +348,7 @@ dat_sr_provider_open (
 {
     DAT_RETURN                         status;
     DAT_SR_ENTRY               *data;
+    void                       *fncptr;
 
     dat_os_lock (&g_sr_lock);
 
@@ -380,6 +381,33 @@ dat_sr_provider_open (
                    data->fini_func = dat_os_library_sym (data->lib_handle,
                                                          DAT_PROVIDER_FINI_FUNC_STR);
 
+                    /* Check DAT and DAPL libraries for extension compatibility */\r
+                    fncptr = dat_os_library_sym(data->lib_handle,\r
+                                                "dapl_extensions");\r
+\r
+                    if (dlerror() != NULL) {\r
+                            dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,\r
+                                  "DAT Registry: IA %s, library %s, "\r
+                                  "dlsym check for extensions failed\n",\r
+                                  data->info.ia_name, data->lib_path);\r
+                            status = DAT_MODEL_NOT_SUPPORTED;\r
+                    }\r
+
+#ifdef DAT_EXTENSIONS\r
+                    if (fncptr == NULL) {\r
+                        dat_os_dbg_print(DAT_OS_DBG_TYPE_ERROR,\r
+                                        "DAT Registry: expected"\r
+                                        " uDAPL with DAT_EXTENSIONS\n");\r
+#else\r
+                    if (fncptr != NULL) {\r
+                        dat_os_dbg_print(DAT_OS_DBG_TYPE_ERROR,\r
+                                        "DAT Registry: expected"\r
+                                        " uDAPL without DAT_EXTENSIONS\n");\r
+#endif\r
+                        status = DAT_MODEL_NOT_SUPPORTED;\r
+                        break;\r
+                    }\r
+
                    if ( NULL != data->init_func )
                    {
                        (*data->init_func) (&data->info, data->ia_params);
old mode 100644 (file)
new mode 100755 (executable)
index 53b2dd5..890d7ed
@@ -401,16 +401,13 @@ typedef enum dat_ep_creator_for_psp
 /* To support backwards compatibility for DAPL-1.0 & DAPL-1.1 */
 #define max_mtu_size max_message_size
 
-#ifdef DAT_EXTENSIONS
-/* DAPL 2.0 addition */
-/* Defines extensions */
+/* Query for provider IA extension support */
 typedef enum dat_extension
 {
        DAT_EXTENSION_IB,  /* IB extension.           */
        DAT_EXTENSION_IW,  /* iWARP extension.        */
        DAT_EXTENSION_NONE /* no extension supported. */
 } DAT_EXTENSION;
-#endif /* DAT_EXTENSIONS */
 
 typedef struct dat_ia_attr DAT_IA_ATTR;
 
@@ -451,6 +448,7 @@ typedef DAT_UINT64 DAT_IA_ATTR_MASK;
 #define DAT_IA_FIELD_IA_MAX_RDMA_READ_PER_EP_IN_GUARANTEED  UINT64_C(0x020000000)
 #define DAT_IA_FIELD_IA_MAX_RDMA_READ_PER_EP_OUT_GUARANTEED UINT64_C(0x040000000)
 #define DAT_IA_FIELD_IA_ZB_SUPPORTED                   UINT64_C(0x080000000)
+#define DAT_IA_FIELD_IA_EXTENSIONS_SUPPORTED           UINT64_C(0x100000000)
 
 /* To support backwards compatibility for DAPL-1.0 & DAPL-1.1 */
 #define DAT_IA_ALL                                      DAT_IA_FIELD_ALL
old mode 100644 (file)
new mode 100755 (executable)
index e8d5af2..02b64c7
@@ -466,13 +466,12 @@ typedef struct dat_provider DAT_PROVIDER;
        (name), \
        (answer))
 
-#ifdef DAT_EXTENSIONS
-        /* generic extended op */
-#define DAT_HANDLE_EXTENDEDOP (handle,op,args) \
-                       (*DAT_HANDLE_TO_PROVIDER(handle)->extendedop_func) (\
-       (handle), \
-       (op),   \
-       (args))
+#ifdef DAT_EXTENSIONS\r
+#define DAT_HANDLE_EXTENDEDOP(handle, op, args) \\r
+       (*DAT_HANDLE_TO_PROVIDER (handle)->handle_extendedop_func) (\\r
+               (handle), \\r
+               (op), \\r
+               (args))\r
 #endif
 
 /***************************************************************
@@ -848,12 +847,12 @@ typedef DAT_RETURN (*DAT_IA_HA_RELATED_FUNC) (
        IN const DAT_NAME_PTR, /* provider             */
        OUT     DAT_BOOLEAN *);         /* answer */
 
-#ifdef DAT_EXTENSIONS
-#include <stdarg.h>
-typedef DAT_RETURN (*DAT_HANDLE_EXTENDEDOP_FUNC) (
-       IN      DAT_HANDLE,             /* handle */
-       IN      DAT_EXTENDED_OP,        /* extended op */
-       IN      va_list );              /* arguments list */
+#ifdef DAT_EXTENSIONS  \r
+#include <stdarg.h>\r
+typedef DAT_RETURN (*DAT_HANDLE_EXTENDEDOP_FUNC)(\r
+       IN      DAT_HANDLE,             /* handle */\r
+       IN      DAT_EXTENDED_OP,        /* extended op */\r
+       IN      va_list);               /* argument list */\r
 #endif /* DAT_EXTENSIONS */
 
 #endif /* _DAT_REDIRECTION_H_ */
old mode 100644 (file)
new mode 100755 (executable)
index 569b702..4c140f3
@@ -292,20 +292,17 @@ struct dat_ia_attr
        DAT_BOOLEAN                 max_rdma_read_per_ep_in_guaranteed;
        DAT_BOOLEAN                 max_rdma_read_per_ep_out_guaranteed;
        DAT_BOOLEAN                 zb_supported;
-#ifdef DAT_EXTENSIONS
        DAT_EXTENSION               extension_supported;
        DAT_COUNT                   extension_version;
-#endif /* DAT_EXTENSIONS */
        DAT_COUNT                   num_transport_attr;
        DAT_NAMED_ATTR              *transport_attr;
        DAT_COUNT                   num_vendor_attr;
        DAT_NAMED_ATTR              *vendor_attr;
 };
 
-#ifdef DAT_EXTENSIONS
+
 #define DAT_IA_FIELD_IA_EXTENSION                       UINT64_C(0x100000000)
 #define DAT_IA_FIELD_IA_EXTENSION_VERSION               UINT64_C(0x200000000)
-#endif /* DAT_EXTENSIONS */
 
 #define DAT_IA_FIELD_IA_NUM_TRANSPORT_ATTR               UINT64_C(0x400000000)
 #define DAT_IA_FIELD_IA_TRANSPORT_ATTR                   UINT64_C(0x800000000)
old mode 100644 (file)
new mode 100755 (executable)
index 764ede9..9f12fe0
@@ -348,9 +348,9 @@ struct dat_provider
 
        DAT_IA_HA_RELATED_FUNC                  ia_ha_related_func;
 
-#ifdef DAT_EXTENSIONS
-       DAT_HANDLE_EXTENDEDOP_FUNC              handle_extendedop_func;
-#endif
+#ifdef DAT_EXTENSIONS\r
+    DAT_HANDLE_EXTENDEDOP_FUNC         handle_extendedop_func;\r
+#endif /* DAT_EXTENSIONS */
 };
 
 #endif /* _UDAT_REDIRECTION_H_ */
old mode 100644 (file)
new mode 100755 (executable)
index 89caca3..3ab4e0c
@@ -1,4 +1,4 @@
-DAT_1.2 {
+DAT_2.0 {
         global:
                dat_cno_create;
                dat_cno_free;
@@ -73,5 +73,6 @@ DAT_1.2 {
                dat_srq_set_lw;
                dats_get_ia_handle;
                dat_strerror;
+               dat_extension_op;
        local: *;
 };
old mode 100644 (file)
new mode 100755 (executable)
index e458441..4998c13
@@ -65,8 +65,12 @@ udat_check_state ( void );
  * External Function Definitions                                     *
  *                                                                   *
  *********************************************************************/
-
-
+\r
+/*\r
+ *  Use a global to get an unresolved when run with pre-extension library\r
+ */\r
+int g_dat_extensions = 0;\r
+\r
 /*
  *
  * Provider API
@@ -239,6 +243,42 @@ dat_ia_openv (
        }
     }
 
+    /*\r
+     *  See if provider supports extensions\r
+     */\r
+    if (dat_status == DAT_SUCCESS)\r
+    {\r
+        DAT_PROVIDER_ATTR       p_attr;\r
+        int                     i;\r
+\r
+        return_handle = dats_set_ia_handle (*ia_handle);\r
+        if (return_handle >= 0)\r
+        {\r
+            *ia_handle = (DAT_IA_HANDLE)return_handle;\r
+        }\r
+\r
+        if ( dat_ia_query( *ia_handle,\r
+                           NULL,\r
+                           0,\r
+                           NULL,\r
+                           DAT_PROVIDER_FIELD_PROVIDER_SPECIFIC_ATTR,\r
+                           &p_attr ) == DAT_SUCCESS )\r
+        {\r
+            for ( i = 0; i < p_attr.num_provider_specific_attr; i++ )\r
+            {\r
+                if (strcmp( p_attr.provider_specific_attr[i].name,\r
+                            "DAT_EXTENSION_INTERFACE" ) == 0)\r
+                {\r
+                        dat_os_dbg_print(DAT_OS_DBG_TYPE_CONSUMER_API,\r
+                                         "DAT Registry: dat_ia_open () "\r
+                                         "Extension Interface supported!\n");\r
+\r
+                        g_dat_extensions = 1;\r
+                        break;\r
+                }\r
+            }\r
+        }\r
+    }\r
     return dat_status;
 }
 
index 38ea368d9634b7cd780801cb4c1562c0b882f288..9b8f62fa9101d5d41d10b8066b36e5a567a58ef7 100755 (executable)
@@ -1,12 +1,13 @@
+bin_PROGRAMS = dtest
+dtest_SOURCES = dtest.c
+
 if EXT_TYPE_IB
-XFLAGS = -DDAT_EXTENSIONS
-else
-XFLAGS =
+bin_PROGRAMS += dtestx
+dtestx_SOURCES = dtestx.c
+dtestx_CFLAGS = -DDAT_EXTENSIONS
+dtestx_LDADD = $(srcdir)/../../dat/udat/libdat.la
 endif
 
-dtest_CFLAGS = $(XFLAGS)
-bin_PROGRAMS = dtest
-dtest_SOURCES = dtest.c
 INCLUDES =  -I $(srcdir)/../../dat/include 
 dtest_LDADD = $(srcdir)/../../dat/udat/libdat.la
 
diff --git a/test/dtest/dtestx.c b/test/dtest/dtestx.c
new file mode 100755 (executable)
index 0000000..12db920
--- /dev/null
@@ -0,0 +1,789 @@
+/*
+ * Copyright (c) 2007 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: $
+ */\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <netdb.h>\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <netinet/tcp.h>\r
+#include <arpa/inet.h>\r
+#include <endian.h>\r
+#include <byteswap.h>\r
+\r
+#include "dat/udat.h"\r
+#include "dat/dat_ib_extensions.h"\r
+\r
+#define _OK(status, str) \\r
+{ \\r
+       const char  *maj_msg, *min_msg; \\r
+       if (status != DAT_SUCCESS) { \\r
+               dat_strerror(status, &maj_msg, &min_msg); \\r
+               fprintf(stderr, str " returned %s : %s\n", maj_msg, min_msg); \\r
+               exit(1); \\r
+       } \\r
+}\r
+\r
+#define DTO_TIMEOUT       (1000*1000*5)
+#define CONN_TIMEOUT      (1000*1000*10)
+#define SERVER_TIMEOUT    (1000*1000*20)\r
+#define SERVER_CONN_QUAL       31111\r
+#define BUF_SIZE               256\r
+#define BUF_SIZE_ATOMIC                8\r
+#define REG_MEM_COUNT          10\r
+#define SND_RDMA_BUF_INDEX     0\r
+#define RCV_RDMA_BUF_INDEX     1\r
+#define SEND_BUF_INDEX         2\r
+#define RECV_BUF_INDEX         3\r
+\r
+u_int64_t              *atomic_buf;\r
+DAT_LMR_HANDLE         lmr_atomic;\r
+DAT_LMR_CONTEXT                lmr_atomic_context;\r
+DAT_RMR_CONTEXT                rmr_atomic_context;\r
+DAT_VLEN               reg_atomic_size;\r
+DAT_VADDR              reg_atomic_addr;\r
+DAT_LMR_HANDLE         lmr[ REG_MEM_COUNT ];\r
+DAT_LMR_CONTEXT                lmr_context[ REG_MEM_COUNT ];\r
+DAT_RMR_TRIPLET                rmr[ REG_MEM_COUNT ];\r
+DAT_RMR_CONTEXT                rmr_context[ REG_MEM_COUNT ];\r
+DAT_VLEN               reg_size[ REG_MEM_COUNT ];\r
+DAT_VADDR              reg_addr[ REG_MEM_COUNT ];\r
+DAT_RMR_TRIPLET *      buf[ REG_MEM_COUNT ];\r
+DAT_EP_HANDLE          ep;\r
+DAT_EVD_HANDLE         async_evd = DAT_HANDLE_NULL;\r
+DAT_IA_HANDLE          ia = DAT_HANDLE_NULL;\r
+DAT_PZ_HANDLE          pz = DAT_HANDLE_NULL;\r
+DAT_EVD_HANDLE         cr_evd = DAT_HANDLE_NULL;\r
+DAT_EVD_HANDLE         con_evd = DAT_HANDLE_NULL;\r
+DAT_EVD_HANDLE         dto_evd = DAT_HANDLE_NULL;\r
+DAT_PSP_HANDLE         psp = DAT_HANDLE_NULL;\r
+DAT_CR_HANDLE          cr = DAT_HANDLE_NULL;\r
+int                    server;\r
+\r
+char *usage = "[-s] | hostname\n";\r
+\r
+void\r
+send_msg(\r
+       void *data,\r
+       DAT_COUNT size,\r
+       DAT_LMR_CONTEXT context,\r
+       DAT_DTO_COOKIE cookie,\r
+       DAT_COMPLETION_FLAGS flags)\r
+{\r
+       DAT_LMR_TRIPLET                 iov;\r
+       DAT_EVENT                       event;\r
+       DAT_COUNT                       nmore;\r
+       DAT_RETURN                      status;\r
+       DAT_DTO_COMPLETION_EVENT_DATA *dto_event = \r
+               &event.event_data.dto_completion_event_data;\r
+\r
+       iov.lmr_context     = context;\r
+       iov.virtual_address = (DAT_VADDR)(unsigned long)data;\r
+       iov.segment_length  = (DAT_VLEN)size;\r
+\r
+       status = dat_ep_post_send(ep,\r
+                                  1,\r
+                                  &iov,\r
+                                  cookie,\r
+                                  flags);\r
+       _OK(status, "dat_ep_post_send");\r
+\r
+       if (! (flags & DAT_COMPLETION_SUPPRESS_FLAG)) {\r
+               status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+               _OK(status, "dat_evd_wait after dat_ep_post_send");\r
+\r
+               if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+                       printf("unexpected event waiting for post_send completion - 0x%x\n", event.event_number);\r
+                       exit(1);\r
+               }\r
+\r
+               _OK(dto_event->status, "event status for post_send");\r
+       }\r
+}\r
+\r
+int\r
+connect_ep(char *hostname)\r
+{\r
+       DAT_SOCK_ADDR           remote_addr;\r
+       DAT_EP_ATTR             ep_attr;\r
+       DAT_RETURN              status;\r
+       DAT_REGION_DESCRIPTION  region;\r
+       DAT_EVENT               event;\r
+       DAT_COUNT               nmore;\r
+       DAT_LMR_TRIPLET         iov;\r
+       DAT_RMR_TRIPLET         r_iov;\r
+       DAT_DTO_COOKIE          cookie;\r
+       int                     i;\r
+       DAT_DTO_COMPLETION_EVENT_DATA *dto_event = \r
+               &event.event_data.dto_completion_event_data;\r
+\r
+       status = dat_ia_open("Det2", 8, &async_evd, &ia);\r
+       _OK(status, "dat_ia_open");\r
+\r
+       status = dat_pz_create(ia, &pz);\r
+       _OK(status, "dat_pz_create");\r
+\r
+       status = dat_evd_create(ia, 10, DAT_HANDLE_NULL, DAT_EVD_CR_FLAG, &cr_evd );\r
+       _OK(status, "dat_evd_create CR");\r
+       status = dat_evd_create(ia, 10, DAT_HANDLE_NULL, DAT_EVD_CONNECTION_FLAG, &con_evd );\r
+       _OK(status, "dat_evd_create CR");\r
+       status = dat_evd_create(ia, 10, DAT_HANDLE_NULL, DAT_EVD_DTO_FLAG, &dto_evd );\r
+       _OK(status, "dat_evd_create DTO");\r
+\r
+       memset(&ep_attr, 0, sizeof(ep_attr));\r
+       ep_attr.service_type                = DAT_SERVICE_TYPE_RC;\r
+       ep_attr.max_rdma_size               = 0x10000;\r
+       ep_attr.qos                         = 0;\r
+       ep_attr.recv_completion_flags       = 0;\r
+       ep_attr.max_recv_dtos               = 10;\r
+       ep_attr.max_request_dtos            = 10;\r
+       ep_attr.max_recv_iov                = 1;\r
+       ep_attr.max_request_iov             = 1;\r
+       ep_attr.max_rdma_read_in            = 8;\r
+       ep_attr.max_rdma_read_out           = 8;\r
+       ep_attr.request_completion_flags    = DAT_COMPLETION_DEFAULT_FLAG;\r
+       ep_attr.ep_transport_specific_count = 0;\r
+       ep_attr.ep_transport_specific       = NULL;\r
+       ep_attr.ep_provider_specific_count  = 0;\r
+       ep_attr.ep_provider_specific        = NULL;\r
+\r
+       status = dat_ep_create(ia, pz, dto_evd, dto_evd, con_evd, &ep_attr, &ep);\r
+       _OK(status, "dat_ep_create");\r
+\r
+       for (i = 0; i < REG_MEM_COUNT; i++) {\r
+               buf[ i ] = (DAT_RMR_TRIPLET*)malloc(BUF_SIZE);\r
+               region.for_va = buf[ i ];\r
+               status = dat_lmr_create(ia,\r
+                                       DAT_MEM_TYPE_VIRTUAL,\r
+                                       region,\r
+                                       BUF_SIZE,\r
+                                       pz,\r
+                                       DAT_MEM_PRIV_ALL_FLAG,\r
+                                       DAT_VA_TYPE_VA,
+                                       &lmr[ i ],\r
+                                       &lmr_context[ i ],\r
+                                       &rmr_context[ i ],\r
+                                       &reg_size[ i ],\r
+                                       &reg_addr[ i ]);\r
+               _OK(status, "dat_lmr_create");\r
+               printf(" buf[%d]=%p, reg_addr[%d]=%p\n",\r
+                       i, buf[ i ], i, reg_addr[ i ]);\r
+       }\r
+\r
+       /* register atomic return buffer for original data */\r
+       atomic_buf = (u_int64_t*)malloc(BUF_SIZE);\r
+       region.for_va = atomic_buf;\r
+       status = dat_lmr_create(ia,\r
+                               DAT_MEM_TYPE_VIRTUAL,\r
+                               region,\r
+                               BUF_SIZE_ATOMIC,\r
+                               pz,\r
+                               DAT_MEM_PRIV_ALL_FLAG,\r
+                               DAT_VA_TYPE_VA,
+                               &lmr_atomic,\r
+                               &lmr_atomic_context,\r
+                               &rmr_atomic_context,\r
+                               &reg_atomic_size,\r
+                               &reg_atomic_addr);\r
+       _OK(status, "dat_lmr_create atomic");\r
+       \r
+       for (i = RECV_BUF_INDEX; i < REG_MEM_COUNT; i++) {\r
+               cookie.as_64        = i;\r
+               iov.lmr_context     = lmr_context[ i ];\r
+               iov.virtual_address = (DAT_VADDR)(unsigned long)buf[ i ];\r
+               iov.segment_length  = BUF_SIZE;\r
+\r
+               status = dat_ep_post_recv(ep,\r
+                                          1,\r
+                                          &iov,\r
+                                          cookie,\r
+                                          DAT_COMPLETION_DEFAULT_FLAG);\r
+               _OK(status, "dat_ep_post_recv");\r
+       }\r
+\r
+       /* setup receive buffer to initial string to be overwritten */\r
+       strcpy((char*)buf[ RCV_RDMA_BUF_INDEX ], "blah, blah, blah\n");\r
+\r
+       if (server) {\r
+\r
+               strcpy((char*)buf[ SND_RDMA_BUF_INDEX ], "server written data");\r
+\r
+               status = dat_psp_create(ia,\r
+                                       SERVER_CONN_QUAL,\r
+                                        cr_evd,\r
+                                        DAT_PSP_CONSUMER_FLAG,\r
+                                        &psp);\r
+               _OK(status, "dat_psp_create");\r
+\r
+               printf("Server waiting for connect request\n");\r
+               status = dat_evd_wait(cr_evd, SERVER_TIMEOUT, 1, &event, &nmore);\r
+               _OK(status, "listen dat_evd_wait");\r
+\r
+               if (event.event_number != DAT_CONNECTION_REQUEST_EVENT) {\r
+                       printf("unexpected event after dat_psp_create: 0x%x\n", event.event_number); \r
+                       exit(1);\r
+               }\r
+\r
+               if ((event.event_data.cr_arrival_event_data.conn_qual != SERVER_CONN_QUAL) ||\r
+                    (event.event_data.cr_arrival_event_data.sp_handle.psp_handle != psp)) {\r
+\r
+                       printf("wrong cr event data\n");\r
+                       exit(1);\r
+               }\r
+\r
+               cr = event.event_data.cr_arrival_event_data.cr_handle;\r
+               status = dat_cr_accept(cr, ep, 0, (DAT_PVOID)0);\r
+\r
+       } else {\r
+               struct addrinfo *target;\r
+               int                             rval;\r
+\r
+               if (getaddrinfo (hostname, NULL, NULL, &target) != 0) {\r
+                       printf("Error getting remote address.\n");\r
+                       exit(1);\r
+               }\r
+\r
+               rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;\r
+               printf ("Server Name: %s \n", hostname);\r
+               printf ("Server Net Address: %d.%d.%d.%d\n",\r
+                   (rval >>  0) & 0xff,\r
+                   (rval >>  8) & 0xff,\r
+                   (rval >> 16) & 0xff,\r
+                   (rval >> 24) & 0xff);\r
+\r
+               remote_addr = *((DAT_IA_ADDRESS_PTR)target->ai_addr);\r
+\r
+               strcpy((char*)buf[ SND_RDMA_BUF_INDEX ], "client written data");\r
+\r
+               status = dat_ep_connect(ep,\r
+                                        &remote_addr,\r
+                                        SERVER_CONN_QUAL,\r
+                                        CONN_TIMEOUT,\r
+                                        0,\r
+                                        (DAT_PVOID)0,\r
+                                        0,\r
+                                        DAT_CONNECT_DEFAULT_FLAG );\r
+               _OK(status, "dat_psp_create");\r
+       }\r
+\r
+       printf("Client waiting for connect response\n");\r
+       status = dat_evd_wait(con_evd, CONN_TIMEOUT, 1, &event, &nmore);\r
+               _OK(status, "connect dat_evd_wait");\r
+\r
+       if (event.event_number != DAT_CONNECTION_EVENT_ESTABLISHED) {\r
+               printf("unexpected event after dat_ep_connect: 0x%x\n", event.event_number); \r
+               exit(1);\r
+       }\r
+\r
+       printf("Connected!\n");\r
+\r
+       /*\r
+        *  Setup our remote memory and tell the other side about it\r
+        */\r
+       printf("Sending RMR data to remote\n");\r
+       r_iov.rmr_context    = rmr_context[ RCV_RDMA_BUF_INDEX ];\r
+       r_iov.virtual_address = (DAT_VADDR)((unsigned long)buf[ RCV_RDMA_BUF_INDEX ]);\r
+       r_iov.segment_length = BUF_SIZE;\r
+\r
+       *buf[ SEND_BUF_INDEX ] = r_iov;\r
+\r
+       send_msg(       buf[ SEND_BUF_INDEX ],\r
+                       sizeof(DAT_RMR_TRIPLET),\r
+                       lmr_context[ SEND_BUF_INDEX ],\r
+                       cookie,\r
+                       DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+       /*\r
+        *  Wait for their RMR\r
+        */\r
+       printf("Waiting for remote to send RMR data\n");\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait after dat_ep_post_send");\r
+\r
+       if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+               printf("unexpected event waiting for RMR context - 0x%x\n", \r
+                       event.event_number);\r
+               exit(1);\r
+       }\r
+\r
+       _OK(dto_event->status, "event status for post_send");\r
+       if ((dto_event->transfered_length != sizeof(DAT_RMR_TRIPLET)) ||\r
+            (dto_event->user_cookie.as_64 != RECV_BUF_INDEX)) {\r
+               printf("unexpected event data for receive: len=%d cookie=%d expected %d/%d\n",\r
+                       (int)dto_event->transfered_length,\r
+                       (int)dto_event->user_cookie.as_64,\r
+                       sizeof(DAT_RMR_TRIPLET), RECV_BUF_INDEX);\r
+               exit(1);\r
+       }\r
+\r
+       r_iov = *buf[ RECV_BUF_INDEX ];\r
+\r
+       printf("Received RMR from remote: r_iov: ctx=%x,va=%p,len=%d\n",\r
+               r_iov.rmr_context,\r
+               (void*)(unsigned long)r_iov.virtual_address,\r
+               r_iov.segment_length);\r
+\r
+       return(0);\r
+}\r
+\r
+int\r
+disconnect_ep()\r
+{\r
+       DAT_RETURN      status;\r
+       int                     i;\r
+\r
+       status = dat_ep_disconnect(ep, DAT_CLOSE_DEFAULT);\r
+       _OK(status, "dat_ep_disconnect");\r
+\r
+       printf("EP disconnected\n");\r
+\r
+       if (server) {\r
+               status = dat_psp_free(psp);\r
+               _OK(status, "dat_ep_disconnect");\r
+       }\r
+\r
+       for (i = 0; i < REG_MEM_COUNT; i++) {\r
+               status = dat_lmr_free(lmr[ i ]);\r
+               _OK(status, "dat_lmr_free");\r
+       }\r
+\r
+       status = dat_lmr_free(lmr_atomic);\r
+       _OK(status, "dat_lmr_free_atomic");\r
+\r
+       status = dat_ep_free(ep);\r
+       _OK(status, "dat_ep_free");\r
+\r
+       status = dat_evd_free(dto_evd);\r
+       _OK(status, "dat_evd_free DTO");\r
+       status = dat_evd_free(con_evd);\r
+       _OK(status, "dat_evd_free CON");\r
+       status = dat_evd_free(cr_evd);\r
+       _OK(status, "dat_evd_free CR");\r
+\r
+       status = dat_pz_free(pz);\r
+       _OK(status, "dat_pz_free");\r
+\r
+       status = dat_ia_close(ia, DAT_CLOSE_DEFAULT);\r
+       _OK(status, "dat_ia_close");\r
+\r
+       return(0);\r
+}\r
+\r
+int\r
+do_immediate()\r
+{\r
+       DAT_REGION_DESCRIPTION  region;\r
+       DAT_EVENT               event;\r
+       DAT_COUNT               nmore;\r
+       DAT_LMR_TRIPLET         iov;\r
+       DAT_RMR_TRIPLET         r_iov;\r
+       DAT_DTO_COOKIE          cookie;\r
+       DAT_RMR_CONTEXT         their_context;\r
+       DAT_RETURN              status;\r
+       DAT_UINT32              immed_data;\r
+       DAT_UINT32              immed_data_recv;\r
+       DAT_DTO_COMPLETION_EVENT_DATA *dto_event = \r
+               &event.event_data.dto_completion_event_data;\r
+       DAT_IB_EXTENSION_EVENT_DATA *ext_event = \r
+               (DAT_IB_EXTENSION_EVENT_DATA *)&event.event_extension_data[0];\r
+\r
+       printf("\nDoing RDMA WRITE IMMEDIATE DATA\n");\r
+\r
+       if (server) {\r
+               immed_data = 0x1111;\r
+       } else {\r
+               immed_data = 0x7777;\r
+       }\r
+\r
+       cookie.as_64 = 0x5555;\r
+       \r
+       r_iov = *buf[ RECV_BUF_INDEX ];\r
+\r
+       iov.lmr_context     = lmr_context[ SND_RDMA_BUF_INDEX ];\r
+       iov.virtual_address = (DAT_VADDR)(unsigned long)buf[ SND_RDMA_BUF_INDEX ];\r
+       iov.segment_length  = BUF_SIZE;\r
+\r
+       cookie.as_64 = 0x9999;\r
+       \r
+       status = dat_ib_post_rdma_write_immed(ep,               // ep_handle\r
+                                               1,              // num_segments\r
+                                               &iov,           // LMR\r
+                                               cookie,         // user_cookie\r
+                                               &r_iov,         // RMR\r
+                                               immed_data,\r
+                                               DAT_COMPLETION_DEFAULT_FLAG);\r
+       _OK(status, "dat_ib_post_rdma_write_immed");\r
+       printf("dat_ib_post_rdma_write_immed posted\n");\r
+\r
+       /*\r
+        *  Collect first event, write completion or the inbound recv with immed\r
+        */\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait after dat_ib_post_rdma_write");\r
+       if (event.event_number != DAT_IB_DTO_EVENT)\r
+       {\r
+               printf("unexpected event # waiting for WR-IMMED - 0x%x\n", \r
+                       event.event_number);\r
+               exit(1);\r
+       }\r
+       \r
+       _OK(dto_event->status, "event status");\r
+       if (ext_event->type == DAT_IB_RDMA_WRITE_IMMED)\r
+       {\r
+         if ((dto_event->transfered_length != BUF_SIZE) ||\r
+            (dto_event->user_cookie.as_64 != 0x9999)) \r
+         {\r
+              printf("unexpected event data for rdma_write_immed: len=%d cookie=0x%x\n",\r
+                       (int)dto_event->transfered_length,\r
+                       (int)dto_event->user_cookie.as_64);\r
+             exit(1);\r
+         }\r
+       } \r
+       else if (ext_event->type == DAT_IB_RDMA_WRITE_IMMED_DATA)\r
+        {\r
+         if ((dto_event->transfered_length != BUF_SIZE) ||\r
+            (dto_event->user_cookie.as_64 != RECV_BUF_INDEX+1)) \r
+         {\r
+               printf("unexpected event data of immediate write: len=%d cookie=%d expected %d/%d\n",\r
+                       (int)dto_event->transfered_length,\r
+                       (int)dto_event->user_cookie.as_64,\r
+                       sizeof(int), RECV_BUF_INDEX+1);\r
+               exit(1);\r
+         }\r
+         \r
+         /* get immediate data from event */\r
+         immed_data_recv = ext_event->val.immed.data;\r
+       }\r
+       else\r
+       {\r
+               printf("unexpected extension type for event - 0x%x, 0x%x\n", \r
+                       event.event_number, ext_event->type);\r
+               exit(1);\r
+       }\r
+\r
+\r
+       /*\r
+        *  Collect second event, write completion or the inbound recv with immed\r
+        */\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait after dat_ib_post_rdma_write");\r
+       if (event.event_number != DAT_IB_DTO_EVENT)\r
+       {\r
+               printf("unexpected event # waiting for WR-IMMED - 0x%x\n", \r
+                       event.event_number);\r
+               exit(1);\r
+       }\r
+       \r
+       _OK(dto_event->status, "event status");\r
+       if (ext_event->type == DAT_IB_RDMA_WRITE_IMMED)\r
+       {\r
+         if ((dto_event->transfered_length != BUF_SIZE) ||\r
+            (dto_event->user_cookie.as_64 != 0x9999)) \r
+         {\r
+              printf("unexpected event data for rdma_write_immed: len=%d cookie=0x%x\n",\r
+                       (int)dto_event->transfered_length,\r
+                       (int)dto_event->user_cookie.as_64);\r
+             exit(1);\r
+         }\r
+       } \r
+       else if (ext_event->type == DAT_IB_RDMA_WRITE_IMMED_DATA)\r
+        {\r
+         if ((dto_event->transfered_length != BUF_SIZE) ||\r
+            (dto_event->user_cookie.as_64 != RECV_BUF_INDEX+1)) \r
+         {\r
+               printf("unexpected event data of immediate write: len=%d cookie=%d expected %d/%d\n",\r
+                       (int)dto_event->transfered_length,\r
+                       (int)dto_event->user_cookie.as_64,\r
+                       sizeof(int), RECV_BUF_INDEX+1);\r
+               exit(1);\r
+         }\r
+         \r
+         /* get immediate data from event */\r
+         immed_data_recv = ext_event->val.immed.data;\r
+       }\r
+       else\r
+       {\r
+               printf("unexpected extension type for event - 0x%x, 0x%x\n", \r
+                       event.event_number, ext_event->type);\r
+               exit(1);\r
+       }\r
+               \r
+       if ((server) && (immed_data_recv != 0x7777))\r
+       {\r
+               printf("ERROR: Server got unexpected immed_data_recv 0x%x/0x%x\n", \r
+                       0x7777,  immed_data_recv);\r
+               exit(1);\r
+       } \r
+       else if ((!server) && (immed_data_recv != 0x1111))\r
+       {\r
+               printf("ERROR: Client got unexpected immed_data_recv 0x%x/0x%x\n", \r
+                       0x1111,  immed_data_recv);\r
+               exit(1);\r
+       }\r
+\r
+       if (server)\r
+               printf("SUCCESS: Server received immed_data=0x%x\n", immed_data_recv);\r
+       else\r
+               printf("SUCCESS: Client received immed_data=0x%x\n", immed_data_recv);\r
+       \r
+       printf("RCV buffer %p contains: %s\n", \r
+               buf[ RCV_RDMA_BUF_INDEX ], buf[ RCV_RDMA_BUF_INDEX ]);\r
+\r
+       return (0);\r
+}\r
+\r
+int\r
+do_cmp_swap()\r
+{\r
+       DAT_DTO_COOKIE  cookie;\r
+       DAT_RETURN              status;\r
+       DAT_EVENT               event;\r
+       DAT_COUNT               nmore;\r
+       DAT_LMR_TRIPLET         l_iov;\r
+       DAT_RMR_TRIPLET         r_iov;\r
+       volatile DAT_UINT64     *target = (DAT_UINT64*)buf[ RCV_RDMA_BUF_INDEX ];\r
+       DAT_DTO_COMPLETION_EVENT_DATA *dto_event = \r
+               &event.event_data.dto_completion_event_data;\r
+       DAT_IB_EXTENSION_EVENT_DATA *ext_event = \r
+               (DAT_IB_EXTENSION_EVENT_DATA *)&event.event_extension_data[0];\r
+\r
+       printf("\nDoing CMP and SWAP\n");\r
+        \r
+       r_iov = *buf[ RECV_BUF_INDEX ];\r
+       \r
+       l_iov.lmr_context     = lmr_atomic_context;\r
+       l_iov.virtual_address = (DAT_VADDR)(unsigned long)atomic_buf;\r
+       l_iov.segment_length  = BUF_SIZE_ATOMIC;\r
+\r
+       cookie.as_64 = 3333;\r
+       if (server) {\r
+               *target = 0x12345;\r
+               sleep(1);\r
+               /* server does not compare and should not swap */\r
+               status = dat_ib_post_cmp_and_swap(      ep, \r
+                                                       (DAT_UINT64)0x654321, \r
+                                                       (DAT_UINT64)0x6789A, \r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       } else {\r
+               *target = 0x54321;\r
+               sleep(1);\r
+               /* client does compare and should swap */\r
+               status = dat_ib_post_cmp_and_swap(      ep, \r
+                                                       (DAT_UINT64)0x12345, \r
+                                                       (DAT_UINT64)0x98765,\r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       }\r
+       _OK(status, "dat_ib_post_cmp_and_swap");\r
+       printf("dat_ib_post_cmp_and_swap posted\n");\r
+\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait for compare and swap");\r
+       if (event.event_number != DAT_IB_DTO_EVENT) {\r
+           printf("unexpected event after post_cmp_and_swap: 0x%x\n", \r
+                   event.event_number); \r
+           exit(1);\r
+       }\r
+\r
+       _OK(dto_event->status, "event status for CMP and SWAP");\r
+       if (ext_event->type != DAT_IB_CMP_AND_SWAP) {\r
+           printf("unexpected event data of cmp and swap : type=%d cookie=%d original 0x%llx\n",\r
+               (int)ext_event->type,\r
+               (int)dto_event->user_cookie.as_64,\r
+               *atomic_buf);\r
+               exit(1);\r
+       }\r
+\r
+       if (server) {\r
+           printf("Server got original data        = 0x%llx, expected 0x54321\n", *atomic_buf);\r
+           printf("Client final result (on server) = 0x%llx, expected 0x98765\n", *target);\r
+       } else {\r
+           printf("Client got original data        = 0x%llx, expected 0x12345\n",*atomic_buf);\r
+           printf("Server final result (on client) = 0x%llx, expected 0x54321\n", *target);\r
+       }\r
+       sleep(1);\r
+       return(0);\r
+}\r
+\r
+int\r
+do_fetch_add()\r
+{\r
+       DAT_DTO_COOKIE  cookie;\r
+       DAT_RETURN              status;\r
+       DAT_EVENT               event;\r
+       DAT_COUNT               nmore;\r
+       DAT_LMR_TRIPLET         l_iov;\r
+       DAT_RMR_TRIPLET         r_iov;\r
+       volatile DAT_UINT64     *target = (DAT_UINT64*)buf[ RCV_RDMA_BUF_INDEX ];\r
+       DAT_DTO_COMPLETION_EVENT_DATA *dto_event = \r
+               &event.event_data.dto_completion_event_data;\r
+       DAT_IB_EXTENSION_EVENT_DATA *ext_event = \r
+               (DAT_IB_EXTENSION_EVENT_DATA *)&event.event_extension_data[0];\r
+\r
+       printf("\nDoing FETCH and ADD\n");\r
+\r
+       r_iov = *buf[ RECV_BUF_INDEX ];\r
+       \r
+       l_iov.lmr_context     = lmr_atomic_context;\r
+       l_iov.virtual_address = (DAT_VADDR)(unsigned long)atomic_buf;\r
+       l_iov.segment_length  = BUF_SIZE_ATOMIC;\r
+\r
+       cookie.as_64 = 0x7777;\r
+       if (server) {\r
+               *target = 0x10;\r
+               sleep(1);\r
+               status = dat_ib_post_fetch_and_add(     ep, \r
+                                                       (DAT_UINT64)0x100,\r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       } else {\r
+               *target = 0x100;\r
+               sleep(1);\r
+               status = dat_ib_post_fetch_and_add(     ep, \r
+                                                       (DAT_UINT64)0x10, \r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       }\r
+       _OK(status, "dat_ib_post_fetch_and_add");\r
+       printf("dat_ib_post_fetch_and_add posted\n");\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait for fetch and add");\r
+       if (event.event_number != DAT_IB_DTO_EVENT) {\r
+               printf("unexpected event after post_fetch_and_add: 0x%x\n", event.event_number); \r
+               exit(1);\r
+       }\r
+\r
+       _OK(dto_event->status, "event status for FETCH and ADD");\r
+       if (ext_event->type != DAT_IB_FETCH_AND_ADD) {\r
+               printf("unexpected event data of fetch and add : type=%d cookie=%d original%d\n",\r
+                       (int)ext_event->type,\r
+                       (int)dto_event->user_cookie.as_64,\r
+                       (int)*atomic_buf);\r
+               exit(1);\r
+       }\r
+\r
+       if (server) {\r
+           printf("Client original data (on server) = 0x%llx, expected 0x100\n", *atomic_buf);\r
+       } else {\r
+           printf("Server original data (on client) = 0x%llx, expected 0x10\n", *atomic_buf);\r
+       }\r
+\r
+       sleep(1);       \r
+\r
+       if (server) {\r
+               status = dat_ib_post_fetch_and_add(     ep, \r
+                                                       (DAT_UINT64)0x100, \r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       } else {\r
+               status = dat_ib_post_fetch_and_add(     ep, \r
+                                                       (DAT_UINT64)0x10,\r
+                                                       &l_iov,\r
+                                                       cookie, \r
+                                                       &r_iov, \r
+                                                       DAT_COMPLETION_DEFAULT_FLAG);\r
+       }\r
+\r
+       status = dat_evd_wait(dto_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+       _OK(status, "dat_evd_wait for second fetch and add");\r
+       if (event.event_number != DAT_IB_DTO_EVENT) {\r
+               printf("unexpected event after second post_fetch_and_add: 0x%x\n", event.event_number); \r
+               exit(1);\r
+       }\r
+\r
+       _OK(dto_event->status, "event status for second FETCH and ADD");\r
+       if (ext_event->type != DAT_IB_FETCH_AND_ADD) {\r
+               printf("unexpected event data of second fetch and add : type=%d cookie=%d original%d\n",\r
+                       (int)ext_event->type,\r
+                       (int)dto_event->user_cookie.as_64,\r
+                       (long)atomic_buf);\r
+               exit(1);\r
+       }\r
+\r
+       sleep(1);\r
+       if (server) {\r
+           printf("Server got original data         = 0x%llx, expected 0x200\n", *atomic_buf);\r
+           printf("Client final result (on server)  = 0x%llx, expected 0x30\n", *target);\r
+       } else {\r
+           printf("Server side original data        = 0x%llx, expected 0x20\n", *atomic_buf);\r
+           printf("Server final result (on client)  = 0x%llx, expected 0x300\n", *target);\r
+       }\r
+\r
+       return(0);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       char                                    *hostname;\r
+\r
+       if (argc != 2) {\r
+               printf(usage);\r
+               exit(1);\r
+       }\r
+       if (strcmp(argv[ 1 ], "-s") == 0)\r
+       {\r
+               server = 1;\r
+       } else {\r
+               server = 0;\r
+               hostname = argv[ 1 ];\r
+       }\r
+\r
+       /*\r
+        * connect\r
+        */\r
+       if (connect_ep(hostname)) {\r
+               exit(1);\r
+       }\r
+       if (do_immediate()) {\r
+               exit(1);\r
+       }\r
+       if (do_cmp_swap()) {\r
+               exit(1);\r
+       }\r
+       if (do_fetch_add()) {\r
+               exit(1);\r
+       }\r
+       return (disconnect_ep());\r
+}\r