--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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
+ ®_size[ i ],\r
+ ®_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
+ ®_atomic_size,\r
+ ®_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