Discussion:
unknown
1970-01-01 00:00:00 UTC
Permalink
+ gProtocolInfo = *lpProtocolInfo;
+ }
+ gStartupCount++;
+TRACE("StartupCount incremented to %d", gStartupCount);
+
+ LeaveCriticalSection( &gCriticalSection );
+
+ /* Set the return parameters */
+ *lpWSPData = gWSPData;
+ *lpProcTable = gProcTable;
+
+ /* store the upcall function table */
+ gMainUpCallTable = UpCallTable;
+
+ return Error;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hInstance);
@@ -44,10 +1195,28 @@
if (heap == NULL) {
return FALSE;
}
- InitializeCriticalSection(&lock);
+ fastlock_init(&lock);
+ fastlock_init(&mut);
+ fastlock_init(&TraceLock);
+
+ //
+ // Initialize some critical section objects
+ //
+ __try
+ {
+ InitializeCriticalSection( &gCriticalSection );
+ }
+ __except( EXCEPTION_EXECUTE_HANDLER )
+ {
+ goto cleanup;
+ }
break;
case DLL_PROCESS_DETACH:
- DeleteCriticalSection(&lock);
+ gDetached = TRUE;
+ DeleteCriticalSection( &gCriticalSection );
+ fastlock_destroy(&mut);
+ fastlock_destroy(&lock);
+ fastlock_destroy(&TraceLock);
HeapDestroy(heap);
break;
default:
@@ -55,4 +1224,8 @@
}

return TRUE;
+
+cleanup:
+
+ return FALSE;
}
Index: ulp/librdmacm/src/indexer.cpp
===================================================================
--- ulp/librdmacm/src/indexer.cpp (revision 0)
+++ ulp/librdmacm/src/indexer.cpp (working copy)
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2011 Intel Corporation. All rights reserved.
+ * Copyright (c) 2012 Oce Printing Systems GmbH. All rights reserved.
+ *
+ * This software is available to you under the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * - Neither the name Oce Printing Systems GmbH nor the names
+ * of the authors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+ * OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <windows.h>
+
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "indexer.h"
+#include "cma.h"
+
+/*
+ * Indexer - to find a structure given an index
+ *
+ * We store pointers using a double lookup and return an index to the
+ * user which is then used to retrieve the pointer. The upper bits of
+ * the index are itself an index into an array of memory allocations.
+ * The lower bits specify the offset into the allocated memory where
+ * the pointer is stored.
+ *
+ * This allows us to adjust the number of pointers stored by the index
+ * list without taking a lock during data lookups.
+ */
+
+static int idx_grow(struct indexer *idx)
+{
+ union idx_entry *entry;
+ int i, start_index;
+
+ if (idx->size >= IDX_ARRAY_SIZE)
+ goto nomem;
+
+ idx->array[idx->size] = (union idx_entry *)calloc(IDX_ENTRY_SIZE, sizeof(union idx_entry));
+ if (!idx->array[idx->size])
+ goto nomem;
+
+ entry = idx->array[idx->size];
+ start_index = idx->size << IDX_ENTRY_BITS;
+ entry[IDX_ENTRY_SIZE - 1].next = idx->free_list;
+
+ for (i = IDX_ENTRY_SIZE - 2; i >= 0; i--)
+ entry[i].next = start_index + i + 1;
+
+ /* Index 0 is reserved */
+ if (start_index == 0)
+ start_index++;
+ idx->free_list = start_index;
+ idx->size++;
+ return start_index;
+
+nomem:
+ errno = ENOMEM;
+ return -1;
+}
+
+int idx_insert(struct indexer *idx, void *item)
+{
+ union idx_entry *entry;
+ int index;
+
+ if ((index = idx->free_list) == 0) {
+ if ((index = idx_grow(idx)) <= 0)
+ return index;
+ }
+
+ entry = idx->array[idx_array_index(index)];
+ idx->free_list = entry[idx_entry_index(index)].next;
+ entry[idx_entry_index(index)].item = item;
+ return index;
+}
+
+void *idx_remove(struct indexer *idx, int index)
+{
+ union idx_entry *entry;
+ void *item;
+
+ entry = idx->array[idx_array_index(index)];
+ item = entry[idx_entry_index(index)].item;
+ entry[idx_entry_index(index)].next = idx->free_list;
+ idx->free_list = index;
+ return item;
+}
+
+void idx_replace(struct indexer *idx, int index, void *item)
+{
+ union idx_entry *entry;
+
+ entry = idx->array[idx_array_index(index)];
+ entry[idx_entry_index(index)].item = item;
+}
+
+
+static int idm_grow(struct index_map *idm, int index)
+{
+ idm->array[idx_array_index(index)] = (void **)calloc(IDX_ENTRY_SIZE, sizeof(void *));
+ if (!idm->array[idx_array_index(index)])
+ goto nomem;
+
+ return index;
+
+nomem:
+ errno = ENOMEM;
+ return -1;
+}
+
+int idm_set(struct index_map *idm, int index, void *item)
+{
+ void **entry;
+
+ if (index > IDX_MAX_INDEX) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ if (!idm->array[idx_array_index(index)]) {
+ if (idm_grow(idm, index) < 0)
+ return -1;
+ }
+
+ entry = idm->array[idx_array_index(index)];
+ entry[idx_entry_index(index)] = item;
+ return index;
+}
+
+void *idm_clear(struct index_map *idm, int index)
+{
+ void **entry;
+ void *item;
+
+ entry = idm->array[idx_array_index(index)];
+ item = entry[idx_entry_index(index)];
+ entry[idx_entry_index(index)] = NULL;
+ return item;
+}
Index: ulp/librdmacm/src/indexer.h
===================================================================
--- ulp/librdmacm/src/indexer.h (revision 0)
+++ ulp/librdmacm/src/indexer.h (working copy)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 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.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+
+/*
+ * Indexer - to find a structure given an index. Synchronization
+ * must be provided by the caller. Caller must initialize the
+ * indexer by setting free_list and size to 0.
+ */
+
+union idx_entry {
+ void *item;
+ int next;
+};
+
+#define IDX_INDEX_BITS 16
+#define IDX_ENTRY_BITS 10
+#define IDX_ENTRY_SIZE (1 << IDX_ENTRY_BITS)
+#define IDX_ARRAY_SIZE (1 << (IDX_INDEX_BITS - IDX_ENTRY_BITS))
+#define IDX_MAX_INDEX ((1 << IDX_INDEX_BITS) - 1)
+
+struct indexer
+{
+ union idx_entry *array[IDX_ARRAY_SIZE];
+ int free_list;
+ int size;
+};
+
+#define idx_array_index(index) (index >> IDX_ENTRY_BITS)
+#define idx_entry_index(index) (index & (IDX_ENTRY_SIZE - 1))
+
+int idx_insert(struct indexer *idx, void *item);
+void *idx_remove(struct indexer *idx, int index);
+void idx_replace(struct indexer *idx, int index, void *item);
+
+static inline void *idx_at(struct indexer *idx, int index)
+{
+ return (idx->array[idx_array_index(index)] + idx_entry_index(index))->item;
+}
+
+/*
+ * Index map - associates a structure with an index. Synchronization
+ * must be provided by the caller. Caller must initialize the
+ * index map by setting it to 0.
+ */
+
+struct index_map
+{
+ void **array[IDX_ARRAY_SIZE];
+};
+
+int idm_set(struct index_map *idm, int index, void *item);
+void *idm_clear(struct index_map *idm, int index);
+
+static inline void *idm_at(struct index_map *idm, int index)
+{
+ void **entry;
+ entry = idm->array[idx_array_index(index)];
+ return entry[idx_entry_index(index)];
+}
+
+static inline void *idm_lookup(struct index_map *idm, int index)
+{
+ return ((index <= IDX_MAX_INDEX) && idm->array[idx_array_index(index)]) ?
+ idm_at(idm, index) : NULL;
+}
Index: ulp/librdmacm/src/openib_osd.h
===================================================================
--- ulp/librdmacm/src/openib_osd.h (revision 0)
+++ ulp/librdmacm/src/openib_osd.h (working copy)
@@ -0,0 +1,47 @@
+#ifndef OPENIB_OSD_H
+#define OPENIB_OSD_H
+
+#if defined(FD_SETSIZE) && FD_SETSIZE != 1024
+#undef FD_SETSIZE
+#endif
+#define FD_SETSIZE 1024 /* Set before including winsock2 - see select help */
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <fcntl.h>
+
+#define container_of CONTAINING_RECORD
+#define offsetof FIELD_OFFSET
+#define ssize_t SSIZE_T
+
+#define __thread /*???*/
+
+#define ntohll _byteswap_uint64
+#define htonll _byteswap_uint64
+
+#define SHUT_RD SD_RECEIVE
+#define SHUT_WR SD_SEND
+#define SHUT_RDWR SD_BOTH
+
+#define O_NONBLOCK 0x4000
+
+/* allow casting to WSABUF */
+struct iovec
+{
+ u_long iov_len;
+ char FAR* iov_base;
+};
+
+struct msghdr
+{
+ void *msg_name; // optional address
+ socklen_t msg_namelen; // size of address
+ struct iovec *msg_iov; // scatter/gather array
+ int msg_iovlen; // members in msg_iov
+ void *msg_control; // ancillary data, see below
+ socklen_t msg_controllen; // ancillary data buffer len
+ int msg_flags; // flags on received message
+};
+
+#endif // OPENIB_OSD_H
Index: ulp/librdmacm/src/rsocket.cpp
===================================================================
--- ulp/librdmacm/src/rsocket.cpp (revision 0)
+++ ulp/librdmacm/src/rsocket.cpp (working copy)
@@ -0,0 +1,2334 @@
+/*
+ * Copyright (c) 2008-2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2012 Oce Printing Systems GmbH. All rights reserved.
+ *
+ * This software is available to you under the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * - Neither the name Oce Printing Systems GmbH nor the names
+ * of the authors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+ * OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+
+#include <windows.h>
+#include "openib_osd.h"
+#include <sys/time.h>
+#include <stdarg.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <_fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <_errno.h>
+#include <complib/cl_byteswap.h>
+#include <rdma/rdma_cma.h>
+#include <rdma/rdma_verbs.h>
+#include <rdma/rwinsock.h>
+#include <rdma/rsocket.h>
+#include "cma.h"
+#include "indexer.h"
+#include "../../../etc/user/gtod.c" // getimeofday()
+
+#define RS_OLAP_START_SIZE 2048
+#define RS_MAX_TRANSFER 65536
+#define RS_MAX_BACKLOG 256
+#define RS_QP_MAX_SIZE 0xFFFE
+#define RS_QP_CTRL_SIZE 4
+#define RS_CONN_RETRIES 6
+#define RS_SGL_SIZE 2
+
+static struct index_map idm;
+static uint16_t def_inline = 64;
+static uint16_t def_sqsize = 384;
+static uint16_t def_rqsize = 384;
+static uint32_t def_mem = (1 << 17);
+static uint32_t def_wmem = (1 << 17);
+static uint32_t polling_time = 10;
+
+extern fastlock_t mut;
+extern BOOL gDetached; // Indicates if process is detaching from DLL
+extern CRITICAL_SECTION gCriticalSection; // Critical section for initialization and
+extern WSPUPCALLTABLE gMainUpCallTable; // Upcall functions given to us by Winsock
+extern WSAPROTOCOL_INFOW gProtocolInfo;
+
+/*
+ * Immediate data format is determined by the upper bits
+ * bit 31: message type, 0 - data, 1 - control
+ * bit 30: buffers updated, 0 - target, 1 - direct-receive
+ * bit 29: more data, 0 - end of transfer, 1 - more data available
+ *
+ * for data transfers:
+ * bits [28:0]: bytes transfered, 0 = 1 GB
+ * for control messages:
+ * bits [28-0]: receive credits granted
+ */
+
+enum {
+ RS_OP_DATA,
+ RS_OP_RSVD_DATA_MORE,
+ RS_OP_RSVD_DRA,
+ RS_OP_RSVD_DRA_MORE,
+ RS_OP_SGL,
+ RS_OP_RSVD,
+ RS_OP_RSVD_DRA_SGL,
+ RS_OP_CTRL
+};
+#define rs_msg_set(op, data) ((op << 29) | (uint32_t) (data))
+#define rs_msg_op(imm_data) (imm_data >> 29)
+#define rs_msg_data(imm_data) (imm_data & 0x1FFFFFFF)
+
+enum {
+ RS_CTRL_DISCONNECT,
+ RS_CTRL_SHUTDOWN
+};
+
+struct rs_msg {
+ uint32_t op;
+ uint32_t data;
+};
+
+struct rs_sge {
+ uint64_t addr;
+ uint32_t key;
+ uint32_t length;
+};
+
+#define RS_MIN_INLINE (sizeof(struct rs_sge))
+#define rs_host_is_net() (1 == htonl(1))
+#define RS_CONN_FLAG_NET 1
+
+struct rs_conn_data {
+ uint8_t version;
+ uint8_t flags;
+ uint16_t credits;
+ uint32_t reserved2;
+ struct rs_sge target_sgl;
+ struct rs_sge data_buf;
+};
+
+#define RS_RECV_WR_ID (~((uint64_t) 0))
+
+/*
+ * rsocket states are ordered as passive, connecting, connected, disconnected.
+ */
+enum rs_state {
+ rs_init,
+ rs_bound = 0x0001,
+ rs_listening = 0x0002,
+ rs_opening = 0x0004,
+ rs_resolving_addr = rs_opening | 0x0010,
+ rs_resolving_route = rs_opening | 0x0020,
+ rs_connecting = rs_opening | 0x0040,
+ rs_accepting = rs_opening | 0x0080,
+ rs_connected = 0x0100,
+ rs_connect_wr = 0x0200,
+ rs_connect_rd = 0x0400,
+ rs_connect_rdwr = rs_connected | rs_connect_rd | rs_connect_wr,
+ rs_connect_error = 0x0800,
+ rs_disconnected = 0x1000,
+ rs_error = 0x2000,
+};
+
+#define RS_OPT_SWAP_SGL 1
+
+struct rsocket {
+ struct rdma_cm_id *cm_id;
+ fastlock_t slock;
+ fastlock_t rlock;
+ fastlock_t cq_lock;
+ fastlock_t cq_wait_lock;
+
+ int opts;
+ long fd_flags;
+ uint64_t so_opts;
+ uint64_t tcp_opts;
+ uint64_t ipv6_opts;
+ int state;
+ int cq_armed;
+ int retries;
+ int err;
+ int index;
+ int ctrl_avail;
+ int sqe_avail;
+ int sbuf_bytes_avail;
+ uint16_t sseq_no;
+ uint16_t sseq_comp;
+ uint16_t sq_size;
+ uint16_t sq_inline;
+
+ uint16_t rq_size;
+ uint16_t rseq_no;
+ uint16_t rseq_comp;
+ int rbuf_bytes_avail;
+ int rbuf_free_offset;
+ int rbuf_offset;
+ int rmsg_head;
+ int rmsg_tail;
+ struct rs_msg *rmsg;
+
+ int remote_sge;
+ struct rs_sge remote_sgl;
+
+ struct ibv_mr *target_mr;
+ int target_sge;
+ volatile struct rs_sge target_sgl[RS_SGL_SIZE];
+
+ uint32_t rbuf_size;
+ struct ibv_mr *rmr;
+ uint8_t *rbuf;
+
+ uint32_t sbuf_size;
+ struct ibv_mr *smr;
+ struct ibv_sge ssgl[2];
+ uint8_t *sbuf;
+};
+
+static void rs_configure(void)
+{
+ FILE *f;
+ static int init;
+
+ if (init)
+ return;
+
+ fastlock_acquire(&mut);
+ if (init)
+ goto out;
+
+ if ((f = fopen(RS_CONF_DIR "/polling_time", "r"))) {
+ fscanf(f, "%u", &polling_time);
+ fclose(f);
+ }
+
+ if ((f = fopen(RS_CONF_DIR "/inline_default", "r"))) {
+ fscanf(f, "%hu", &def_inline);
+ fclose(f);
+
+ if (def_inline < RS_MIN_INLINE)
+ def_inline = RS_MIN_INLINE;
+ }
+
+ if ((f = fopen(RS_CONF_DIR "/sqsize_default", "r"))) {
+ fscanf(f, "%hu", &def_sqsize);
+ fclose(f);
+ }
+
+ if ((f = fopen(RS_CONF_DIR "/rqsize_default", "r"))) {
+ fscanf(f, "%hu", &def_rqsize);
+ fclose(f);
+ }
+
+ if ((f = fopen(RS_CONF_DIR "/mem_default", "r"))) {
+ fscanf(f, "%u", &def_mem);
+ fclose(f);
+
+ if (def_mem < 1)
+ def_mem = 1;
+ }
+
+ if ((f = fopen(RS_CONF_DIR "/wmem_default", "r"))) {
+ fscanf(f, "%u", &def_wmem);
+ fclose(f);
+
+ if (def_wmem < 1)
+ def_wmem = 1;
+ }
+ init = 1;
+out:
+ fastlock_release(&mut);
+}
+
+static int rs_insert(struct rsocket *rs)
+{
+ fastlock_acquire(&mut);
+ rs->index = idm_set(&idm, ((int)rs->cm_id->channel->channel.Event >> 2)/*fd*/, rs);
+ fastlock_release(&mut);
+ return rs->index;
+}
+
+static void rs_remove(struct rsocket *rs)
+{
+ fastlock_acquire(&mut);
+ idm_clear(&idm, rs->index);
+ fastlock_release(&mut);
+}
+
+static struct rsocket *rs_alloc(struct rsocket *inherited_rs)
+{
+ struct rsocket *rs;
+
+ rs = (struct rsocket *)calloc(1, sizeof *rs);
+ if (!rs)
+ return NULL;
+
+ rs->index = -1;
+ if (inherited_rs) {
+ rs->sbuf_size = inherited_rs->sbuf_size;
+ rs->rbuf_size = inherited_rs->rbuf_size;
+ rs->sq_inline = inherited_rs->sq_inline;
+ rs->sq_size = inherited_rs->sq_size;
+ rs->rq_size = inherited_rs->rq_size;
+ rs->ctrl_avail = inherited_rs->ctrl_avail;
+ } else {
+ rs->sbuf_size = def_wmem;
+ rs->rbuf_size = def_mem;
+ rs->sq_inline = def_inline;
+ rs->sq_size = def_sqsize;
+ rs->rq_size = def_rqsize;
+ rs->ctrl_avail = RS_QP_CTRL_SIZE;
+ }
+ fastlock_init(&rs->slock);
+ fastlock_init(&rs->rlock);
+ fastlock_init(&rs->cq_lock);
+ fastlock_init(&rs->cq_wait_lock);
+ return rs;
+}
+
+static int rs_set_nonblocking(struct rsocket *rs, long arg)
+{
+ if (rs->cm_id->recv_cq_channel)
+ rs->cm_id->recv_cq_channel->comp_channel.Milliseconds = (arg == O_NONBLOCK ? 0 : INFINITE);
+
+ if (rs->state < rs_connected)
+ rs->cm_id->channel->channel.Milliseconds = (arg == O_NONBLOCK ? 0 : INFINITE);
+
+ return 0;
+}
+
+static void rs_set_qp_size(struct rsocket *rs)
+{
+ uint16_t max_size;
+
+ max_size = min(ucma_max_qpsize(rs->cm_id), RS_QP_MAX_SIZE);
+
+ if (rs->sq_size > max_size)
+ rs->sq_size = max_size;
+ else if (rs->sq_size < 2)
+ rs->sq_size = 2;
+ if (rs->sq_size <= (RS_QP_CTRL_SIZE << 2))
+ rs->ctrl_avail = 1;
+
+ if (rs->rq_size > max_size)
+ rs->rq_size = max_size;
+ else if (rs->rq_size < 2)
+ rs->rq_size = 2;
+}
+
+static int rs_init_bufs(struct rsocket *rs)
+{
+ rs->rmsg = (struct rs_msg *)calloc(rs->rq_size + 1, sizeof(*rs->rmsg));
+ if (!rs->rmsg)
+ return -1;
+
+ rs->sbuf = (uint8_t *)calloc(rs->sbuf_size, sizeof(*rs->sbuf));
+ if (!rs->sbuf)
+ return -1;
+
+ rs->smr = rdma_reg_msgs(rs->cm_id, rs->sbuf, rs->sbuf_size);
+ if (!rs->smr)
+ return -1;
+
+ rs->target_mr = rdma_reg_write(rs->cm_id, (void *) rs->target_sgl,
+ sizeof(rs->target_sgl));
+ if (!rs->target_mr)
+ return -1;
+
+ rs->rbuf = (uint8_t *)calloc(rs->rbuf_size, sizeof(*rs->rbuf));
+ if (!rs->rbuf)
+ return -1;
+
+ rs->rmr = rdma_reg_write(rs->cm_id, rs->rbuf, rs->rbuf_size);
+ if (!rs->rmr)
+ return -1;
+
+ rs->ssgl[0].addr = rs->ssgl[1].addr = (uintptr_t) rs->sbuf;
+ rs->sbuf_bytes_avail = rs->sbuf_size;
+ rs->ssgl[0].lkey = rs->ssgl[1].lkey = rs->smr->lkey;
+
+ rs->rbuf_free_offset = rs->rbuf_size >> 1;
+ rs->rbuf_bytes_avail = rs->rbuf_size >> 1;
+ rs->sqe_avail = rs->sq_size - rs->ctrl_avail;
+ rs->rseq_comp = rs->rq_size >> 1;
+ return 0;
+}
+
+static int rs_create_cq(struct rsocket *rs)
+{
+ rs->cm_id->recv_cq_channel = ibv_create_comp_channel(rs->cm_id->verbs);
+ if (!rs->cm_id->recv_cq_channel)
+ return -1;
+
+ rs->cm_id->recv_cq = ibv_create_cq(rs->cm_id->verbs, rs->sq_size + rs->rq_size,
+ rs->cm_id, rs->cm_id->recv_cq_channel, 0);
+ if (!rs->cm_id->recv_cq)
+ goto err1;
+
+ if (rs->fd_flags & O_NONBLOCK) {
+ if (rs_set_nonblocking(rs, O_NONBLOCK))
+ goto err2;
+ }
+
+ rs->cm_id->send_cq_channel = rs->cm_id->recv_cq_channel;
+ rs->cm_id->send_cq = rs->cm_id->recv_cq;
+ return 0;
+
+err2:
+ ibv_destroy_cq(rs->cm_id->recv_cq);
+ rs->cm_id->recv_cq = NULL;
+err1:
+ ibv_destroy_comp_channel(rs->cm_id->recv_cq_channel);
+ rs->cm_id->recv_cq_channel = NULL;
+ return -1;
+}
+
+static __inline int
+rs_post_recv(struct rsocket *rs)
+{
+ struct ibv_recv_wr wr, *bad;
+
+ wr.wr_id = RS_RECV_WR_ID;
+ wr.next = NULL;
+ wr.sg_list = NULL;
+ wr.num_sge = 0;
+
+ return rdma_seterrno(ibv_post_recv(rs->cm_id->qp, &wr, &bad));
+}
+
+static int rs_create_ep(struct rsocket *rs)
+{
+ struct ibv_qp_init_attr qp_attr;
+ int i, ret;
+
+ rs_set_qp_size(rs);
+
+ ret = rs_create_cq(rs);
+ if (ret)
+ return ret;
+
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_context = rs;
+ qp_attr.send_cq = rs->cm_id->send_cq;
+ qp_attr.recv_cq = rs->cm_id->recv_cq;
+ qp_attr.qp_type = IBV_QPT_RC;
+ qp_attr.sq_sig_all = 1;
+ qp_attr.cap.max_send_wr = rs->sq_size;
+ qp_attr.cap.max_recv_wr = rs->rq_size;
+ qp_attr.cap.max_send_sge = 2;
+ qp_attr.cap.max_recv_sge = 1;
+ qp_attr.cap.max_inline_data = rs->sq_inline;
+
+ ret = rdma_create_qp(rs->cm_id, NULL, &qp_attr);
+ if (ret)
+ return ret;
+
+ ret = rs_init_bufs(rs);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < rs->rq_size; i++) {
+ ret = rs_post_recv(rs);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static void rs_free(struct rsocket *rs)
+{
+ if (rs->index >= 0)
+ rs_remove(rs);
+
+ if (rs->rmsg)
+ free(rs->rmsg);
+
+ if (rs->sbuf) {
+ if (rs->smr)
+ rdma_dereg_mr(rs->smr);
+ free(rs->sbuf);
+ }
+
+ if (rs->rbuf) {
+ if (rs->rmr)
+ rdma_dereg_mr(rs->rmr);
+ free(rs->rbuf);
+ }
+
+ if (rs->target_mr)
+ rdma_dereg_mr(rs->target_mr);
+
+ if (rs->cm_id) {
+ if (rs->cm_id->qp)
+ rdma_destroy_qp(rs->cm_id);
+ rdma_destroy_id(rs->cm_id);
+ }
+
+ fastlock_destroy(&rs->cq_wait_lock);
+ fastlock_destroy(&rs->cq_lock);
+ fastlock_destroy(&rs->rlock);
+ fastlock_destroy(&rs->slock);
+ free(rs);
+}
+
+static void rs_set_conn_data(struct rsocket *rs, struct rdma_conn_param *param,
+ struct rs_conn_data *conn)
+{
+ conn->version = 1;
+ conn->flags = rs_host_is_net() ? RS_CONN_FLAG_NET : 0;
+ conn->credits = htons(rs->rq_size);
+ conn->reserved2 = 0;
+
+ conn->target_sgl.addr = htonll((uintptr_t) rs->target_sgl);
+ conn->target_sgl.length = htonl(RS_SGL_SIZE);
+ conn->target_sgl.key = htonl(rs->target_mr->rkey);
+
+ conn->data_buf.addr = htonll((uintptr_t) rs->rbuf);
+ conn->data_buf.length = htonl(rs->rbuf_size >> 1);
+ conn->data_buf.key = htonl(rs->rmr->rkey);
+
+ param->private_data = conn;
+ param->private_data_len = sizeof *conn;
+}
+
+static void rs_save_conn_data(struct rsocket *rs, struct rs_conn_data *conn)
+{
+ rs->remote_sgl.addr = ntohll(conn->target_sgl.addr);
+ rs->remote_sgl.length = ntohl(conn->target_sgl.length);
+ rs->remote_sgl.key = ntohl(conn->target_sgl.key);
+ rs->remote_sge = 1;
+ if ((rs_host_is_net() && !(conn->flags & RS_CONN_FLAG_NET)) ||
+ (!rs_host_is_net() && (conn->flags & RS_CONN_FLAG_NET)))
+ rs->opts = RS_OPT_SWAP_SGL;
+
+ rs->target_sgl[0].addr = ntohll(conn->data_buf.addr);
+ rs->target_sgl[0].length = ntohl(conn->data_buf.length);
+ rs->target_sgl[0].key = ntohl(conn->data_buf.key);
+
+ rs->sseq_comp = ntohs(conn->credits);
+}
+
+__declspec(dllexport)
+int rsocket(int domain, int type, int protocol)
+{
+ struct rsocket *rs;
+ int ret;
+
+ wsa_setlasterror(0);
+ if ((domain != PF_INET && domain != PF_INET6) ||
+ (type != SOCK_STREAM) || (protocol && protocol != IPPROTO_TCP))
+ return ERR(ENOTSUP);
+
+ rs_configure();
+ rs = rs_alloc(NULL);
+ if (!rs)
+ return ERR(ENOMEM);
+
+ ret = rdma_create_id(NULL, &rs->cm_id, rs, RDMA_PS_TCP);
+ if (ret)
+ goto err;
+
+ ret = rs_insert(rs);
+ if (ret < 0)
+ goto err;
+
+ rs->cm_id->route.addr.src_addr.sa_family = (ADDRESS_FAMILY)domain;
+ return rs->index;
+
+err:
+ rs_free(rs);
+ return ret;
+}
+
+__declspec(dllexport)
+int rbind(int socket, const struct sockaddr *addr, socklen_t addrlen)
+{
+ struct rsocket *rs;
+ int ret;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ ret = rdma_bind_addr(rs->cm_id, (struct sockaddr *) addr);
+ if (!ret)
+ {
+ rs->state = rs_bound;
+ }
+ else
+ {
+ wsa_setlasterror(errno);
+ }
+
+ return ret;
+}
+
+__declspec(dllexport)
+int rlisten(int socket, int backlog)
+{
+ struct rsocket *rs;
+ int ret;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+
+ if (backlog > RS_MAX_BACKLOG || backlog == SOMAXCONN)
+ backlog = RS_MAX_BACKLOG;
+
+ ret = rdma_listen(rs->cm_id, backlog);
+ if (!ret)
+ {
+ rs->state = rs_listening;
+ }
+ else
+ {
+ wsa_setlasterror(errno);
+ }
+
+ return ret;
+}
+
+static int rs_do_connect(struct rsocket *rs)
+{
+ struct rdma_conn_param param;
+ struct rs_conn_data creq, *cresp;
+ struct sockaddr_storage dst_addr;
+ int to, ret;
+
+ switch (rs->state) {
+ case rs_init:
+ case rs_bound:
+resolve_addr:
+ to = 1000 << rs->retries++;
+ RtlCopyMemory(
+ &dst_addr,
+ &rs->cm_id->route.addr.dst_addr,
+ rs->cm_id->route.addr.dst_addr.sa_family == AF_INET
+ ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6)
+ );
+ ret = rdma_resolve_addr(rs->cm_id, NULL,
+ (struct sockaddr *)&dst_addr, to);
+ if (!ret)
+ goto resolve_route;
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ rs->state = rs_resolving_addr;
+ break;
+ case rs_resolving_addr:
+ ret = ucma_complete(rs->cm_id);
+ if (ret) {
+ if (errno == ETIMEDOUT && rs->retries <= RS_CONN_RETRIES)
+ goto resolve_addr;
+ break;
+ }
+
+ rs->retries = 0;
+resolve_route:
+ to = 1000 << rs->retries++;
+ ret = rdma_resolve_route(rs->cm_id, to);
+ if (!ret)
+ goto do_connect;
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ rs->state = rs_resolving_route;
+ break;
+ case rs_resolving_route:
+ ret = ucma_complete(rs->cm_id);
+ if (ret) {
+ if (errno == ETIMEDOUT && rs->retries <= RS_CONN_RETRIES)
+ goto resolve_route;
+ break;
+ }
+do_connect:
+ ret = rs_create_ep(rs);
+ if (ret)
+ break;
+
+ memset(&param, 0, sizeof param);
+ rs_set_conn_data(rs, &param, &creq);
+ param.flow_control = 1;
+ param.retry_count = 7;
+ param.rnr_retry_count = 7;
+ rs->retries = 0;
+
+ ret = rdma_connect(rs->cm_id, &param);
+ if (!ret)
+ goto connected;
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ rs->state = rs_connecting;
+ break;
+ case rs_connecting:
+ ret = ucma_complete(rs->cm_id);
+ if (ret)
+ break;
+connected:
+ cresp = (struct rs_conn_data *) rs->cm_id->event->param.conn.private_data;
+ if (cresp->version != 1) {
+ ret = ERR(ENOTSUP);
+ break;
+ }
+
+ rs_save_conn_data(rs, cresp);
+ rs->state = rs_connect_rdwr;
+ break;
+ case rs_accepting:
+ if (!(rs->fd_flags & O_NONBLOCK))
+ rs_set_nonblocking(rs, 0);
+
+ ret = ucma_complete(rs->cm_id);
+ if (ret)
+ break;
+
+ rs->state = rs_connect_rdwr;
+ break;
+ default:
+ ret = ERR(EINVAL);
+ break;
+ }
+
+ if (ret) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ errno = EINPROGRESS;
+ } else {
+ rs->state = rs_connect_error;
+ rs->err = errno;
+ }
+ wsa_setlasterror(errno);
+ }
+ return ret;
+}
+
+__declspec(dllexport)
+int rconnect(int socket, const struct sockaddr *addr, socklen_t addrlen)
+{
+ struct rsocket *rs;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ memcpy(&rs->cm_id->route.addr.dst_addr, addr, addrlen);
+ return rs_do_connect(rs);
+}
+
+static int rs_post_write(struct rsocket *rs,
+ struct ibv_sge *sgl, int nsge,
+ uint32_t imm_data, int flags,
+ uint64_t addr, uint32_t rkey)
+{
+ struct ibv_send_wr wr, *bad;
+
+ wr.wr_id = (uint64_t) imm_data;
+ wr.next = NULL;
+ wr.sg_list = sgl;
+ wr.num_sge = nsge;
+ wr.opcode = IBV_WR_RDMA_WRITE_WITH_IMM;
+ wr.send_flags = flags;
+ wr.imm_data = htonl(imm_data);
+ wr.wr.rdma.remote_addr = addr;
+ wr.wr.rdma.rkey = rkey;
+
+ return rdma_seterrno(ibv_post_send(rs->cm_id->qp, &wr, &bad));
+}
+
+/*
+ * Update target SGE before sending data. Otherwise the remote side may
+ * update the entry before we do.
+ */
+static int rs_write_data(struct rsocket *rs,
+ struct ibv_sge *sgl, int nsge,
+ uint32_t length, int flags)
+{
+ uint64_t addr;
+ uint32_t rkey;
+
+ rs->sseq_no++;
+ rs->sqe_avail--;
+ rs->sbuf_bytes_avail -= length;
+
+ addr = rs->target_sgl[rs->target_sge].addr;
+ rkey = rs->target_sgl[rs->target_sge].key;
+
+ rs->target_sgl[rs->target_sge].addr += length;
+ rs->target_sgl[rs->target_sge].length -= length;
+
+ if (!rs->target_sgl[rs->target_sge].length) {
+ if (++rs->target_sge == RS_SGL_SIZE)
+ rs->target_sge = 0;
+ }
+
+ return rs_post_write(rs, sgl, nsge, rs_msg_set(RS_OP_DATA, length),
+ flags, addr, rkey);
+}
+
+static uint32_t rs_sbuf_left(struct rsocket *rs)
+{
+ return (uint32_t) (((uint64_t) (uintptr_t) &rs->sbuf[rs->sbuf_size]) -
+ rs->ssgl[0].addr);
+}
+
+static void rs_send_credits(struct rsocket *rs)
+{
+ struct ibv_sge ibsge;
+ struct rs_sge sge;
+
+ rs->ctrl_avail--;
+ rs->rseq_comp = rs->rseq_no + (rs->rq_size >> 1);
+ if ((uint32_t)rs->rbuf_bytes_avail >= (rs->rbuf_size >> 1)) {
+ if (!(rs->opts & RS_OPT_SWAP_SGL)) {
+ sge.addr = (uintptr_t) &rs->rbuf[rs->rbuf_free_offset];
+ sge.key = rs->rmr->rkey;
+ sge.length = rs->rbuf_size >> 1;
+ } else {
+ sge.addr = cl_ntoh64((uintptr_t) &rs->rbuf[rs->rbuf_free_offset]);
+ sge.key = cl_ntoh32(rs->rmr->rkey);
+ sge.length = cl_ntoh32(rs->rbuf_size >> 1);
+ }
+
+ ibsge.addr = (uintptr_t) &sge;
+ ibsge.lkey = 0;
+ ibsge.length = sizeof(sge);
+
+ rs_post_write(rs, &ibsge, 1,
+ rs_msg_set(RS_OP_SGL, rs->rseq_no + rs->rq_size),
+ IBV_SEND_INLINE,
+ rs->remote_sgl.addr +
+ rs->remote_sge * sizeof(struct rs_sge),
+ rs->remote_sgl.key);
+
+ rs->rbuf_bytes_avail -= rs->rbuf_size >> 1;
+ rs->rbuf_free_offset += rs->rbuf_size >> 1;
+ if ((uint32_t)rs->rbuf_free_offset >= rs->rbuf_size)
+ rs->rbuf_free_offset = 0;
+ if (++rs->remote_sge == rs->remote_sgl.length)
+ rs->remote_sge = 0;
+ } else {
+ rs_post_write(rs, NULL, 0,
+ rs_msg_set(RS_OP_SGL, rs->rseq_no + rs->rq_size), 0, 0, 0);
+ }
+}
+
+static int rs_give_credits(struct rsocket *rs)
+{
+ return (((uint32_t)rs->rbuf_bytes_avail >= (rs->rbuf_size >> 1)) ||
+ ((short) ((short) rs->rseq_no - (short) rs->rseq_comp) >= 0)) &&
+ rs->ctrl_avail && (rs->state & rs_connected);
+}
+
+static void rs_update_credits(struct rsocket *rs)
+{
+ if (rs_give_credits(rs))
+ rs_send_credits(rs);
+}
+
+static int rs_poll_cq(struct rsocket *rs)
+{
+ struct ibv_wc wc;
+ uint32_t imm_data;
+ int ret, rcnt = 0;
+
+ while ((ret = ibv_poll_cq(rs->cm_id->recv_cq, 1, &wc)) > 0) {
+ if (wc.wr_id == RS_RECV_WR_ID) {
+ if (wc.status != IBV_WC_SUCCESS)
+ continue;
+ rcnt++;
+
+ imm_data = ntohl(wc.imm_data);
+ switch (rs_msg_op(imm_data)) {
+ case RS_OP_SGL:
+ rs->sseq_comp = (uint16_t) rs_msg_data(imm_data);
+ break;
+ case RS_OP_CTRL:
+ if (rs_msg_data(imm_data) == RS_CTRL_DISCONNECT) {
+ rs->state = rs_disconnected;
+ return 0;
+ } else if (rs_msg_data(imm_data) == RS_CTRL_SHUTDOWN) {
+ rs->state &= ~rs_connect_rd;
+ }
+ break;
+ default:
+ rs->rmsg[rs->rmsg_tail].op = rs_msg_op(imm_data);
+ rs->rmsg[rs->rmsg_tail].data = rs_msg_data(imm_data);
+ if (++rs->rmsg_tail == rs->rq_size + 1)
+ rs->rmsg_tail = 0;
+ break;
+ }
+ } else {
+ switch (rs_msg_op((uint32_t) wc.wr_id)) {
+ case RS_OP_SGL:
+ rs->ctrl_avail++;
+ break;
+ case RS_OP_CTRL:
+ rs->ctrl_avail++;
+ if (rs_msg_data((uint32_t) wc.wr_id) == RS_CTRL_DISCONNECT)
+ rs->state = rs_disconnected;
+ break;
+ default:
+ rs->sqe_avail++;
+ rs->sbuf_bytes_avail += rs_msg_data((uint32_t) wc.wr_id);
+ break;
+ }
+
+ if (wc.status != IBV_WC_SUCCESS && (rs->state & rs_connected)) {
+ rs->state = rs_error;
+ rs->err = EIO;
+ }
+ }
+ }
+
+ if (rs->state & rs_connected) {
+ while (!ret && rcnt--)
+ {
+ ret = rs_post_recv(rs);
+ }
+
+ if (ret) {
+ rs->state = rs_error;
+ rs->err = errno;
+ }
+ }
+ return ret;
+}
+
+static int rs_get_cq_event(struct rsocket *rs)
+{
+ struct ibv_cq *cq;
+ void *context;
+ int ret;
+
+ if (!rs->cq_armed)
+ {
+ return 0;
+ }
+ ret = ibv_get_cq_event(rs->cm_id->recv_cq_channel, &cq, &context);
+ if (!ret) {
+ ibv_ack_cq_events(rs->cm_id->recv_cq, 1);
+ rs->cq_armed = 0;
+ } else if (errno != EAGAIN) {
+ rs->state = rs_error;
+ }
+ return ret;
+}
+
+/*
+ * Although we serialize rsend and rrecv calls with respect to themselves,
+ * both calls may run simultaneously and need to poll the CQ for completions.
+ * We need to serialize access to the CQ, but rsend and rrecv need to
+ * allow each other to make forward progress.
+ *
+ * For example, rsend may need to wait for credits from the remote side,
+ * which could be stalled until the remote process calls rrecv. This should
+ * not block rrecv from receiving data from the remote side however.
+ *
+ * We handle this by using two locks. The cq_lock protects against polling
+ * the CQ and processing completions. The cq_wait_lock serializes access to
+ * waiting on the CQ.
+ */
+static int rs_process_cq(struct rsocket *rs, int nonblock, int (*test)(struct rsocket *rs))
+{
+ int ret;
+
+ fastlock_acquire(&rs->cq_lock);
+ do {
+ rs_update_credits(rs);
+ ret = rs_poll_cq(rs);
+ if (test(rs)) {
+ ret = 0;
+ break;
+ } else if (ret) {
+ break;
+ } else if (nonblock) {
+ ret = ERR(EWOULDBLOCK);
+ } else if (!rs->cq_armed) {
+ ibv_req_notify_cq(rs->cm_id->recv_cq, 0);
+ rs->cq_armed = 1;
+ } else {
+ rs_update_credits(rs);
+ fastlock_acquire(&rs->cq_wait_lock);
+ fastlock_release(&rs->cq_lock);
+ ret = rs_get_cq_event(rs);
+ fastlock_release(&rs->cq_wait_lock);
+ fastlock_acquire(&rs->cq_lock);
+ }
+ } while (!ret);
+
+ rs_update_credits(rs);
+ fastlock_release(&rs->cq_lock);
+ return ret;
+}
+
+static int rs_get_comp(struct rsocket *rs, int nonblock, int (*test)(struct rsocket *rs))
+{
+ struct timeval s, e;
+ uint32_t poll_time = 0;
+ int ret;
+ do {
+ ret = rs_process_cq(rs, 1, test);
+ if (!ret || nonblock || errno != EWOULDBLOCK) {
+ return ret;
+ }
+
+ if (!poll_time)
+ gettimeofday(&s, NULL);
+
+ gettimeofday(&e, NULL);
+ poll_time = (e.tv_sec - s.tv_sec) * 1000000 +
+ (e.tv_usec - s.tv_usec) + 1;
+ } while (poll_time <= polling_time);
+ ret = rs_process_cq(rs, 0, test);
+ return ret;
+}
+
+static int rs_nonblocking(struct rsocket *rs)
+{
+ return (rs->fd_flags & O_NONBLOCK);
+}
+
+static int rs_is_cq_armed(struct rsocket *rs)
+{
+ return rs->cq_armed;
+}
+
+static int rs_poll_all(struct rsocket *rs)
+{
+ return 1;
+}
+
+/*
+ * We use hardware flow control to prevent over running the remote
+ * receive queue. However, data transfers still require space in
+ * the remote rmsg queue, or we risk losing notification that data
+ * has been transfered.
+ *
+ * Be careful with race conditions in the check below. The target SGL
+ * may be updated by a remote RDMA write.
+ */
+static int rs_can_send(struct rsocket *rs)
+{
+ return rs->sqe_avail && rs->sbuf_bytes_avail &&
+ (rs->sseq_no != rs->sseq_comp) &&
+ (rs->target_sgl[rs->target_sge].length != 0);
+}
+
+static int rs_conn_can_send(struct rsocket *rs)
+{
+ return rs_can_send(rs) || !(rs->state & rs_connect_wr);
+}
+
+static int rs_conn_can_send_ctrl(struct rsocket *rs)
+{
+ return rs->ctrl_avail || !(rs->state & rs_connected);
+}
+
+static int rs_have_rdata(struct rsocket *rs)
+{
+ return (rs->rmsg_head != rs->rmsg_tail);
+}
+
+static int rs_conn_have_rdata(struct rsocket *rs)
+{
+ return rs_have_rdata(rs) || !(rs->state & rs_connect_rd);
+}
+
+static int rs_conn_all_sends_done(struct rsocket *rs)
+{
+ return ((rs->sqe_avail + rs->ctrl_avail) == rs->sq_size) ||
+ !(rs->state & rs_connected);
+}
+
+static ssize_t rs_peek(struct rsocket *rs, void *buf, size_t len)
+{
+ size_t left = len;
+ uint32_t end_size, rsize;
+ int rmsg_head, rbuf_offset;
+ uint8_t *bufb = (uint8_t *)buf;
+
+ rmsg_head = rs->rmsg_head;
+ rbuf_offset = rs->rbuf_offset;
+
+ for (; left && (rmsg_head != rs->rmsg_tail); left -= rsize) {
+ if (left < rs->rmsg[rmsg_head].data) {
+ rsize = left;
+ } else {
+ rsize = rs->rmsg[rmsg_head].data;
+ if (++rmsg_head == rs->rq_size + 1)
+ rmsg_head = 0;
+ }
+
+ end_size = rs->rbuf_size - rbuf_offset;
+ if (rsize > end_size) {
+ memcpy(bufb, &rs->rbuf[rbuf_offset], end_size);
+ rbuf_offset = 0;
+ bufb += end_size;
+ rsize -= end_size;
+ left -= end_size;
+ }
+ memcpy(bufb, &rs->rbuf[rbuf_offset], rsize);
+ rbuf_offset += rsize;
+ bufb += rsize;
+ }
+
+ return len - left;
+}
+
+/*
+ * Continue to receive any queued data even if the remote side has disconnected.
+ */
+ __declspec(dllexport)
+ssize_t rrecv(int socket, void *buf, size_t len, int flags)
+{
+ struct rsocket *rs;
+ size_t left = len;
+ uint32_t end_size, rsize;
+ int ret;
+ uint8_t *bufb = (uint8_t *)buf;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ if (rs->state & rs_opening) {
+ ret = rs_do_connect(rs);
+ if (ret) {
+ if (errno == EINPROGRESS)
+ errno = EAGAIN;
+ goto out;
+ }
+ }
+ fastlock_acquire(&rs->rlock);
+ do {
+ if (!rs_have_rdata(rs)) {
+ ret = rs_get_comp(rs, rs_nonblocking(rs),
+ rs_conn_have_rdata);
+ if (ret)
+ break;
+ }
+
+ ret = 0;
+ if (flags & MSG_PEEK) {
+ left = len - rs_peek(rs, buf, left);
+ break;
+ }
+
+ for (; left && rs_have_rdata(rs); left -= rsize) {
+ if (left < rs->rmsg[rs->rmsg_head].data) {
+ rsize = left;
+ rs->rmsg[rs->rmsg_head].data -= left;
+ } else {
+ rs->rseq_no++;
+ rsize = rs->rmsg[rs->rmsg_head].data;
+ if (++rs->rmsg_head == rs->rq_size + 1)
+ rs->rmsg_head = 0;
+ }
+
+ end_size = rs->rbuf_size - rs->rbuf_offset;
+ if (rsize > end_size) {
+ memcpy(bufb, &rs->rbuf[rs->rbuf_offset], end_size);
+ rs->rbuf_offset = 0;
+ bufb += end_size;
+ rsize -= end_size;
+ left -= end_size;
+ rs->rbuf_bytes_avail += end_size;
+ }
+ memcpy(bufb, &rs->rbuf[rs->rbuf_offset], rsize);
+ rs->rbuf_offset += rsize;
+ bufb += rsize;
+ rs->rbuf_bytes_avail += rsize;
+ }
+ } while (left && (flags & MSG_WAITALL) && (rs->state & rs_connect_rd));
+
+ fastlock_release(&rs->rlock);
+
+out:
+ if (ret)
+ {
+ wsa_setlasterror(errno);
+ return ret;
+ }
+ else
+ {
+ return len - left;
+ }
+}
+
+ssize_t rrecvfrom(int socket, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ ssize_t ret;
+
+ ret = rrecv(socket, buf, len, flags);
+ if (ret > 0 && src_addr)
+ rgetpeername(socket, src_addr, addrlen);
+
+ return ret;
+}
+
+/*
+ * Simple, straightforward implementation for now that only tries to fill
+ * in the first vector.
+ */
+static ssize_t rrecvv(int socket, const struct iovec *iov, int iovcnt, int flags)
+{
+ return rrecv(socket, iov[0].iov_base, iov[0].iov_len, flags);
+}
+
+ssize_t rrecvmsg(int socket, struct msghdr *msg, int flags)
+{
+ if (msg->msg_control && msg->msg_controllen)
+ return ERR(ENOTSUP);
+
+ return rrecvv(socket, msg->msg_iov, (int) msg->msg_iovlen, msg->msg_flags);
+}
+
+ssize_t rread(int socket, void *buf, size_t count)
+{
+ return rrecv(socket, buf, count, 0);
+}
+
+ssize_t rreadv(int socket, const struct iovec *iov, int iovcnt)
+{
+ return rrecvv(socket, iov, iovcnt, 0);
+}
+
+/*
+ * We overlap sending the data, by posting a small work request immediately,
+ * then increasing the size of the send on each iteration.
+ */
+ssize_t rsend(int socket, const void *buf, size_t len, int flags)
+{
+ struct rsocket *rs;
+ struct ibv_sge sge;
+ size_t left = len;
+ uint32_t xfer_size, olen = RS_OLAP_START_SIZE;
+ int ret = 0;
+ uint8_t *bufb = (uint8_t *)buf;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ if (rs->state & rs_opening) {
+ ret = rs_do_connect(rs);
+ if (ret) {
+ if (errno == EINPROGRESS)
+ errno = EAGAIN;
+ goto out;
+ }
+ }
+
+ fastlock_acquire(&rs->slock);
+ for (; left; left -= xfer_size, bufb += xfer_size) {
+ if (!rs_can_send(rs)) {
+ ret = rs_get_comp(rs, rs_nonblocking(rs),
+ rs_conn_can_send);
+ if (ret)
+ break;
+ if (!(rs->state & rs_connect_wr)) {
+ ret = ERR(ECONNRESET);
+ break;
+ }
+ }
+
+ if (olen < left) {
+ xfer_size = olen;
+ if (olen < RS_MAX_TRANSFER)
+ olen <<= 1;
+ } else {
+ xfer_size = left;
+ }
+
+ if (xfer_size > (uint32_t)rs->sbuf_bytes_avail)
+ xfer_size = rs->sbuf_bytes_avail;
+ if (xfer_size > rs->target_sgl[rs->target_sge].length)
+ xfer_size = rs->target_sgl[rs->target_sge].length;
+
+ if (xfer_size <= rs->sq_inline) {
+ sge.addr = (uintptr_t)bufb;
+ sge.length = xfer_size;
+ sge.lkey = 0;
+ ret = rs_write_data(rs, &sge, 1, xfer_size, IBV_SEND_INLINE);
+ } else if (xfer_size <= rs_sbuf_left(rs)) {
+ memcpy((void *) (uintptr_t) rs->ssgl[0].addr, bufb, xfer_size);
+ rs->ssgl[0].length = xfer_size;
+ ret = rs_write_data(rs, rs->ssgl, 1, xfer_size, 0);
+ if (xfer_size < rs_sbuf_left(rs))
+ rs->ssgl[0].addr += xfer_size;
+ else
+ rs->ssgl[0].addr = (uintptr_t) rs->sbuf;
+ } else {
+ rs->ssgl[0].length = rs_sbuf_left(rs);
+ memcpy((void *) (uintptr_t) rs->ssgl[0].addr, bufb,
+ rs->ssgl[0].length);
+ rs->ssgl[1].length = xfer_size - rs->ssgl[0].length;
+ memcpy(rs->sbuf, bufb + rs->ssgl[0].length, rs->ssgl[1].length);
+ ret = rs_write_data(rs, rs->ssgl, 2, xfer_size, 0);
+ rs->ssgl[0].addr = (uintptr_t) rs->sbuf + rs->ssgl[1].length;
+ }
+ if (ret)
+ break;
+ }
+ fastlock_release(&rs->slock);
+
+out:
+ if (ret && left == len)
+ {
+ wsa_setlasterror(errno);
+ return ret;
+ }
+ else
+ {
+ return len - left;
+ }
+}
+
+ssize_t rsendto(int socket, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+/*
+ * In Windows on a connection-oriented socket,
+ * the dest_addr and addrlen parameters are just ignored,
+ * making sendto() equivalent to send().
+ */
+ return rsend(socket, buf, len, flags);
+}
+
+static void rs_copy_iov(void *dst, const struct iovec **iov, size_t *offset, size_t len)
+{
+ size_t size;
+ uint8_t *dstb = (uint8_t *)dst;
+
+ while (len) {
+ size = (*iov)->iov_len - *offset;
+ if (size > len) {
+ memcpy (dstb, (*iov)->iov_base + *offset, len);
+ *offset += len;
+ break;
+ }
+
+ memcpy(dstb, (*iov)->iov_base + *offset, size);
+ len -= size;
+ dstb += size;
+ (*iov)++;
+ *offset = 0;
+ }
+}
+
+static ssize_t rsendv(int socket, const struct iovec *iov, int iovcnt, int flags)
+{
+ struct rsocket *rs;
+ const struct iovec *cur_iov;
+ size_t left, len, offset = 0;
+ uint32_t xfer_size, olen = RS_OLAP_START_SIZE;
+ int i, ret = 0;
+
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ if (rs->state & rs_opening) {
+ ret = rs_do_connect(rs);
+ if (ret) {
+ if (errno == EINPROGRESS)
+ errno = EAGAIN;
+ return ret;
+ }
+ }
+
+ cur_iov = iov;
+ len = iov[0].iov_len;
+ for (i = 1; i < iovcnt; i++)
+ len += iov[i].iov_len;
+
+ fastlock_acquire(&rs->slock);
+ for (left = len; left; left -= xfer_size) {
+ if (!rs_can_send(rs)) {
+ ret = rs_get_comp(rs, rs_nonblocking(rs),
+ rs_conn_can_send);
+ if (ret)
+ break;
+ if (!(rs->state & rs_connect_wr)) {
+ ret = ERR(ECONNRESET);
+ break;
+ }
+ }
+
+ if (olen < left) {
+ xfer_size = olen;
+ if (olen < RS_MAX_TRANSFER)
+ olen <<= 1;
+ } else {
+ xfer_size = left;
+ }
+
+ if (xfer_size > (uint32_t)rs->sbuf_bytes_avail)
+ xfer_size = rs->sbuf_bytes_avail;
+ if (xfer_size > rs->target_sgl[rs->target_sge].length)
+ xfer_size = rs->target_sgl[rs->target_sge].length;
+
+ if (xfer_size <= rs_sbuf_left(rs)) {
+ rs_copy_iov((void *) (uintptr_t) rs->ssgl[0].addr,
+ &cur_iov, &offset, xfer_size);
+ rs->ssgl[0].length = xfer_size;
+ ret = rs_write_data(rs, rs->ssgl, 1, xfer_size,
+ xfer_size <= rs->sq_inline ? IBV_SEND_INLINE : 0);
+ if (xfer_size < rs_sbuf_left(rs))
+ rs->ssgl[0].addr += xfer_size;
+ else
+ rs->ssgl[0].addr = (uintptr_t) rs->sbuf;
+ } else {
+ rs->ssgl[0].length = rs_sbuf_left(rs);
+ rs_copy_iov((void *) (uintptr_t) rs->ssgl[0].addr, &cur_iov,
+ &offset, rs->ssgl[0].length);
+ rs->ssgl[1].length = xfer_size - rs->ssgl[0].length;
+ rs_copy_iov(rs->sbuf, &cur_iov, &offset, rs->ssgl[1].length);
+ ret = rs_write_data(rs, rs->ssgl, 2, xfer_size,
+ xfer_size <= rs->sq_inline ? IBV_SEND_INLINE : 0);
+ rs->ssgl[0].addr = (uintptr_t) rs->sbuf + rs->ssgl[1].length;
+ }
+ if (ret)
+ break;
+ }
+ fastlock_release(&rs->slock);
+
+ return (ret && left == len) ? ret : len - left;
+}
+
+__declspec(dllexport)
+ssize_t rsendmsg(int socket, const struct msghdr *msg, int flags)
+{
+ wsa_setlasterror(0);
+ if (msg->msg_control && msg->msg_controllen)
+ return ERR(ENOTSUP);
+
+ return rsendv(socket, msg->msg_iov, (int) msg->msg_iovlen, msg->msg_flags);
+}
+
+__declspec(dllexport)
+ssize_t rwrite(int socket, const void *buf, size_t count)
+{
+ return rsend(socket, buf, count, 0);
+}
+
+__declspec(dllexport)
+ssize_t rwritev(int socket, const struct iovec *iov, int iovcnt)
+{
+ return rsendv(socket, iov, iovcnt, 0);
+}
+
+static struct pollfd *rs_fds_alloc(nfds_t nfds)
+{
+ static __thread struct pollfd *rfds;
+ static __thread nfds_t rnfds;
+
+ if (nfds > rnfds) {
+ if (rfds)
+ free(rfds);
+
+ rfds = (struct pollfd *)malloc(sizeof *rfds * nfds);
+ rnfds = rfds ? nfds : 0;
+ }
+
+ return rfds;
+}
+
+static int rs_poll_rs(struct rsocket *rs, int events,
+ int nonblock, int (*test)(struct rsocket *rs))
+{
+ COMP_SET fds;
+ short revents;
+ int ret;
+
+check_cq:
+ if ((rs->state & rs_connected) || (rs->state == rs_disconnected) ||
+ (rs->state & rs_error)) {
+ rs_process_cq(rs, nonblock, test);
+
+ revents = 0;
+ if ((events & POLLIN) && rs_conn_have_rdata(rs))
+ revents |= POLLIN;
+ if ((events & POLLOUT) && rs_can_send(rs))
+ revents |= POLLOUT;
+ if (!(rs->state & rs_connected)) {
+ if (rs->state == rs_disconnected)
+ revents |= POLLHUP;
+ else
+ revents |= POLLERR;
+ }
+
+ return revents;
+ }
+
+ if (rs->state == rs_listening) {
+ if (CompSetInit(&fds))
+ return 0;
+
+ CompSetZero(&fds);
+ CompSetAdd(&rs->cm_id->channel->channel, &fds);
+ return CompSetPoll(&fds, 0);
+ }
+
+ if (rs->state & rs_opening) {
+ ret = rs_do_connect(rs);
+ if (ret) {
+ if (errno == EINPROGRESS) {
+ errno = 0;
+ return 0;
+ } else {
+ return POLLOUT;
+ }
+ }
+ goto check_cq;
+ }
+
+ if (rs->state == rs_connect_error)
+ return (rs->err && events & POLLOUT) ? POLLOUT : 0;
+
+ return 0;
+}
+
+static int rs_poll_check(struct pollfd *fds, nfds_t nfds)
+{
+ struct rsocket *rs;
+ int i, cnt = 0;
+
+ for (i = 0; i < (int)nfds; i++) {
+ rs = (struct rsocket *)idm_lookup(&idm, (int)fds[i].fd);
+ if (rs)
+ fds[i].revents = (SHORT)rs_poll_rs(rs, fds[i].events, 1, rs_poll_all);
+ else
+ ;//WSAPoll(&fds[i], 1, 0);
+
+ if (fds[i].revents)
+ cnt++;
+ }
+ return cnt;
+}
+
+static int rs_poll_arm(struct pollfd *rfds, struct pollfd *fds, nfds_t nfds)
+{
+ struct rsocket *rs;
+ int i;
+
+ for (i = 0; i < (int)nfds; i++) {
+ rs = (struct rsocket *)idm_lookup(&idm, (int)fds[i].fd);
+ if (rs) {
+ fds[i].revents = (SHORT)rs_poll_rs(rs, fds[i].events, 0, rs_is_cq_armed);
+ if (fds[i].revents)
+ return 1;
+
+ if (rs->state >= rs_connected)
+ rfds[i].fd = ((short)rs->cm_id->recv_cq_channel->comp_channel.Event >> 2);
+ else
+ rfds[i].fd = ((short)rs->cm_id->channel->channel.Event >> 2);
+
+ rfds[i].events = POLLIN;
+ } else {
+ rfds[i].fd = fds[i].fd;
+ rfds[i].events = fds[i].events;
+ }
+ rfds[i].revents = 0;
+ }
+ return 0;
+}
+
+static int rs_poll_events(struct pollfd *rfds, struct pollfd *fds, nfds_t nfds)
+{
+ struct rsocket *rs;
+ int i, cnt = 0;
+
+ for (i = 0; i < (int)nfds; i++) {
+ if (!rfds[i].revents)
+ continue;
+
+ rs = (struct rsocket *)idm_lookup(&idm, (int)fds[i].fd);
+ if (rs) {
+ rs_get_cq_event(rs);
+ fds[i].revents = (SHORT)rs_poll_rs(rs, fds[i].events, 1, rs_poll_all);
+ } else {
+ fds[i].revents = rfds[i].revents;
+ }
+ if (fds[i].revents)
+ cnt++;
+ }
+ return cnt;
+}
+
+/*
+ * We need to poll *all* fd's that the user specifies at least once.
+ * Note that we may receive events on an rsocket that may not be reported
+ * to the user (e.g. connection events or credit updates). Process those
+ * events, then return to polling until we find ones of interest.
+ */
+__declspec(dllexport)
+int rpoll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+ struct timeval s, e;
+ struct pollfd *rfds;
+ uint32_t poll_time = 0;
+ int ret;
+
+ wsa_setlasterror(0);
+ do {
+ ret = rs_poll_check(fds, nfds);
+ if (ret || !timeout)
+ return ret;
+
+ if (!poll_time)
+ gettimeofday(&s, NULL);
+
+ gettimeofday(&e, NULL);
+ poll_time = (e.tv_sec - s.tv_sec) * 1000000 +
+ (e.tv_usec - s.tv_usec) + 1;
+ } while (poll_time <= polling_time);
+
+ rfds = rs_fds_alloc(nfds);
+ if (!rfds)
+ return ERR(ENOMEM);
+
+ do {
+ ret = rs_poll_arm(rfds, fds, nfds);
+ if (ret)
+ break;
+#if 0
+ ret = WSAPoll(rfds, nfds, timeout);
+ if (ret <= 0)
+ break;
+#endif
+ ret = rs_poll_events(rfds, fds, nfds);
+ } while (!ret);
+
+ return ret;
+}
+
+static struct pollfd *
+rs_select_to_poll(int *nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+ struct pollfd *fds;
+ int fd, i = 0;
+
+ fds = (struct pollfd *)calloc(*nfds, sizeof *fds);
+ if (!fds)
+ return NULL;
+
+ for (fd = 0; fd < *nfds; fd++) {
+ if (readfds && FD_ISSET(fd, readfds)) {
+ fds[i].fd = fd;
+ fds[i].events = POLLIN;
+ }
+
+ if (writefds && FD_ISSET(fd, writefds)) {
+ fds[i].fd = fd;
+ fds[i].events |= POLLOUT;
+ }
+
+ if (exceptfds && FD_ISSET(fd, exceptfds))
+ fds[i].fd = fd;
+
+ if (fds[i].fd)
+ i++;
+ }
+
+ *nfds = i;
+ return fds;
+}
+
+static int
+rs_poll_to_select(int nfds, struct pollfd *fds, fd_set *readfds,
+ fd_set *writefds, fd_set *exceptfds)
+{
+ int i, cnt = 0;
+
+ for (i = 0; i < nfds; i++) {
+ if (readfds && (fds[i].revents & (POLLIN | POLLHUP))) {
+ FD_SET(fds[i].fd, readfds);
+ cnt++;
+ }
+
+ if (writefds && (fds[i].revents & POLLOUT)) {
+ FD_SET(fds[i].fd, writefds);
+ cnt++;
+ }
+
+ if (exceptfds && (fds[i].revents & ~(POLLIN | POLLOUT))) {
+ FD_SET(fds[i].fd, exceptfds);
+ cnt++;
+ }
+ }
+ return cnt;
+}
+
+static int rs_convert_timeout(struct timeval *timeout)
+{
+ return !timeout ? -1 :
+ timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+}
+
+__declspec(dllexport)
+int rselect(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *exceptfds, struct timeval *timeout)
+{
+ struct pollfd *fds;
+ int ret;
+
+ wsa_setlasterror(0);
+ fds = rs_select_to_poll(&nfds, readfds, writefds, exceptfds);
+ if (!fds)
+ return ERR(ENOMEM);
+
+ ret = rpoll(fds, nfds, rs_convert_timeout(timeout));
+
+ if (readfds)
+ FD_ZERO(readfds);
+ if (writefds)
+ FD_ZERO(writefds);
+ if (exceptfds)
+ FD_ZERO(exceptfds);
+
+ if (ret > 0)
+ ret = rs_poll_to_select(nfds, fds, readfds, writefds, exceptfds);
+
+ free(fds);
+ return ret;
+}
+
+/*
+ * For graceful disconnect, notify the remote side that we're
+ * disconnecting and wait until all outstanding sends complete.
+ */
+__declspec(dllexport)
+int rshutdown(int socket, int how)
+{
+ struct rsocket *rs;
+ int ctrl, ret = 0;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ if (how == SHUT_RD) {
+ rs->state &= ~rs_connect_rd;
+ return 0;
+ }
+
+ if (rs->fd_flags & O_NONBLOCK)
+ rs_set_nonblocking(rs, 0);
+
+ if (rs->state & rs_connected) {
+ if (how == SHUT_RDWR) {
+ ctrl = RS_CTRL_DISCONNECT;
+ rs->state &= ~(rs_connect_rd | rs_connect_wr);
+ } else {
+ rs->state &= ~rs_connect_wr;
+ ctrl = (rs->state & rs_connect_rd) ?
+ RS_CTRL_SHUTDOWN : RS_CTRL_DISCONNECT;
+ }
+ if (!rs->ctrl_avail) {
+ ret = rs_process_cq(rs, 0, rs_conn_can_send_ctrl);
+ if (ret)
+ {
+ wsa_setlasterror(errno);
+ return ret;
+ }
+ }
+ if ((rs->state & rs_connected) && rs->ctrl_avail) {
+ rs->ctrl_avail--;
+ ret = rs_post_write(rs, NULL, 0,
+ rs_msg_set(RS_OP_CTRL, ctrl), 0, 0, 0);
+ }
+ }
+
+ if (rs->state & rs_connected)
+ rs_process_cq(rs, 0, rs_conn_all_sends_done);
+
+ if ((rs->fd_flags & O_NONBLOCK) && (rs->state & rs_connected))
+ rs_set_nonblocking(rs, 1);
+
+ return 0;
+}
+
+__declspec(dllexport)
+int rclose(int socket)
+{
+ struct rsocket *rs;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ if (rs->state & rs_connected)
+ rshutdown(socket, SHUT_RDWR);
+
+ rs_free(rs);
+ return 0;
+}
+
+static void rs_copy_addr(struct sockaddr *dst, struct sockaddr *src, socklen_t *len)
+{
+ socklen_t size;
+
+ if (src->sa_family == AF_INET) {
+ size = min(*len, sizeof(struct sockaddr_in));
+ *len = sizeof(struct sockaddr_in);
+ } else {
+ size = min(*len, sizeof(struct sockaddr_in6));
+ *len = sizeof(struct sockaddr_in6);
+ }
+ memcpy(dst, src, size);
+}
+
+__declspec(dllexport)
+int rgetpeername(int socket, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct rsocket *rs;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ rs_copy_addr(addr, rdma_get_peer_addr(rs->cm_id), addrlen);
+ return 0;
+}
+
+__declspec(dllexport)
+int rgetsockname(int socket, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct rsocket *rs;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ rs_copy_addr(addr, rdma_get_local_addr(rs->cm_id), addrlen);
+ return 0;
+}
+
+/*
+ * Nonblocking is usually not inherited between sockets, but we need to
+ * inherit it here to establish the connection only. This is needed to
+ * prevent rdma_accept from blocking until the remote side finishes
+ * establishing the connection. If we were to allow rdma_accept to block,
+ * then a single thread cannot establish a connection with itself, or
+ * two threads which try to connect to each other can deadlock trying to
+ * form a connection.
+ *
+ * Data transfers on the new socket remain blocking unless the user
+ * specifies otherwise through rfcntl.
+ */
+__declspec(dllexport)
+int raccept(int socket, struct sockaddr *addr, socklen_t *addrlen)
+{
+ struct rsocket *rs, *new_rs;
+ struct rdma_conn_param param;
+ struct rs_conn_data *creq, cresp;
+ int ret;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ new_rs = rs_alloc(rs);
+ if (!new_rs)
+ return ERR(ENOMEM);
+
+ ret = rdma_get_request(rs->cm_id, &new_rs->cm_id);
+ if (ret)
+ goto err;
+
+ ret = rs_insert(new_rs);
+ if (ret < 0)
+ goto err;
+
+ creq = (struct rs_conn_data *) new_rs->cm_id->event->param.conn.private_data;
+ if (creq->version != 1) {
+ ret = ERR(ENOTSUP);
+ goto err;
+ }
+
+ if (rs->fd_flags & O_NONBLOCK)
+ rs_set_nonblocking(new_rs, O_NONBLOCK);
+
+ ret = rs_create_ep(new_rs);
+ if (ret)
+ goto err;
+
+ rs_save_conn_data(new_rs, creq);
+ param = new_rs->cm_id->event->param.conn;
+ rs_set_conn_data(new_rs, &param, &cresp);
+ ret = rdma_accept(new_rs->cm_id, &param);
+ if (!ret)
+ new_rs->state = rs_connect_rdwr;
+ else if (errno == EAGAIN || errno == EWOULDBLOCK)
+ new_rs->state = rs_accepting;
+ else
+ goto err;
+
+ if (addr && addrlen)
+ rgetpeername(new_rs->index, addr, addrlen);
+ return new_rs->index;
+
+err:
+ rs_free(new_rs);
+ return ret;
+}
+
+/*
+ * Socket provider's variant:
+ */
+SOCKET WSPAPI WSPAccept(
+ SOCKET socket,
+ struct sockaddr *addr,
+ LPINT addrlen,
+ LPCONDITIONPROC lpfnCondition,
+ DWORD_PTR dwCallbackData,
+ LPINT lpErrno
+ )
+{
+ struct rsocket *rs, *new_rs;
+ struct rdma_conn_param param;
+ struct rs_conn_data *creq, cresp;
+ SOCKET new_socket = INVALID_SOCKET;
+ DWORD_PTR rsock = INVALID_SOCKET;
+ int ret = gMainUpCallTable.lpWPUQuerySocketHandleContext(
+ socket,
+ (PDWORD_PTR)&rsock, // __out PDWORD_PTR lpContext
+ lpErrno
+ );
+ if (SOCKET_ERROR == ret)
+ return INVALID_SOCKET;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, (int)rsock);
+ new_rs = rs_alloc(rs);
+ if (!new_rs)
+ return ERR(ENOMEM);
+
+ ret = rdma_get_request(rs->cm_id, &new_rs->cm_id);
+ if (ret)
+ goto err;
+
+ ret = rs_insert(new_rs);
+ if (ret < 0)
+ goto err;
+
+ creq = (struct rs_conn_data *) new_rs->cm_id->event->param.conn.private_data;
+ if (creq->version != 1) {
+ ret = ERR(ENOTSUP);
+ goto err;
+ }
+
+ if (rs->fd_flags & O_NONBLOCK)
+ rs_set_nonblocking(new_rs, O_NONBLOCK);
+
+ ret = rs_create_ep(new_rs);
+ if (ret)
+ goto err;
+
+ rs_save_conn_data(new_rs, creq);
+ param = new_rs->cm_id->event->param.conn;
+ rs_set_conn_data(new_rs, &param, &cresp);
+
+ if (addr && addrlen)
+ rgetpeername(new_rs->index, addr, addrlen);
+
+ if (lpfnCondition) {
+ struct sockaddr local_addr;
+ socklen_t local_addrlen = sizeof(local_addr);
+ WSABUF caller_id;
+ WSABUF callee_id;
+ WSABUF callee_data;
+
+ /* Set the caller and callee data buffer */
+ caller_id.buf = (char *)addr;
+ caller_id.len = sizeof(*addr);
+
+ rs_copy_addr(&local_addr, rdma_get_local_addr(new_rs->cm_id), &local_addrlen);
+
+ callee_id.buf = (char *)&local_addr;
+ callee_id.len = local_addrlen;
+
+ callee_data.buf = NULL;
+ callee_data.len = 0;
+
+ switch(lpfnCondition(&caller_id, NULL, NULL, NULL, &callee_id, &callee_data, NULL, dwCallbackData)) {
+ default:
+ /* Should never happen */
+ /* Fall through. */
+ case CF_REJECT:
+ *lpErrno = WSAECONNREFUSED;
+ ret = (int)INVALID_SOCKET;
+ goto err;
+ case CF_DEFER:
+ *lpErrno = WSATRY_AGAIN;
+ ret = (int)INVALID_SOCKET;
+ goto err;
+ case CF_ACCEPT:
+ break;
+ }
+ }
+ new_socket = gMainUpCallTable.lpWPUCreateSocketHandle(
+ gProtocolInfo.dwCatalogEntryId,
+ new_rs->index, // __in DWORD_PTR dwContext
+ lpErrno
+ );
+ if (INVALID_SOCKET == new_socket) {
+ //??? *lpErrno = WSATRY_AGAIN;
+ goto err;
+ }
+ ret = rdma_accept(new_rs->cm_id, &param);
+ if (!ret)
+ new_rs->state = rs_connect_rdwr;
+ else if (errno == EAGAIN || errno == EWOULDBLOCK)
+ new_rs->state = rs_accepting;
+ else
+ goto err;
+
+ return new_socket;
+
+err:
+ rs_free(new_rs);
+ if (new_socket != INVALID_SOCKET)
+ gMainUpCallTable.lpWPUCloseSocketHandle(new_socket, lpErrno);
+
+ return INVALID_SOCKET;
+}
+
+__declspec(dllexport)
+int rsetsockopt(int socket, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ struct rsocket *rs;
+ int ret, opt_on = 0;
+ uint64_t *opts = NULL;
+
+ ret = ERR(ENOTSUP);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ switch (level) {
+ case SOL_SOCKET:
+ opts = &rs->so_opts;
+ switch (optname) {
+ case SO_REUSEADDR:
+ ret = rdma_set_option(rs->cm_id, RDMA_OPTION_ID,
+ RDMA_OPTION_ID_REUSEADDR,
+ (void *) optval, optlen);
+ if (ret && ((errno == ENOSYS) || ((rs->state != rs_init) &&
+ rs->cm_id->context &&
+ (rs->cm_id->verbs->device->transport_type == IBV_TRANSPORT_IB))))
+ ret = 0;
+ opt_on = *(int *) optval;
+ break;
+ case SO_RCVBUF:
+ if (!rs->rbuf)
+ rs->rbuf_size = (*(uint32_t *) optval) << 1;
+ ret = 0;
+ break;
+ case SO_SNDBUF:
+ if (!rs->sbuf)
+ rs->sbuf_size = (*(uint32_t *) optval) << 1;
+ ret = 0;
+ break;
+ case SO_LINGER:
+ /* Invert value so default so_opt = 0 is on */
+ opt_on = !((struct linger *) optval)->l_onoff;
+ ret = 0;
+ break;
+ case SO_KEEPALIVE:
+ opt_on = *(int *) optval;
+ ret = 0;
+ break;
+ case SO_OOBINLINE:
+ opt_on = *(int *) optval;
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case IPPROTO_TCP:
+ opts = &rs->tcp_opts;
+ switch (optname) {
+ case TCP_NODELAY:
+ opt_on = *(int *) optval;
+ ret = 0;
+ break;
+ case TCP_MAXSEG:
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case IPPROTO_IPV6:
+ opts = &rs->ipv6_opts;
+ switch (optname) {
+ case IPV6_V6ONLY:
+ ret = rdma_set_option(rs->cm_id, RDMA_OPTION_ID,
+ RDMA_OPTION_ID_AFONLY,
+ (void *) optval, optlen);
+ opt_on = *(int *) optval;
+ break;
+ default:
+ break;
+ }
+ case SOL_RDMA:
+ if (rs->state >= rs_opening) {
+ ret = ERR(EINVAL);
+ break;
+ }
+
+ switch (optname) {
+ case RDMA_SQSIZE:
+ rs->sq_size = min((*(uint32_t *) optval), RS_QP_MAX_SIZE);
+ ret = 0;
+ break;
+ case RDMA_RQSIZE:
+ rs->rq_size = min((*(uint32_t *) optval), RS_QP_MAX_SIZE);
+ ret = 0;
+ break;
+ case RDMA_INLINE:
+ rs->sq_inline = min(*(uint32_t *) optval, RS_QP_MAX_SIZE);
+ if (rs->sq_inline < RS_MIN_INLINE)
+ rs->sq_inline = RS_MIN_INLINE;
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!ret && opts) {
+ if (opt_on)
+ *opts |= (uint64_t)(1 << optname);
+ else
+ *opts &= ~(1 << optname);
+ }
+
+ return ret;
+}
+
+__declspec(dllexport)
+int rgetsockopt(int socket, int level, int optname,
+ void *optval, socklen_t *optlen)
+{
+ struct rsocket *rs;
+ int ret = 0;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ switch (level) {
+ case SOL_SOCKET:
+ switch (optname) {
+ case SO_REUSEADDR:
+ case SO_KEEPALIVE:
+ case SO_OOBINLINE:
+ *((int *) optval) = !!(rs->so_opts & (uint64_t)(1 << optname));
+ *optlen = sizeof(int);
+ break;
+ case SO_RCVBUF:
+ *((int *) optval) = rs->rbuf_size;
+ *optlen = sizeof(int);
+ break;
+ case SO_SNDBUF:
+ *((int *) optval) = rs->sbuf_size;
+ *optlen = sizeof(int);
+ break;
+ case SO_LINGER:
+ /* Value is inverted so default so_opt = 0 is on */
+ ((struct linger *) optval)->l_onoff =
+ !(rs->so_opts & (uint64_t)(1 << optname));
+ ((struct linger *) optval)->l_linger = 0;
+ *optlen = sizeof(struct linger);
+ break;
+ case SO_ERROR:
+ *((int *) optval) = rs->err;
+ *optlen = sizeof(int);
+ rs->err = 0;
+ break;
+ default:
+ ret = ENOTSUP;
+ break;
+ }
+ break;
+ case IPPROTO_TCP:
+ switch (optname) {
+ case TCP_NODELAY:
+ *((int *) optval) = !!(rs->tcp_opts & (uint64_t)(1 << optname));
+ *optlen = sizeof(int);
+ break;
+ case TCP_MAXSEG:
+ *((int *) optval) = (rs->cm_id && rs->cm_id->route.num_paths) ?
+ 1 << (7 + rs->cm_id->route.path_rec->mtu) :
+ 2048;
+ *optlen = sizeof(int);
+ break;
+ default:
+ ret = ENOTSUP;
+ break;
+ }
+ break;
+ case IPPROTO_IPV6:
+ switch (optname) {
+ case IPV6_V6ONLY:
+ *((int *) optval) = !!(rs->ipv6_opts & (uint64_t)(1 << optname));
+ *optlen = sizeof(int);
+ break;
+ default:
+ ret = ENOTSUP;
+ break;
+ }
+ break;
+ case SOL_RDMA:
+ switch (optname) {
+ case RDMA_SQSIZE:
+ *((int *) optval) = rs->sq_size;
+ *optlen = sizeof(int);
+ break;
+ case RDMA_RQSIZE:
+ *((int *) optval) = rs->rq_size;
+ *optlen = sizeof(int);
+ break;
+ case RDMA_INLINE:
+ *((int *) optval) = rs->sq_inline;
+ *optlen = sizeof(int);
+ break;
+ default:
+ ret = ENOTSUP;
+ break;
+ }
+ break;
+ default:
+ ret = ENOTSUP;
+ break;
+ }
+
+ return ERR/*rdma_seterrno*/(ret);
+}
+
+__declspec(dllexport)
+int rfcntl(int socket, int cmd, ... /* arg */ )
+{
+ struct rsocket *rs;
+ va_list args;
+ long param;
+ int ret = 0;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ va_start(args, cmd);
+ switch (cmd) {
+ case F_GETFL:
+ return (int) rs->fd_flags;
+ case F_SETFL:
+ param = va_arg(args, long);
+ if (param & O_NONBLOCK)
+ ret = rs_set_nonblocking(rs, O_NONBLOCK);
+
+ if (!ret)
+ rs->fd_flags |= param;
+ break;
+ default:
+ ret = ERR(ENOTSUP);
+ }
+ va_end(args);
+ return ret;
+}
+
+__declspec(dllexport)
+int rioctlsocket(int socket, long cmd, u_long* argp)
+{
+ struct rsocket *rs;
+
+ wsa_setlasterror(0);
+ rs = (struct rsocket *)idm_at(&idm, socket);
+ switch (cmd) {
+ case FIONBIO:
+ if (*argp)
+ rs->fd_flags |= O_NONBLOCK;
+ return rs_set_nonblocking(rs, *argp ? O_NONBLOCK : 0);
+ case FIONREAD:
+ case SIOCATMARK:
+ return ERR(ENOTSUP);
+ default:
+ return ERR(ENOTSUP);
+ }
+}
+
+/**
+ * \brief Get current RSockets status information for the calling process
+ * (by calling librdmacm.dll directly).
+ *
+ * \param lppStatusBuffer Pointer to a buffer with an array of RS_STATUS information entries
+ * to be allocated and returned. The caller is responsible for
+ * deallocating that buffer via free() when it is no longer needed.
+ *
+ * \return The number of RS_STATUS entries contained in the status buffer
+ * returned by *lppStatusBuffer.
+ */
+int rsGetStatus ( __out LPRS_STATUS *lppStatusBuffer )
+{
+ DWORD i, e;
+ DWORD dwNumEntries = 0;
+ struct rsocket *rs;
+ char *pst = "";
+
+ for (i = 0; i < IDX_MAX_INDEX; i++)
+ {
+ if (idm_lookup(&idm, i))
+ dwNumEntries++;
+ }
+
+ if ( 0 == dwNumEntries ||
+ NULL == (*lppStatusBuffer = (LPRS_STATUS)malloc(dwNumEntries * sizeof(**lppStatusBuffer)))
+ )
+ {
+ return 0;
+ }
+
+ for (
+ i = 0, e = 0;
+ i < IDX_MAX_INDEX && e < dwNumEntries;
+ i++
+ )
+ {
+ if (rs = (struct rsocket *)idm_lookup(&idm, i))
+ {
+ lppStatusBuffer[e]->src_addr = rs->cm_id->route.addr.src_addr;
+ lppStatusBuffer[e]->dst_addr = rs->cm_id->route.addr.dst_addr;
+ switch (rs->state)
+ {
+ case rs_init: pst = "INIT"; break;
+ case rs_bound: pst = "BOUND"; break;
+ case rs_listening: pst = "LISTENING"; break;
+ case rs_opening: pst = "OPENING"; break;
+ case rs_resolving_addr: pst = "RESOLVING_ADDR"; break;
+ case rs_resolving_route:pst = "RESOLVING_ROUTE";break;
+ case rs_connecting: pst = "CONNECTING"; break;
+ case rs_accepting: pst = "ACCEPTING"; break;
+ case rs_connected: pst = "CONNECTED"; break;
+ case rs_connect_wr: pst = "CONNECT_WR"; break;
+ case rs_connect_rd: pst = "CONNECT_RD"; break;
+ case rs_connect_rdwr: pst = "CONNECT_RDWR"; break;
+ case rs_connect_error: pst = "CONNECT_ERROR"; break;
+ case rs_disconnected: pst = "DISCONNECTED"; break;
+ case rs_error: pst = "ERROR"; break;
+ default: pst = "UNKNOWN";
+ }
+ strncpy(lppStatusBuffer[e]->state, pst, sizeof(lppStatusBuffer[e]->state) - 1);
+ lppStatusBuffer[e]->state[sizeof(lppStatusBuffer[e]->state)] = '\0';
+ e++;
+ }
+ }
+
+ return e;
+}
Index: ulp/librdmacm/src/Sources
===================================================================
--- ulp/librdmacm/src/Sources (revision 3419)
+++ ulp/librdmacm/src/Sources (working copy)
@@ -12,10 +12,12 @@
cma.rc \
cma_main.cpp \
cma.cpp \
- addrinfo.cpp
+ addrinfo.cpp \
+ rsocket.cpp \
+ indexer.cpp

INCLUDES = ..\include;..\..\..\inc;..\..\..\inc\user;..\..\libibverbs\include;\
- ..\..\..\inc\user\linux;
+ ..\..\..\inc\user\linux

USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_CMA_SYMBOLS

@@ -26,4 +28,5 @@
$(SDK_LIB_PATH)\iphlpapi.lib \
$(TARGETPATH)\*\ibat.lib \
$(TARGETPATH)\*\libibverbs.lib \
- $(TARGETPATH)\*\winverbs.lib
+ $(TARGETPATH)\*\winverbs.lib \
+ $(TARGETPATH)\*\complib.lib



This message and attachment(s) are intended solely for use by the addressee and may contain information that is privileged, confidential or otherwise exempt from disclosure under applicable law.

If you are not the intended recipient or agent thereof responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited.

If you have received this communication in error, please notify the sender immediately by telephone and with a 'reply' message.

Thank you for your co-operation.


------_=_NextPart_002_01CDEF18.1141EC2A
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML xmlns:o = "urn:schemas-microsoft-com:office:office" xmlns:st1 =
"urn:schemas-microsoft-com:office:smarttags"><HEAD>
<META content="text/html; charset=iso-8859-1" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.7601.17998"></HEAD>
<BODY>
<DIV><SPAN class=187323909-29112012><FONT face=Arial><FONT size=2>Hi
everyone,</FONT></FONT></SPAN></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012></SPAN></FONT>&nbsp;</DIV>
<DIV><FONT size=2 face=Arial><SPAN class=187323909-29112012>Attached please find
a patch for review and discussion (based on rev. 3419 of <A
href="https://beany.openfabrics.org/svnrepo/ofw/gen1/trunk/">https://beany.openfabrics.org/svnrepo/ofw/gen1/trunk/</A>)
which contains a porting of Sean Hefty's RSockets protocol to Windows.
</SPAN></FONT><FONT size=2 face=Arial><SPAN class=187323909-29112012>Many thanks
to Sean at this point for his cooperation and support.</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012></SPAN></FONT>&nbsp;</DIV>
<DIV><FONT size=2 face=Arial><SPAN class=187323909-29112012>What I've done is
merging the librdmacm sources from current Linux OFED with the respective OFW
sources, resulting in a librdmacm.dll acting as a Winsock base transport
provider (similar to the ulp/wsd component). In contrast to WSD or ND, that
RSocket<SPAN class=221182909-10012013>s</SPAN> provider allows socket-based RDMA
communication not only between Windows hosts, but also between Windows and
Linux.</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012></SPAN></FONT>&nbsp;</DIV>
<DIV><FONT size=2 face=Arial><SPAN class=187323909-29112012>For further comments
and documentation please look at ulp\librdmacm\RSocket.txt.</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN class=187323909-29112012>
<DIV><SPAN class=187323909-29112012><FONT size=2><SPAN
class=282400818-19122012><FONT
color=#0000ff></FONT></SPAN></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=187323909-29112012><FONT size=2><SPAN
class=282400818-19122012><FONT color=#0000ff><FONT color=#000000>The
contribution of the patch is in the name and on behalf of Océ Printing Systems
GmbH. The use of the patch is based in principle upon the terms of the BSD as
noted in ulp\librdmacm\RSocket.txt.</FONT></FONT></SPAN></FONT></SPAN></DIV>
<DIV><SPAN class=187323909-29112012><FONT size=2><SPAN
class=282400818-19122012></SPAN></FONT></SPAN><SPAN
class=187323909-29112012><FONT color=#0000ff size=2><SPAN
class=282400818-19122012></SPAN></FONT></SPAN>&nbsp;</DIV></SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN class=187323909-29112012>Thanks and
Regards,</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012>Hubert</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012></SPAN></FONT>&nbsp;</DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012>===================================================================</SPAN></FONT></DIV>
<DIV><FONT size=2 face=Arial><SPAN
class=187323909-29112012><BR>&nbsp;</DIV></SPAN></FONT><FONT size=2
face=Arial><SPAN class=187323909-29112012>
<DIV>
<DIV align=left>Index:
etc/user/gtod.c<BR>===================================================================<BR>---
etc/user/gtod.c&nbsp;(revision 3419)<BR>+++ etc/user/gtod.c&nbsp;(working
copy)<BR>@@ -57,11 +57,12 @@<BR>&nbsp;&nbsp;ptv-&gt;tv_usec = (long) (ll -
((LONGLONG)(ptv-&gt;tv_sec) * 10000000)) / 10;<BR>&nbsp;}<BR>&nbsp;<BR>-<BR>-//
static __inline<BR>-int gettimeofday(struct timeval *ptv, void
*ignored)<BR>+static /*__inline*/ int gettimeofday(struct timeval *ptv, void
*ignored)<BR>&nbsp;{<BR>&nbsp;&nbsp;static int QueryCounter =
2;<BR>+&nbsp;static LARGE_INTEGER Frequency = {10000000,0}; /* prevent division
by 0 */<BR>+&nbsp;static LARGE_INTEGER Offset; /* counter offset for right
time*/<BR>+&nbsp;static LARGE_INTEGER LastCounter;<BR>&nbsp;&nbsp;FILETIME
CurrentTime;<BR>&nbsp;&nbsp;UNREFERENCED_PARAMETER(ignored);&nbsp;&nbsp;&nbsp;&nbsp;
<BR>&nbsp;<BR>@@ -69,9 +70,6
@@<BR>&nbsp;<BR>&nbsp;&nbsp;if(QueryCounter)<BR>&nbsp;&nbsp;{<BR>-&nbsp;&nbsp;static
LARGE_INTEGER Frequency;<BR>-&nbsp;&nbsp;static LARGE_INTEGER Offset; /* counter
offset for right time*/<BR>-&nbsp;&nbsp;static LARGE_INTEGER
LastCounter;<BR>&nbsp;&nbsp;&nbsp;LARGE_INTEGER
Time;<BR>&nbsp;&nbsp;&nbsp;LARGE_INTEGER Counter;<BR>&nbsp;&nbsp;<BR>@@ -80,13
+78,15 @@<BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;if(QueryCounter ==
2)<BR>&nbsp;&nbsp;&nbsp;{<BR>-&nbsp;&nbsp;&nbsp;QueryCounter =
1;<BR>-&nbsp;&nbsp;&nbsp;if(!QueryPerformanceFrequency(&amp;Frequency))<BR>+&nbsp;&nbsp;&nbsp;if(QueryPerformanceFrequency(&amp;Frequency))<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;QueryCounter
= 1; // But now the Frequency is
valid!<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;QueryCounter
= 0;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Frequency.QuadPart = 10000000; /* prevent
division by 0
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>-&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;/* get
time as a large integer */<BR>&nbsp;&nbsp;&nbsp;&nbsp;Counter.HighPart &amp;=
0x7FL; /* Clear high bits to prevent overflow
*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;Offset.LowPart =
CurrentTime.dwLowDateTime;<BR>Index:
inc/user/linux/_fcntl.h<BR>===================================================================<BR>---
inc/user/linux/_fcntl.h&nbsp;(revision 0)<BR>+++
inc/user/linux/_fcntl.h&nbsp;(working copy)<BR>@@ -0,0 +1,47 @@<BR>+/*<BR>+ *
Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights reserved.<BR>+
*<BR>+ * This software is available to you under the BSD license below:<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source and binary
forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification, are
permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; conditions
are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source
code must retain the above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
copyright notice, this list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer.<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary form must reproduce
the above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice,
this list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided
with the distribution.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the
name Oce Printing Systems GmbH nor the names<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the authors may be used to
endorse or promote products<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
derived from this software without specific prior written<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; permission.<BR>+ *<BR>+ * THIS
SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY EXPRESS OR IMPLIED<BR>+ * WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF<BR>+ * MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN
NO EVENT SHALL THE AUTHORS<BR>+ * OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE
FOR ANY DIRECT,<BR>+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF<BR>+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;<BR>+ * OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF<BR>+ * LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+ * (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE. <BR>+ */<BR>+<BR>+#ifndef
__FCNTL_H_<BR>+#define __FCNTL_H_<BR>+<BR>+#include
&lt;fcntl.h&gt;<BR>+<BR>+#define
F_GETFL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* get file-&gt;f_flags */<BR>+#define
F_SETFL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* set file-&gt;f_flags
*/<BR>+<BR>+#endif&nbsp;/* __FCNTL_H_ */<BR>Index:
tools/dirs<BR>===================================================================<BR>---
tools/dirs&nbsp;(revision 3419)<BR>+++ tools/dirs&nbsp;(working copy)<BR>@@ -6,4
+6,5 @@<BR>&nbsp;&nbsp;part_man&nbsp;\<BR>&nbsp;&nbsp;infiniband-diags
\<BR>&nbsp;&nbsp;qlgcvnic_config&nbsp;\<BR>-&nbsp;ndinstall<BR>+&nbsp;ndinstall
\<BR>+&nbsp;rsinstall<BR>Index:
tools/rsinstall/dirs<BR>===================================================================<BR>---
tools/rsinstall/dirs&nbsp;(revision 0)<BR>+++ tools/rsinstall/dirs&nbsp;(working
copy)<BR>@@ -0,0 +1,2 @@<BR>+DIRS=\<BR>+&nbsp;user<BR>Index:
tools/rsinstall/user/makefile<BR>===================================================================<BR>---
tools/rsinstall/user/makefile&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/makefile&nbsp;(working copy)<BR>@@ -0,0 +1,8 @@<BR>+#<BR>+#
DO NOT EDIT THIS FILE!!!&nbsp; Edit .\sources. if you want to add a new
source<BR>+# file to this component.&nbsp; This file merely indirects to the
real make file<BR>+# that is shared by all the driver components of the OpenIB
Windows project.<BR>+#<BR>+MINIMUM_NT_TARGET_VERSION=0x502<BR>+<BR>+!INCLUDE
..\..\..\inc\openib.def<BR>Index:
tools/rsinstall/user/rsinstall.c<BR>===================================================================<BR>---
tools/rsinstall/user/rsinstall.c&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/rsinstall.c&nbsp;(working copy)<BR>@@ -0,0 +1,724
@@<BR>+/*<BR>+ * Copyright (c) 2005 SilverStorm Technologies.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+/*<BR>+ *&nbsp;Module Name: rsinstall.c<BR>+
*&nbsp;Description: This module installs/removes a winsock service provider for
infiniband. <BR>+ *&nbsp;execute:<BR>+ *&nbsp;To install the service
provider<BR>+ *&nbsp;&nbsp;installsp -i&nbsp;&nbsp;&nbsp;&nbsp; <BR>+ *&nbsp;To
remove the service provider<BR>+ *&nbsp;&nbsp;installsp -r<BR>+
*/<BR>+<BR>+#include "rdma/rwinsock.h"<BR>+#include
&lt;ws2spi.h&gt;<BR>+#include &lt;stdio.h&gt;<BR>+#include
&lt;stdlib.h&gt;<BR>+<BR>+/* Initialize the LSP's provider path for Infiband
Service Provider dll */<BR>+static const WCHAR provider_path[] =
L"%SYSTEMROOT%\\system32\\librdmacm.dll";<BR>+static const WCHAR
provider_prefix[] =L" RSockets for InfiniBand"; //includes one
whitespace<BR>+static const char provider_name[] = VER_PROVIDER
;//L"%VER_PROVIDER% RSockets for InfiniBand"; //(VER_PROVIDER ##
WINDIR);<BR>+static const char openib_key_name[] =
IB_COMPANYNAME;<BR>+<BR>+#ifdef PERFMON_ENABLED<BR>+#include
"LoadPerf.h"<BR>+#include "rdma/rs_regpath.h"<BR>+<BR>+typedef struct
_pm_symbol_def<BR>+{<BR>+&nbsp;DWORD&nbsp;name_def;<BR>+&nbsp;CHAR&nbsp;name_str[40];<BR>+&nbsp;CHAR&nbsp;name_desc[40];<BR>+&nbsp;CHAR&nbsp;help_desc[256];<BR>+<BR>+}
pm_symbol_def_t;<BR>+<BR>+static pm_symbol_def_t&nbsp;
_pm_symbols[]=<BR>+{<BR>+&nbsp;{ RS_PM_OBJ,<BR>+&nbsp;"RS_PM_OBJ",<BR>+&nbsp;"IB
RSockets",<BR>+&nbsp;"InfiniBand RSockets Provider."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(BYTES_SEND),<BR>+&nbsp;"RS_PM_BYTES_TX_SEC",<BR>+&nbsp;"Send
bytes/sec",<BR>+&nbsp;"Send bytes/second, excluding RDMA
Write."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(BYTES_RECV),<BR>+&nbsp;"RS_PM_BYTES_RX_SEC",<BR>+&nbsp;"Recv
bytes/sec",<BR>+&nbsp;"Receive bytes/second, excluding RDMA
Read."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(BYTES_WRITE),<BR>+&nbsp;"RS_PM_RDMA_WR_SEC",<BR>+&nbsp;"RDMA Write
bytes/sec",<BR>+&nbsp;"RDMA Write bytes/second."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(BYTES_READ),<BR>+&nbsp;"RS_PM_RDMA_RD_SEC",<BR>+&nbsp;"RDMA Read
bytes/sec",<BR>+&nbsp;"RDMA Read bytes/second."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(BYTES_TOTAL),<BR>+&nbsp;"RS_PM_BYTES_SEC",<BR>+&nbsp;"Total
bytes/sec",<BR>+&nbsp;"Total bytes transmitted per second, including send,
"<BR>+&nbsp;"receive, RDMA Write, and RDMA Read."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(COMP_SEND),<BR>+&nbsp;"RS_PM_SEND_COMPLETIONS_SEC",<BR>+&nbsp;"Send
Completions/sec",<BR>+&nbsp;"Send and RDMA Write
Completions/sec."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(COMP_RECV),<BR>+&nbsp;"RS_PM_RECV_COMPLETIONS_SEC",<BR>+&nbsp;"Recv
Completions/sec",<BR>+&nbsp;"Recv and RDMA Read
Completions/sec."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(COMP_TOTAL),<BR>+&nbsp;"RS_PM_COMPLETIONS_SEC",<BR>+&nbsp;"Total
Completions/sec",<BR>+&nbsp;"Total Completions processed per
second."<BR>+&nbsp;},<BR>+&nbsp;{
RS_PM_COUNTER(INTR_TOTAL),<BR>+&nbsp;"RS_PM_COMPLETIONS_INTR",<BR>+&nbsp;"Total
Interrupts/sec",<BR>+&nbsp;"Completion Queue events per
second."<BR>+&nbsp;}<BR>+};<BR>+<BR>+#define RS_PM_NUM_SYMBOLS&nbsp;
(sizeof(_pm_symbols)/sizeof(pm_symbol_def_t))<BR>+#define RS_PM_LANGUAGE "009"
/* good for English */<BR>+<BR>+static CHAR *<BR>+_RSGenerateFileName(char
*header,&nbsp;char *file )<BR>+{<BR>+&nbsp;DWORD size1, size;<BR>+&nbsp;CHAR
*full_file_name;<BR>+&nbsp;int header_len = header == NULL ? 0 :
strlen(header);<BR>+<BR>+&nbsp;size = GetTempPath(0, NULL);<BR>+&nbsp;if (size
== 0)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "GetTempPath&nbsp; failed\n"
);<BR>+&nbsp;&nbsp;return NULL;<BR>+&nbsp;}<BR>+&nbsp;size1 = size +
strlen(file) + header_len;<BR>+&nbsp;full_file_name = HeapAlloc (GetProcessHeap
(), HEAP_ZERO_MEMORY, size1);<BR>+&nbsp;if ( full_file_name == NULL
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "GetTempPath&nbsp; failed\n"
);<BR>+&nbsp;&nbsp;return NULL;<BR>+&nbsp;}<BR>+&nbsp;size1 = GetTempPath(size,
full_file_name + header_len);<BR>+&nbsp;if (size != size1 + 1)
<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "Very strange, GetTempPath&nbsp;
returned something different\n" );<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (),
0, full_file_name);<BR>+&nbsp;&nbsp;return NULL;<BR>+&nbsp;}<BR>+&nbsp;if
(header_len != 0)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;memcpy(full_file_name, header,
header_len);<BR>+&nbsp;}<BR>+&nbsp;strcat(full_file_name,
file);<BR>+&nbsp;return full_file_name;<BR>+}<BR>+<BR>+<BR>+static
DWORD<BR>+_RSPerfmonIniFilesGenerate( void
)<BR>+{<BR>+&nbsp;FILE&nbsp;*f_handle;<BR>+&nbsp;DWORD&nbsp;num;<BR>+&nbsp;DWORD
ret = ERROR_SUCCESS;<BR>+&nbsp;char *ibsp_pm_sym_file = NULL;<BR>+&nbsp;char
*ibsp_pm_ini_file = NULL;<BR>+<BR>+&nbsp;/* create ".h" file first
*/<BR>+&nbsp;ibsp_pm_sym_file = _RSGenerateFileName(NULL,
RS_PM_SYM_H_FILE);<BR>+&nbsp;if( !ibsp_pm_sym_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "_RSGenerateFileName&nbsp;
failed\n" );<BR>+&nbsp;&nbsp;ret = ERROR_NOT_ENOUGH_MEMORY;<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;f_handle = fopen( ibsp_pm_sym_file, "w+"
);<BR>+<BR>+&nbsp;if( !f_handle )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr,
"Create Header file %s failed\n", ibsp_pm_sym_file );<BR>+&nbsp;&nbsp;ret =
ERROR_FILE_INVALID;<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;fprintf(<BR>+&nbsp;&nbsp;f_handle, "/* %s
Generated by program */ \r\n", ibsp_pm_sym_file
);<BR>+&nbsp;&nbsp;<BR>+&nbsp;<BR>+&nbsp;for( num = 0; num &lt;
RS_PM_NUM_SYMBOLS; num++ )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( f_handle,
"#define\t%s\t%d\r\n",<BR>+&nbsp;&nbsp;&nbsp;_pm_symbols[num].name_str,
_pm_symbols[num].name_def );<BR>+&nbsp;}<BR>+<BR>+&nbsp;fflush( f_handle
);<BR>+&nbsp;fclose( f_handle );<BR>+<BR>+&nbsp;/* create 'ini' file next
*/<BR>+&nbsp;ibsp_pm_ini_file = _RSGenerateFileName(NULL,
RS_PM_INI_FILE);<BR>+&nbsp;if( !ibsp_pm_sym_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "_RSGenerateFileName&nbsp;
failed\n" );<BR>+&nbsp;&nbsp;ret = ERROR_NOT_ENOUGH_MEMORY;<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+&nbsp;f_handle = fopen( ibsp_pm_ini_file, "w+"
);<BR>+<BR>+&nbsp;if( !f_handle )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr,
"Create INI file %s&nbsp; failed\n", ibsp_pm_ini_file );<BR>+&nbsp;&nbsp;ret =
ERROR_FILE_INVALID;<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;fprintf( f_handle,
"[info]\r\ndrivername="
RS_PM_SUBKEY_NAME<BR>+&nbsp;&nbsp;"\r\nsymbolfile=%s\r\n\r\n", ibsp_pm_sym_file
);<BR>+&nbsp;fprintf( f_handle,"[languages]\r\n"
RS_PM_LANGUAGE<BR>+&nbsp;&nbsp;"=language" RS_PM_LANGUAGE "\r\n\r\n"
);<BR>+<BR>+&nbsp;fprintf( f_handle, <BR>+&nbsp;&nbsp;"[objects]\r\n%s_"
RS_PM_LANGUAGE
"_NAME=%s\r\n\r\n[text]\r\n",<BR>+&nbsp;&nbsp;_pm_symbols[0].name_str,
_pm_symbols[0].name_desc );<BR>+&nbsp;<BR>+&nbsp;for( num = 0; num &lt;
RS_PM_NUM_SYMBOLS; num++ )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( f_handle,"%s_"
RS_PM_LANGUAGE "_NAME=%s\r\n",<BR>+&nbsp;&nbsp;&nbsp;_pm_symbols[num].name_str,
_pm_symbols[num].name_desc );<BR>+&nbsp;&nbsp;fprintf( f_handle,"%s_"
RS_PM_LANGUAGE "_HELP=%s\r\n",<BR>+&nbsp;&nbsp;&nbsp;_pm_symbols[num].name_str,
_pm_symbols[num].help_desc );<BR>+&nbsp;}<BR>+<BR>+&nbsp;fflush( f_handle
);<BR>+&nbsp;fclose( f_handle );<BR>+<BR>+Cleanup:<BR>+&nbsp;if (
ibsp_pm_sym_file )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (), 0,
ibsp_pm_sym_file);<BR>+&nbsp;}<BR>+&nbsp;if ( ibsp_pm_ini_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (), 0,
ibsp_pm_ini_file);<BR>+&nbsp;}<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+<BR>+static
void<BR>+_RSPerfmonIniFilesRemove( void )<BR>+{<BR>+&nbsp;char *ibsp_pm_sym_file
= NULL;<BR>+&nbsp;char *ibsp_pm_ini_file = NULL;<BR>+<BR>+&nbsp;ibsp_pm_sym_file
= _RSGenerateFileName(NULL, RS_PM_SYM_H_FILE);<BR>+&nbsp;if( !ibsp_pm_sym_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "_RSGenerateFileName&nbsp;
failed\n" );<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;ibsp_pm_ini_file = _RSGenerateFileName(NULL,
RS_PM_INI_FILE);<BR>+&nbsp;if( !ibsp_pm_sym_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr, "_RSGenerateFileName&nbsp;
failed\n" );<BR>+&nbsp;&nbsp;goto Cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if(
!DeleteFile( ibsp_pm_ini_file ) )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr,
"Delete file %s failed status %d\n",<BR>+&nbsp;&nbsp;&nbsp;ibsp_pm_ini_file,
GetLastError() );<BR>+&nbsp;}<BR>+&nbsp;if( !DeleteFile( ibsp_pm_sym_file )
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr,"Delete file %s failed status
%d\n",<BR>+&nbsp;&nbsp;&nbsp;ibsp_pm_sym_file, GetLastError()
);<BR>+&nbsp;}<BR>+<BR>+Cleanup:&nbsp;<BR>+&nbsp;if ( ibsp_pm_sym_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (), 0,
ibsp_pm_sym_file);<BR>+&nbsp;}<BR>+&nbsp;if ( ibsp_pm_ini_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (), 0,
ibsp_pm_ini_file);<BR>+&nbsp;}<BR>+&nbsp;<BR>+}<BR>+<BR>+<BR>+/* Try to create
Performance Register Keys */<BR>+static LONG<BR>+_RSPerfmonRegisterKeys( void
)<BR>+{<BR>+&nbsp;LONG&nbsp;reg_status;<BR>+&nbsp;HKEY&nbsp;pm_hkey;<BR>+&nbsp;DWORD&nbsp;typesSupp
= 7;<BR>+<BR>+&nbsp;reg_status = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,<BR>+&nbsp;&nbsp;RS_PM_REGISTRY_PATH RS_PM_SUBKEY_PERF, 0,
NULL,<BR>+&nbsp;&nbsp;REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&amp;pm_hkey, NULL );<BR>+<BR>+&nbsp;if( reg_status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"_RSPerfmonRegisterKeys Create Key %s failed with
%d\n",<BR>+&nbsp;&nbsp;&nbsp;RS_PM_REGISTRY_PATH RS_PM_SUBKEY_PERF, reg_status
);<BR>+&nbsp;&nbsp;return reg_status;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/*
create/assign values to the key */<BR>+&nbsp;RegSetValueExW( pm_hkey,
L"Library", 0, REG_EXPAND_SZ,<BR>+&nbsp;&nbsp;(LPBYTE)provider_path,
sizeof(provider_path) );<BR>+<BR>+&nbsp;RegSetValueEx( pm_hkey, TEXT("Open"), 0,
REG_SZ,<BR>+&nbsp;&nbsp;(LPBYTE)TEXT("RSPmOpen"), sizeof(TEXT("RSPmOpen"))
);<BR>+<BR>+&nbsp;RegSetValueEx( pm_hkey, TEXT("Collect"), 0,
REG_SZ,<BR>+&nbsp;&nbsp;(LPBYTE)TEXT("RSPmCollectData"),
sizeof(TEXT("RSPmCollectData")) );<BR>+<BR>+&nbsp;RegSetValueEx( pm_hkey,
TEXT("Close"), 0, REG_SZ,<BR>+&nbsp;&nbsp;(LPBYTE)TEXT("RSPmClose"),
sizeof(TEXT("RSPmClose")) );<BR>+<BR>+&nbsp;RegFlushKey( pm_hkey
);<BR>+&nbsp;RegCloseKey( pm_hkey );<BR>+<BR>+&nbsp;reg_status = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,<BR>+&nbsp;&nbsp;RS_PM_EVENTLOG_PATH, 0,
NULL,<BR>+&nbsp;&nbsp;REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&amp;pm_hkey, NULL );<BR>+<BR>+&nbsp;if( reg_status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(stderr, "Create EventLog Key failed with
%d\n", reg_status );<BR>+&nbsp;&nbsp;return
reg_status;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/* create/assign values to the key
*/<BR>+&nbsp;RegSetValueExW( pm_hkey, L"EventMessageFile", 0,
REG_EXPAND_SZ,\<BR>+&nbsp;&nbsp;(LPBYTE)provider_path, sizeof(provider_path)
);<BR>+<BR>+&nbsp;RegSetValueEx( pm_hkey, TEXT("TypesSupported"), 0,
REG_DWORD,<BR>+&nbsp;&nbsp;(LPBYTE)&amp;typesSupp, sizeof(typesSupp)
);<BR>+<BR>+&nbsp;RegFlushKey( pm_hkey );<BR>+&nbsp;RegCloseKey( pm_hkey
);<BR>+<BR>+&nbsp;return reg_status;<BR>+}<BR>+<BR>+<BR>+/* Try to destroy
Performance Register Keys */<BR>+static LONG<BR>+_RSPerfmonDeregisterKeys( void
)<BR>+{<BR>+&nbsp;LONG&nbsp;reg_status;<BR>+<BR>+&nbsp;reg_status =
RegDeleteKeyEx( HKEY_LOCAL_MACHINE,<BR>+&nbsp;&nbsp;RS_PM_REGISTRY_PATH
RS_PM_SUBKEY_PERF,<BR>+&nbsp;&nbsp;(KEY_WOW64_32KEY | KEY_WOW64_64KEY), 0
);<BR>+<BR>+&nbsp;if( reg_status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"_RSPerfmonRegisterKeys Remove SubKey failed with
%d\n",<BR>+&nbsp;&nbsp;&nbsp;GetLastError()
);<BR>+&nbsp;}<BR>+<BR>+&nbsp;reg_status = RegDeleteKeyEx(
HKEY_LOCAL_MACHINE,<BR>+&nbsp;&nbsp;RS_PM_REGISTRY_PATH, (KEY_WOW64_32KEY |
KEY_WOW64_64KEY), 0 );<BR>+<BR>+&nbsp;if( reg_status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"_RSPerfmonRegisterKeys Remove SubKey failed with
%d\n",<BR>+&nbsp;&nbsp;&nbsp;GetLastError()
);<BR>+&nbsp;}<BR>+<BR>+&nbsp;reg_status = RegDeleteKeyEx(
HKEY_LOCAL_MACHINE,<BR>+&nbsp;&nbsp;RS_PM_EVENTLOG_PATH, (KEY_WOW64_32KEY |
KEY_WOW64_64KEY), 0 );<BR>+<BR>+&nbsp;if( reg_status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"_RSPerfmonRegisterKeys Remove SubKey failed with
%d\n",<BR>+&nbsp;&nbsp;&nbsp;GetLastError() );<BR>+&nbsp;}<BR>+<BR>+&nbsp;return
reg_status;<BR>+}<BR>+<BR>+<BR>+/*<BR>+ * functions will try to register
performance counters<BR>+ * definitions with PerfMon application.<BR>+ * API
externally called by lodctr.exe/unlodctr.exe utilities.<BR>+ */<BR>+static
DWORD<BR>+_RSPerfmonRegisterCounters( void )<BR>+{<BR>+&nbsp;DWORD
status;<BR>+&nbsp;char *ibsp_pm_ini_file = NULL;<BR>+<BR>+&nbsp;ibsp_pm_ini_file
= _RSGenerateFileName("unused ", RS_PM_INI_FILE);<BR>+&nbsp;if(
!ibsp_pm_ini_file )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf( stderr,
"_RSGenerateFileName&nbsp; failed\n" );<BR>+&nbsp;&nbsp;status =
ERROR_NOT_ENOUGH_MEMORY;<BR>+&nbsp;&nbsp;goto
Cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/*<BR>+&nbsp; * format commandline string,
as per SDK :<BR>+&nbsp; *&nbsp;Pointer to a null-terminated string that consists
of one or more <BR>+&nbsp; *&nbsp;arbitrary letters, a space, and then the name
of the initialization<BR>+&nbsp; *&nbsp;file.<BR>+&nbsp; */<BR>+&nbsp;status =
LoadPerfCounterTextStrings( ibsp_pm_ini_file, TRUE );<BR>+&nbsp;if( status !=
ERROR_SUCCESS )<BR>+&nbsp;{<BR>+&nbsp;&nbsp;status =
GetLastError();<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"IBSPPerfmonRegisterCounters install failed status
%d\n", status );<BR>+&nbsp;}<BR>+Cleanup:&nbsp;<BR>+&nbsp;if ( ibsp_pm_ini_file
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;HeapFree (GetProcessHeap (), 0,
ibsp_pm_ini_file);<BR>+&nbsp;}<BR>+<BR>+&nbsp;return
status;<BR>+}<BR>+<BR>+<BR>+/*<BR>+ * functions will try to unregister
performance counters<BR>+ * definitions with PerfMon application.<BR>+ * API
externally called by lodctr.exe/unlodctr.exe utilities.<BR>+ */<BR>+static
DWORD<BR>+_RSPerfmonDeregisterCounters( void )<BR>+{<BR>+&nbsp;DWORD
status;<BR>+<BR>+&nbsp;/*<BR>+&nbsp; * format commandline string, as per SDK
:<BR>+&nbsp; *&nbsp;Pointer to a null-terminated string that consists of one or
more <BR>+&nbsp; *&nbsp;arbitrary letters, a space, and then the name of the
initialization<BR>+&nbsp; *&nbsp;file.<BR>+&nbsp; */<BR>+&nbsp;status =
UnloadPerfCounterTextStrings(<BR>+&nbsp;&nbsp;TEXT("unused ")
TEXT(RS_PM_SUBKEY_NAME), TRUE );<BR>+&nbsp;if( status != ERROR_SUCCESS
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;fprintf(
stderr,<BR>+&nbsp;&nbsp;&nbsp;"IBSPPerfmonDeregisterCounters remove failed
status %d\n",<BR>+&nbsp;&nbsp;&nbsp;status );<BR>+&nbsp;}<BR>+&nbsp;return
status;<BR>+}<BR>+<BR>+#endif /* PERFMON_ENABLED */<BR>+<BR>+<BR>+/*<BR>+ *
Function: usage<BR>+ *&nbsp;&nbsp; Description: Prints usage information.<BR>+
*/<BR>+static void<BR>+usage (char *progname)<BR>+{<BR>+&nbsp;printf ("usage: %s
[-i/-r [-p]]\n", progname);<BR>+&nbsp;printf ("&nbsp;&nbsp;&nbsp; -i
[path]&nbsp; Install the service
provider,\n"<BR>+&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
optionally specify full pathname of
DLL\n"<BR>+&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;
-r&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Remove the %s service
provider\n"<BR>+&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp; -r &lt;name&gt;&nbsp;
Remove the specified service
provider\n"<BR>+&nbsp;&nbsp;&nbsp;"&nbsp;&nbsp;&nbsp;
-l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List service
providers\n",VER_PROVIDER);<BR>+}<BR>+<BR>+<BR>+/* Function:
print_providers<BR>+ *&nbsp;&nbsp; Description: <BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
This function prints out each entry in the Winsock catalog.<BR>+*/<BR>+static
void print_providers(void)<BR>+{<BR>+&nbsp;WSAPROTOCOL_INFOW
*protocol_info;<BR>+&nbsp;unsigned int protocol_count;<BR>+&nbsp;unsigned int
i;<BR>+&nbsp;DWORD protocol_size;<BR>+&nbsp;INT err_no;<BR>+&nbsp;int
rc;<BR>+<BR>+&nbsp;/* Find the size of the buffer */<BR>+&nbsp;protocol_size =
0;<BR>+&nbsp;rc = WSCEnumProtocols (NULL, NULL, &amp;protocol_size,
&amp;err_no);<BR>+&nbsp;if (rc == SOCKET_ERROR &amp;&amp; err_no != WSAENOBUFS)
{<BR>+&nbsp;&nbsp;printf("WSCEnumProtocols() returned error (%d)\n",
err_no);<BR>+&nbsp;&nbsp;return;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/* Allocate the
buffer */<BR>+&nbsp;protocol_info = HeapAlloc (GetProcessHeap (),
HEAP_ZERO_MEMORY, protocol_size);<BR>+&nbsp;if (protocol_info == NULL)
{<BR>+&nbsp;&nbsp;printf("HeapAlloc()
failed\n");<BR>+&nbsp;&nbsp;return;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/* Enumerate the
catalog for real */<BR>+&nbsp;rc = WSCEnumProtocols (NULL, protocol_info,
&amp;protocol_size, &amp;err_no);<BR>+&nbsp;if (rc == SOCKET_ERROR)
{<BR>+&nbsp;&nbsp;printf("WSCEnumProtocols returned error for real enumeration
(%d)\n",<BR>+&nbsp;&nbsp;&nbsp; err_no);<BR>+&nbsp;&nbsp;HeapFree
(GetProcessHeap (), 0,
protocol_info);<BR>+&nbsp;&nbsp;return;<BR>+&nbsp;}<BR>+<BR>+&nbsp;protocol_count
= rc;<BR>+<BR>+&nbsp;for (i = 0; i &lt; protocol_count; i++)
{<BR>+&nbsp;&nbsp;printf ("%010d - %S\n",
protocol_info[i].dwCatalogEntryId,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;protocol_info[i].szProtocol);<BR>+&nbsp;}<BR>+<BR>+&nbsp;HeapFree
(GetProcessHeap (), 0,
protocol_info);<BR>+<BR>+&nbsp;return;<BR>+}<BR>+<BR>+/*<BR>+ * Function:
install_provider<BR>+ *&nbsp;&nbsp; Description: installs the service
provider<BR>+ */<BR>+static void install_provider(LPWSTR
szProviderPath)<BR>+{<BR>+&nbsp;int rc;<BR>+&nbsp;INT err_no;<BR>+&nbsp;LONG
reg_error;<BR>+&nbsp;WSAPROTOCOL_INFOW provider;<BR>+&nbsp;HKEY
hkey;<BR>+&nbsp;&nbsp;&nbsp; size_t res;<BR>+&nbsp;&nbsp;&nbsp; size_t
st_len;<BR>+<BR>+&nbsp;ZeroMemory(&amp;provider,
sizeof(provider));<BR>+&nbsp;<BR>+&nbsp;/* Setup the values in PROTOCOL_INFO
*/<BR>+&nbsp;provider.dwServiceFlags1 = <BR>+&nbsp;&nbsp;XP1_GUARANTEED_DELIVERY
| <BR>+&nbsp;&nbsp;XP1_GUARANTEED_ORDER | <BR>+&nbsp;&nbsp;XP1_MESSAGE_ORIENTED
|<BR>+&nbsp;&nbsp;XP1_GRACEFUL_CLOSE;<BR>+&nbsp;provider.dwServiceFlags2 =
0;&nbsp;/* Reserved */<BR>+&nbsp;provider.dwServiceFlags3 = 0;&nbsp;/* Reserved
*/<BR>+&nbsp;provider.dwServiceFlags4 = 0;&nbsp;/* Reserved */<BR>+// SAN
provider only:&nbsp;provider.dwProviderFlags =
PFL_HIDDEN;<BR>+&nbsp;provider.ProviderId = rsProviderGuid;&nbsp;/* Service
Provider ID provided by vendor. */<BR>+&nbsp;provider.dwCatalogEntryId =
0;<BR>+&nbsp;provider.ProtocolChain.ChainLen = 1;&nbsp;/* Base Protocol Service
Provider */<BR>+&nbsp;provider.iVersion = 2;&nbsp;/* don't know what it is
*/<BR>+&nbsp;provider.iAddressFamily = AF_INET;<BR>+&nbsp;provider.iMaxSockAddr
= 16;<BR>+&nbsp;provider.iMinSockAddr = 16;<BR>+&nbsp;provider.iSocketType =
SOCK_STREAM;<BR>+&nbsp;provider.iProtocol =
IPPROTO_TCP;<BR>+&nbsp;provider.iProtocolMaxOffset =
0;<BR>+&nbsp;provider.iNetworkByteOrder =
BIGENDIAN;<BR>+&nbsp;provider.iSecurityScheme =
SECURITY_PROTOCOL_NONE;<BR>+&nbsp;provider.dwMessageSize = 0xFFFFFFFF; /* IB
supports 32-bit lengths for data transfers on RC
*/<BR>+&nbsp;provider.dwProviderReserved = 0;<BR>+<BR>+&nbsp;st_len =
strlen(provider_name);<BR>+&nbsp;rc = mbstowcs(provider.szProtocol,
provider_name, st_len); //do not count \0<BR>+&nbsp;// We can't use there
mbstowcs_s <BR>+&nbsp;//rc = mbstowcs_s(&amp;convertedChars,
provider.szProtocol, sizeof(provider_name), provider_name,
);<BR>+&nbsp;&nbsp;&nbsp; if (rc&nbsp; != st_len)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
printf("&lt;install_provider&gt; Can't convert string %s to
WCHAR\n",provider_name);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
printf("Converted %d from %d\n", rc, st_len);<BR>+&nbsp;&nbsp;&nbsp;
}<BR>+&nbsp;&nbsp;&nbsp; wcscpy( provider.szProtocol + st_len,
provider_prefix);<BR>+&nbsp;&nbsp;&nbsp; wprintf(L"Provider protocol = %s\n",
provider.szProtocol);<BR>+&nbsp;wprintf(L"Provider path&nbsp;&nbsp;&nbsp;&nbsp;
= %s\n", szProviderPath);<BR>+<BR>+&nbsp;rc =
WSCInstallProvider(<BR>+&nbsp;&nbsp;(LPGUID)&amp;rsProviderGuid, szProviderPath,
&amp;provider, 1, &amp;err_no );<BR>+&nbsp;if( rc == SOCKET_ERROR
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;if( err_no == WSANO_RECOVERY
)<BR>+&nbsp;&nbsp;&nbsp;printf("The provider is already
installed\n");<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;printf("install_provider:
WSCInstallProvider failed: %d\n", err_no);<BR>+&nbsp;}<BR>+}<BR>+<BR>+/*<BR>+ *
Function: remove_provider<BR>+ *&nbsp;&nbsp; Description: removes our
provider.<BR>+ */<BR>+static void remove_provider( const char* const
provider_name )<BR>+{<BR>+&nbsp;int rc;<BR>+&nbsp;int err_no;<BR>+&nbsp;LONG
reg_error;<BR>+&nbsp;HKEY hkey;<BR>+<BR>+&nbsp;/* Remove from the catalog
*/<BR>+&nbsp;rc = WSCDeinstallProvider((LPGUID)&amp;rsProviderGuid,
&amp;err_no);<BR>+&nbsp;if (rc == SOCKET_ERROR) {<BR>+&nbsp;&nbsp;printf
("WSCDeinstallProvider failed: %d\n", err_no);<BR>+&nbsp;}<BR>+<BR>+#if 0 //def
_WIN64<BR>+&nbsp;/* Remove from the 32-bit catalog too! */<BR>+&nbsp;rc =
WSCDeinstallProvider32((LPGUID)&amp;rsProviderGuid, &amp;err_no);<BR>+&nbsp;if
(rc == SOCKET_ERROR) {<BR>+&nbsp;&nbsp;printf ("WSCDeinstallProvider32 failed:
%d\n", err_no);<BR>+&nbsp;}<BR>+#endif&nbsp;/* _WIN64 */<BR>+}<BR>+<BR>+/*
Function: main<BR>+ *<BR>+ *&nbsp; Description:<BR>+ *&nbsp;&nbsp;&nbsp; Parse
the command line arguments and call either the install or remove<BR>+
*&nbsp;&nbsp;&nbsp; routine.<BR>+ */<BR>+int __cdecl main (int argc, char
*argv[])<BR>+{<BR>+&nbsp;WSADATA wsd;<BR>+&nbsp;size_t&nbsp; rc,
st_len;<BR>+&nbsp;WCHAR&nbsp;&nbsp;
arg_provider_path[MAX_PATH];<BR>+<BR>+&nbsp;/* Load Winsock */<BR>+&nbsp;if
(WSAStartup (MAKEWORD (2, 2), &amp;wsd) != 0) {<BR>+&nbsp;&nbsp;printf
("InstallSP: Unable to load Winsock: %d\n", GetLastError
());<BR>+&nbsp;&nbsp;return -1;<BR>+&nbsp;}<BR>+<BR>+&nbsp;/* Confirm that the
WinSock DLL supports 2.2. Note that if the<BR>+&nbsp; * DLL supports versions
greater than 2.2 in addition to 2.2, it<BR>+&nbsp; * will still return 2.2 in
wVersion since that is the version we<BR>+&nbsp; * requested. */<BR>+&nbsp;if
(LOBYTE (wsd.wVersion) != 2 || HIBYTE (wsd.wVersion) != 2)
{<BR>+<BR>+&nbsp;&nbsp;/* Tell the user that we could not find a usable WinSock
DLL. */<BR>+&nbsp;&nbsp;WSACleanup
();<BR>+&nbsp;&nbsp;printf<BR>+&nbsp;&nbsp;&nbsp;("InstallSP: Unable to find a
usable version of Winsock DLL\n");<BR>+&nbsp;&nbsp;return
-1;<BR>+&nbsp;}<BR>+&nbsp;if (argc &lt; 2) {<BR>+&nbsp;&nbsp;usage
(argv[0]);<BR>+&nbsp;&nbsp;return -1;<BR>+&nbsp;}<BR>+&nbsp;if ((strlen
(argv[1]) != 2) &amp;&amp; (argv[1][0] != '-')<BR>+&nbsp;&nbsp;&amp;&amp;
(argv[1][0] != '/')) {<BR>+&nbsp;&nbsp;usage (argv[0]);<BR>+&nbsp;&nbsp;return
-1;<BR>+&nbsp;}<BR>+&nbsp;switch (tolower (argv[1][1])) {<BR>+<BR>+&nbsp;case
'i':<BR>+&nbsp;&nbsp;/* Install the Infiniband Service Provider
*/<BR>+&nbsp;&nbsp;if( argc == 2
)&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;wcscpy_s(arg_provider_path,
sizeof(arg_provider_path)/2,
provider_path);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;else
{<BR>+&nbsp;&nbsp;&nbsp;st_len = strlen( argv[2] );<BR>+&nbsp;&nbsp;&nbsp;if
(st_len &gt;= sizeof(arg_provider_path)/2)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;st_len =
sizeof(arg_provider_path)/2 - 1;<BR>+&nbsp;&nbsp;&nbsp;rc =
mbstowcs(arg_provider_path, argv[2], st_len); //do not count
\0<BR>+&nbsp;&nbsp;&nbsp;arg_provider_path[st_len] =
'\0';<BR>+&nbsp;&nbsp;&nbsp;// We can't use there mbstowcs_s
<BR>+&nbsp;&nbsp;&nbsp;if (rc != st_len)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;printf("Can't convert string \"%s\" to WCHAR\n",
argv[2]);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;printf("Converted %d from %d\n", rc,
st_len);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;wcscpy_s(arg_provider_path,
sizeof(arg_provider_path)/2,
provider_path);<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;install_provider(
arg_provider_path );<BR>+<BR>+#ifdef
PERFMON_ENABLED<BR>+&nbsp;&nbsp;_RSPerfmonIniFilesGenerate();<BR>+&nbsp;&nbsp;if
( _RSPerfmonRegisterKeys() == ERROR_SUCCESS
)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;_RSPerfmonRegisterCounters();<BR>+#endif<BR>+&nbsp;&nbsp;break;<BR>+<BR>+&nbsp;case
'r':<BR>+&nbsp;&nbsp;/* Remove the service provider */<BR>+&nbsp;&nbsp;if( argc
== 2 )<BR>+&nbsp;&nbsp;&nbsp;remove_provider( openib_key_name
);<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;remove_provider( argv[2]
);<BR>+#ifdef
PERFMON_ENABLED<BR>+&nbsp;&nbsp;_RSPerfmonIniFilesRemove();<BR>+&nbsp;&nbsp;if (
_RSPerfmonDeregisterCounters() == ERROR_SUCCESS
)<BR>+&nbsp;&nbsp;&nbsp;_RSPerfmonDeregisterKeys();<BR>+#endif<BR>+&nbsp;&nbsp;break;<BR>+<BR>+&nbsp;case
'l':<BR>+&nbsp;&nbsp;/* List existing providers
*/<BR>+&nbsp;&nbsp;print_providers();<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;usage
(argv[0]);<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+<BR>+&nbsp;WSACleanup
();<BR>+<BR>+&nbsp;return 0;<BR>+}<BR>Index:
tools/rsinstall/user/rsinstall.exe.manifest<BR>===================================================================<BR>---
tools/rsinstall/user/rsinstall.exe.manifest&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/rsinstall.exe.manifest&nbsp;(working copy)<BR>@@ -0,0 +1,10
@@<BR>+&lt;?xml version="1.0" encoding="UTF-8"
standalone="yes"?&gt;<BR>+&nbsp;&nbsp;&nbsp; &lt;assembly
xmlns="urn:schemas-microsoft-com:asm.v1"
manifestVersion="1.0"&gt;<BR>+&nbsp;&nbsp;&nbsp; &lt;trustInfo
xmlns="urn:schemas-microsoft-com:asm.v3"&gt;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;security&gt;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;requestedPrivileges&gt;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;requestedExecutionLevel level="requireAdministrator"
uiAccess="false"/&gt;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;/requestedPrivileges&gt;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&lt;/security&gt;<BR>+&nbsp;&nbsp;&nbsp;
&lt;/trustInfo&gt;<BR>+&lt;/assembly&gt;&nbsp;&nbsp; <BR>\ No newline at end of
file<BR>Index:
tools/rsinstall/user/rsinstall.rc<BR>===================================================================<BR>---
tools/rsinstall/user/rsinstall.rc&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/rsinstall.rc&nbsp;(working copy)<BR>@@ -0,0 +1,45
@@<BR>+/*<BR>+ * Copyright (c) 2005 SilverStorm Technologies.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the OpenIB.org
BSD license<BR>+ * below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution
and use in source and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
without modification, are permitted provided that the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp; conditions are met:<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source code must retain the
above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this
list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer.<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary form must reproduce
the above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice,
this list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided
with the distribution.<BR>+ *<BR>+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
WARRANTY OF ANY KIND,<BR>+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF<BR>+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>+ *
SOFTWARE.<BR>+ */<BR>+<BR>+<BR>+#include &lt;oib_ver.h&gt;<BR>+<BR>+#define
VER_FILETYPE&nbsp;&nbsp;&nbsp;&nbsp;VFT_APP<BR>+#define
VER_FILESUBTYPE&nbsp;&nbsp;&nbsp;&nbsp;VFT2_UNKNOWN<BR>+<BR>+#ifdef
DBG<BR>+#define VER_FILEDESCRIPTION_STR&nbsp;&nbsp;"RSockets for InfiniBand
installer (Debug)"<BR>+#else<BR>+#define
VER_FILEDESCRIPTION_STR&nbsp;&nbsp;"RSockets for InfiniBand
installer"<BR>+#endif<BR>+<BR>+#define
VER_INTERNALNAME_STR&nbsp;&nbsp;"rsinstall.exe"<BR>+#define
VER_ORIGINALFILENAME_STR&nbsp;"rsinstall.exe"<BR>+<BR>+#include
&lt;common.ver&gt;<BR>Index:
tools/rsinstall/user/RsInstall.sln<BR>===================================================================<BR>---
tools/rsinstall/user/RsInstall.sln&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/RsInstall.sln&nbsp;(working copy)<BR>@@ -0,0 +1,21
@@<BR>+Microsoft Visual Studio Solution File, Format Version
8.00<BR>+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "InstallSP",
"InstallSP.vcproj",
"{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}"<BR>+&nbsp;ProjectSection(ProjectDependencies)
=
postProject<BR>+&nbsp;EndProjectSection<BR>+EndProject<BR>+Global<BR>+&nbsp;GlobalSection(SolutionConfiguration)
= preSolution<BR>+&nbsp;&nbsp;Debug = Debug<BR>+&nbsp;&nbsp;Release =
Release<BR>+&nbsp;EndGlobalSection<BR>+&nbsp;GlobalSection(ProjectConfiguration)
=
postSolution<BR>+&nbsp;&nbsp;{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Debug.ActiveCfg
=
Debug|Win32<BR>+&nbsp;&nbsp;{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Debug.Build.0
=
Debug|Win32<BR>+&nbsp;&nbsp;{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Release.ActiveCfg
=
Release|Win32<BR>+&nbsp;&nbsp;{B3A2B7A0-1906-413E-A457-8AD2FC5E88BB}.Release.Build.0
=
Release|Win32<BR>+&nbsp;EndGlobalSection<BR>+&nbsp;GlobalSection(ExtensibilityGlobals)
=
postSolution<BR>+&nbsp;EndGlobalSection<BR>+&nbsp;GlobalSection(ExtensibilityAddIns)
= postSolution<BR>+&nbsp;EndGlobalSection<BR>+EndGlobal<BR>Index:
tools/rsinstall/user/SOURCES<BR>===================================================================<BR>---
tools/rsinstall/user/SOURCES&nbsp;(revision 0)<BR>+++
tools/rsinstall/user/SOURCES&nbsp;(working copy)<BR>@@ -0,0 +1,30
@@<BR>+TARGETNAME=rsinstall<BR>+TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)<BR>+TARGETTYPE=PROGRAM<BR>+UMTYPE=console<BR>+USE_MSVCRT=1<BR>+<BR>+INCLUDES=..\..\..\inc;\<BR>+&nbsp;..\..\..\inc\user;\<BR>+&nbsp;..\..\..\ulp\librdmacm\include;\<BR>+&nbsp;$(PLATFORM_SDK_PATH)\include;<BR>+<BR>+SOURCES=
\<BR>+&nbsp;rsinstall.rc
\<BR>+&nbsp;rsinstall.c<BR>+<BR>+USER_C_FLAGS=$(USER_C_FLAGS)<BR>+#
-DPERFMON_ENABLED<BR>+<BR>+TARGETLIBS=\<BR>+&nbsp;$(SDK_LIB_PATH)\ws2_32.lib
\<BR>+&nbsp;$(SDK_LIB_PATH)\LoadPerf.lib <BR>+<BR>+MSC_WARNING_LEVEL=
/W3<BR>+<BR>+LINKER_FLAGS=$(LINKER_FLAGS)<BR>+<BR>+SXS_APPLICATION_MANIFEST=rsinstall.exe.manifest<BR>+SXS_ASSEMBLY_VERSION=1.0<BR>+SXS_ASSEMBLY_NAME=rsinstall.exe<BR>+SXS_ASSEMBLY_LANGUAGE=0000<BR>Index:
ulp/librdmacm/AUTHORS<BR>===================================================================<BR>---
ulp/librdmacm/AUTHORS&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/AUTHORS&nbsp;(working copy)<BR>@@ -1 +1,2 @@<BR>&nbsp;Sean
Hefty&nbsp;&nbsp;&lt;<A
href="mailto:***@intel.com">***@intel.com</A>&gt;<BR>+Hubert
Schmitt&nbsp;&lt;<A
href="mailto:***@oce.com">***@oce.com</A>&gt;<BR>Index:
ulp/librdmacm/COPYING<BR>===================================================================<BR>---
ulp/librdmacm/COPYING&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/COPYING&nbsp;(working copy)<BR>@@ -1,11 +1,11
@@<BR>&nbsp;Copyright (c) 2008 Intel Corporation.&nbsp; All rights
reserved.<BR>+Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>&nbsp;<BR>-This software is available to you under the
OpenFabrics.org BSD license<BR>-below:<BR>+This software is available to you
under the BSD license below:<BR>&nbsp;<BR>-&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with
or<BR>-&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided
that the following<BR>-&nbsp;&nbsp;&nbsp;&nbsp; conditions are
met:<BR>+&nbsp;&nbsp;&nbsp; Redistribution and use in source and binary forms,
with or<BR>+&nbsp;&nbsp;&nbsp; without modification, are permitted provided that
the following<BR>+&nbsp;&nbsp;&nbsp; conditions are
met:<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of
source code must retain the
above<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this
list of conditions and the following<BR>@@ -16,11 +16,21
@@<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the
documentation and/or other
materials<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the
distribution.<BR>&nbsp;<BR>-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
OF ANY KIND,<BR>-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF<BR>-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AWV<BR>-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>-BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>-ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN<BR>-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE<BR>-SOFTWARE.<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce
Printing Systems GmbH nor the
names<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the authors may be used
to endorse or promote products<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
derived from this software without specific prior
written<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+<BR>+&nbsp;&nbsp;&nbsp; THIS SOFTWARE IS PROVIDED&nbsp; “AS IS”
AND ANY EXPRESS OR IMPLIED<BR>+&nbsp;&nbsp;&nbsp; WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE WARRANTIES OF<BR>+&nbsp;&nbsp;&nbsp; MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE AND<BR>+&nbsp;&nbsp;&nbsp; NON-INFRINGEMENT ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+&nbsp;&nbsp;&nbsp; OR CONTRIBUTOR
OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+&nbsp;&nbsp;&nbsp; INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+&nbsp;&nbsp;&nbsp; DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF<BR>+&nbsp;&nbsp;&nbsp; SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;<BR>+&nbsp;&nbsp;&nbsp; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF<BR>+&nbsp;&nbsp;&nbsp; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT<BR>+&nbsp;&nbsp;&nbsp; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF<BR>+&nbsp;&nbsp;&nbsp; THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY<BR>+&nbsp;&nbsp;&nbsp; OF SUCH DAMAGE. <BR>Index:
ulp/librdmacm/examples/rstream/makefile<BR>===================================================================<BR>---
ulp/librdmacm/examples/rstream/makefile&nbsp;(revision 0)<BR>+++
ulp/librdmacm/examples/rstream/makefile&nbsp;(working copy)<BR>@@ -0,0 +1,7
@@<BR>+#<BR>+# DO NOT EDIT THIS FILE!!!&nbsp; Edit .\sources. if you want to add
a new source<BR>+# file to this component.&nbsp; This file merely indirects to
the real make file<BR>+# that is shared by all the driver components of the
OpenIB Windows project.<BR>+#<BR>+<BR>+!INCLUDE
..\..\..\..\inc\openib.def<BR>Index:
ulp/librdmacm/examples/rstream/makefile.inc<BR>===================================================================<BR>---
ulp/librdmacm/examples/rstream/makefile.inc&nbsp;(revision 0)<BR>+++
ulp/librdmacm/examples/rstream/makefile.inc&nbsp;(working copy)<BR>@@ -0,0 +1,8
@@<BR>+Custom_target:<BR>+!if "$(BUILD_PASS)" == "PASS2" || "$(BUILD_PASS)" ==
"ALL"<BR>+<BR>+!endif<BR>+<BR>+<BR>+<BR>+!INCLUDE
..\..\..\..\inc\mod_ver.def<BR>Index:
ulp/librdmacm/examples/rstream/rstream.c<BR>===================================================================<BR>---
ulp/librdmacm/examples/rstream/rstream.c&nbsp;(revision 0)<BR>+++
ulp/librdmacm/examples/rstream/rstream.c&nbsp;(working copy)<BR>@@ -0,0 +1,749
@@<BR>+/*<BR>+ * Copyright (c) 2011-2012 Intel Corporation.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE. <BR>+ */<BR>+ <BR>+#include &lt;stdio.h&gt;<BR>+#include
&lt;stdlib.h&gt;<BR>+#include &lt;string.h&gt;<BR>+#include
&lt;_errno.h&gt;<BR>+#include "../../../../etc/user/gtod.c" //
getimeofday()<BR>+#include "getopt.c"<BR>+#include
&lt;sys/types.h&gt;<BR>+#include &lt;sys/time.h&gt;<BR>+#include
&lt;netdb.h&gt;<BR>+#include &lt;_fcntl.h&gt;<BR>+#include
&lt;unistd.h&gt;<BR>+<BR>+#include "..\src\openib_osd.h"<BR>+#include
&lt;rdma/rdma_cma.h&gt;<BR>+#include &lt;rdma/rwinsock.h&gt;<BR>+<BR>+#define
MSG_DONTWAIT 0x80<BR>+<BR>+struct test_size_param {<BR>+&nbsp;int
size;<BR>+&nbsp;int option;<BR>+};<BR>+<BR>+static struct test_size_param
test_size[] = {<BR>+&nbsp;{ 1 &lt;&lt;&nbsp; 6, 0 },<BR>+&nbsp;{ 1
&lt;&lt;&nbsp; 7, 1 }, { (1 &lt;&lt;&nbsp; 7) + (1 &lt;&lt;&nbsp; 6),
1},<BR>+&nbsp;{ 1 &lt;&lt;&nbsp; 8, 1 }, { (1 &lt;&lt;&nbsp; 8) + (1
&lt;&lt;&nbsp; 7), 1},<BR>+&nbsp;{ 1 &lt;&lt;&nbsp; 9, 1 }, { (1 &lt;&lt;&nbsp;
9) + (1 &lt;&lt;&nbsp; 8), 1},<BR>+&nbsp;{ 1 &lt;&lt; 10, 1 }, { (1 &lt;&lt; 10)
+ (1 &lt;&lt;&nbsp; 9), 1},<BR>+&nbsp;{ 1 &lt;&lt; 11, 1 }, { (1 &lt;&lt; 11) +
(1 &lt;&lt; 10), 1},<BR>+&nbsp;{ 1 &lt;&lt; 12, 0 }, { (1 &lt;&lt; 12) + (1
&lt;&lt; 11), 1},<BR>+&nbsp;{ 1 &lt;&lt; 13, 1 }, { (1 &lt;&lt; 13) + (1
&lt;&lt; 12), 1},<BR>+&nbsp;{ 1 &lt;&lt; 14, 1 }, { (1 &lt;&lt; 14) + (1
&lt;&lt; 13), 1},<BR>+&nbsp;{ 1 &lt;&lt; 15, 1 }, { (1 &lt;&lt; 15) + (1
&lt;&lt; 14), 1},<BR>+&nbsp;{ 1 &lt;&lt; 16, 0 }, { (1 &lt;&lt; 16) + (1
&lt;&lt; 15), 1},<BR>+&nbsp;{ 1 &lt;&lt; 17, 1 }, { (1 &lt;&lt; 17) + (1
&lt;&lt; 16), 1},<BR>+&nbsp;{ 1 &lt;&lt; 18, 1 }, { (1 &lt;&lt; 18) + (1
&lt;&lt; 17), 1},<BR>+&nbsp;{ 1 &lt;&lt; 19, 1 }, { (1 &lt;&lt; 19) + (1
&lt;&lt; 18), 1},<BR>+&nbsp;{ 1 &lt;&lt; 20, 0 }, { (1 &lt;&lt; 20) + (1
&lt;&lt; 19), 1},<BR>+&nbsp;{ 1 &lt;&lt; 21, 1 }, { (1 &lt;&lt; 21) + (1
&lt;&lt; 20), 1},<BR>+&nbsp;{ 1 &lt;&lt; 22, 1 }, { (1 &lt;&lt; 22) + (1
&lt;&lt; 21), 1},<BR>+};<BR>+#define TEST_CNT (sizeof test_size / sizeof
test_size[0])<BR>+<BR>+enum rs_optimization
{<BR>+&nbsp;opt_mixed,<BR>+&nbsp;opt_latency,<BR>+&nbsp;opt_bandwidth<BR>+};<BR>+<BR>+static
int rs, lrs;<BR>+static int use_rs = 1;<BR>+static int use_async = 0;<BR>+static
int verify = 0;<BR>+static int flags = 0; //MSG_DONTWAIT;<BR>+static int
poll_timeout = 0;<BR>+static int custom;<BR>+static enum rs_optimization
optimization;<BR>+static int size_option;<BR>+static int iterations =
1;<BR>+static int transfer_size = 1000;<BR>+static int transfer_count =
1000;<BR>+static int buffer_size;<BR>+static char test_name[10] =
"custom";<BR>+static char *port = "7471";<BR>+static char *dst_addr;<BR>+static
char *src_addr;<BR>+static struct timeval start, end;<BR>+static void
*buf;<BR>+<BR>+#define
rs_socket(f,t,p)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; use_rs ?
WSASocket(f,t,p,rsGetProtocolInfo(NULL),0,0) : socket(f,t,p)<BR>+#define
rs_bind(s,a,l)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
bind(s,a,l)<BR>+#define
rs_listen(s,b)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
listen(s,b)<BR>+#define
rs_connect(s,a,l)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
connect(s,a,l)<BR>+#define
rs_accept(s,a,l)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
accept(s,a,l)<BR>+#define
rs_shutdown(s,h)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
shutdown(s,h)<BR>+#define
rs_close(s)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
closesocket(s)<BR>+#define
rs_recv(s,b,l,f)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
recv(s,b,l,f)<BR>+#define
rs_send(s,b,l,f)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
send(s,b,l,f)<BR>+#define rs_recvfrom(s,b,l,f,a,al)
recvfrom(s,b,l,f,a,al)<BR>+#define rs_sendto(s,b,l,f,a,al)&nbsp;&nbsp;
sendto(s,b,l,f,a,al)<BR>+#define rs_select(n,rf,wf,ef,t)&nbsp;&nbsp;
select(n,rf,wf,ef,t)<BR>+#define rs_ioctlsocket(s,c,p)&nbsp;&nbsp;&nbsp;&nbsp;
ioctlsocket(s,c,p)<BR>+#define rs_setsockopt(s,l,n,v,ol)
setsockopt(s,l,n,v,ol)<BR>+#define rs_getsockopt(s,l,n,v,ol)
getsockopt(s,l,n,v,ol)<BR>+<BR>+static void size_str(char *str, size_t ssize,
long long size)<BR>+{<BR>+&nbsp;long long base, fraction = 0;<BR>+&nbsp;char
mag;<BR>+<BR>+&nbsp;if (size &gt;= (1 &lt;&lt; 30)) {<BR>+&nbsp;&nbsp;base = 1
&lt;&lt; 30;<BR>+&nbsp;&nbsp;mag = 'g';<BR>+&nbsp;} else if (size &gt;= (1
&lt;&lt; 20)) {<BR>+&nbsp;&nbsp;base = 1 &lt;&lt; 20;<BR>+&nbsp;&nbsp;mag =
'm';<BR>+&nbsp;} else if (size &gt;= (1 &lt;&lt; 10)) {<BR>+&nbsp;&nbsp;base = 1
&lt;&lt; 10;<BR>+&nbsp;&nbsp;mag = 'k';<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;base
= 1;<BR>+&nbsp;&nbsp;mag = '\0';<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (size / base &lt;
10)<BR>+&nbsp;&nbsp;fraction = (size % base) * 10 / base;<BR>+&nbsp;if
(fraction) {<BR>+&nbsp;&nbsp;_snprintf(str, ssize, "%lld.%lld%c", size / base,
fraction, mag);<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;_snprintf(str, ssize,
"%lld%c", size / base, mag);<BR>+&nbsp;}<BR>+}<BR>+<BR>+static void cnt_str(char
*str, size_t ssize, long long cnt)<BR>+{<BR>+&nbsp;if (cnt &gt;=
1000000000)<BR>+&nbsp;&nbsp;_snprintf(str, ssize, "%lldb", cnt /
1000000000);<BR>+&nbsp;else if (cnt &gt;=
1000000)<BR>+&nbsp;&nbsp;_snprintf(str, ssize, "%lldm", cnt /
1000000);<BR>+&nbsp;else if (cnt &gt;= 1000)<BR>+&nbsp;&nbsp;_snprintf(str,
ssize, "%lldk", cnt / 1000);<BR>+&nbsp;else<BR>+&nbsp;&nbsp;_snprintf(str,
ssize, "%lld", cnt);<BR>+}<BR>+<BR>+static void
show_perf(void)<BR>+{<BR>+&nbsp;char str[32];<BR>+&nbsp;float
usec;<BR>+&nbsp;long long bytes;<BR>+<BR>+&nbsp;usec = (float)((end.tv_sec -
start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec));<BR>+&nbsp;bytes =
(long long) iterations * transfer_count * transfer_size * 2;<BR>+<BR>+&nbsp;/*
name size transfers iterations bytes seconds Gb/sec usec/xfer
*/<BR>+&nbsp;printf("%-10s", test_name);<BR>+&nbsp;size_str(str, sizeof str,
transfer_size);<BR>+&nbsp;printf("%-8s", str);<BR>+&nbsp;cnt_str(str, sizeof
str, transfer_count);<BR>+&nbsp;printf("%-8s", str);<BR>+&nbsp;cnt_str(str,
sizeof str, iterations);<BR>+&nbsp;printf("%-8s", str);<BR>+&nbsp;size_str(str,
sizeof str, bytes);<BR>+&nbsp;printf("%-8s",
str);<BR>+&nbsp;printf("%8.2fs%10.2f%11.2f\n",<BR>+&nbsp;&nbsp;usec / 1000000.,
(bytes * 8) / (1000. * usec),<BR>+&nbsp;&nbsp;(usec / iterations) /
(transfer_count * 2));<BR>+}<BR>+<BR>+static int size_to_count(int
size)<BR>+{<BR>+&nbsp;if (size &gt;= 1000000)<BR>+&nbsp;&nbsp;return
100;<BR>+&nbsp;else if (size &gt;= 100000)<BR>+&nbsp;&nbsp;return
1000;<BR>+&nbsp;else if (size &gt;= 10000)<BR>+&nbsp;&nbsp;return
10000;<BR>+&nbsp;else if (size &gt;= 1000)<BR>+&nbsp;&nbsp;return
100000;<BR>+&nbsp;else<BR>+&nbsp;&nbsp;return 1000000;<BR>+}<BR>+<BR>+static
void init_latency_test(int size)<BR>+{<BR>+&nbsp;char
sstr[5];<BR>+<BR>+&nbsp;size_str(sstr, sizeof sstr,
size);<BR>+&nbsp;_snprintf(test_name, sizeof test_name, "%s_lat",
sstr);<BR>+&nbsp;transfer_count = 1;<BR>+&nbsp;transfer_size =
size;<BR>+&nbsp;iterations = size_to_count(transfer_size);<BR>+}<BR>+<BR>+static
void init_bandwidth_test(int size)<BR>+{<BR>+&nbsp;char
sstr[5];<BR>+<BR>+&nbsp;size_str(sstr, sizeof sstr,
size);<BR>+&nbsp;_snprintf(test_name, sizeof test_name, "%s_bw",
sstr);<BR>+&nbsp;iterations = 1;<BR>+&nbsp;transfer_size =
size;<BR>+&nbsp;transfer_count =
size_to_count(transfer_size);<BR>+}<BR>+<BR>+static void format_buf(void *buf,
int size)<BR>+{<BR>+&nbsp;uint8_t *array = buf;<BR>+&nbsp;static uint8_t
data;<BR>+&nbsp;int i;<BR>+<BR>+&nbsp;for (i = 0; i &lt; size;
i++)<BR>+&nbsp;&nbsp;array[i] = data++;<BR>+}<BR>+<BR>+static int
verify_buf(void *buf, int size)<BR>+{<BR>+&nbsp;static long long
total_bytes;<BR>+&nbsp;uint8_t *array = buf;<BR>+&nbsp;static uint8_t
data;<BR>+&nbsp;int i;<BR>+<BR>+&nbsp;for (i = 0; i &lt; size; i++,
total_bytes++) {<BR>+&nbsp;&nbsp;if (array[i] != data++)
{<BR>+&nbsp;&nbsp;&nbsp;printf("data verification failed byte %lld\n",
total_bytes);<BR>+&nbsp;&nbsp;&nbsp;return
-1;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+static int
do_poll(struct pollfd
*fds)<BR>+{<BR>+&nbsp;int&nbsp;&nbsp;ret;<BR>+&nbsp;int&nbsp;&nbsp;nfds =
0;<BR>+&nbsp;fd_set&nbsp;readfds, writefds, exceptfds;<BR>+&nbsp;struct timeval
timeout;<BR>+&nbsp;<BR>+&nbsp;FD_ZERO(&amp;readfds);<BR>+&nbsp;FD_ZERO(&amp;writefds);<BR>+&nbsp;FD_ZERO(&amp;exceptfds);<BR>+&nbsp;<BR>+&nbsp;if
(fds-&gt;events &amp; (POLLIN | POLLHUP)) {<BR>+&nbsp;&nbsp;FD_SET(fds-&gt;fd,
&amp;readfds);<BR>+&nbsp;&nbsp;nfds++;<BR>+&nbsp;}<BR>+&nbsp;&nbsp;<BR>+&nbsp;if
(fds-&gt;events &amp; POLLOUT) {<BR>+&nbsp;&nbsp;FD_SET(fds-&gt;fd,
&amp;writefds);<BR>+&nbsp;&nbsp;nfds++;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(fds-&gt;events &amp; ~(POLLIN | POLLOUT)) {<BR>+&nbsp;&nbsp;FD_SET(fds-&gt;fd,
&amp;exceptfds);<BR>+&nbsp;&nbsp;nfds++;<BR>+&nbsp;}<BR>+<BR>+&nbsp;timeout.tv_sec&nbsp;
= poll_timeout / 1000;<BR>+&nbsp;timeout.tv_usec = timeout.tv_sec ? 0 :
poll_timeout * 1000;<BR>+&nbsp;<BR>+&nbsp;do {&nbsp;<BR>+&nbsp;&nbsp;ret =
rs_select(<BR>+&nbsp;&nbsp;&nbsp;nfds,<BR>+&nbsp;&nbsp;&nbsp;FD_ISSET(fds-&gt;fd,
&amp;readfds&nbsp; ) ? &amp;readfds&nbsp;&nbsp; :
NULL,<BR>+&nbsp;&nbsp;&nbsp;FD_ISSET(fds-&gt;fd, &amp;writefds ) ?
&amp;writefds&nbsp; : NULL,<BR>+&nbsp;&nbsp;&nbsp;FD_ISSET(fds-&gt;fd,
&amp;exceptfds) ? &amp;exceptfds : NULL,<BR>+&nbsp;&nbsp;&nbsp;poll_timeout &lt;
0 ? NULL : &amp;timeout<BR>+&nbsp;&nbsp;);<BR>+&nbsp;} while
(!ret);<BR>+&nbsp;<BR>+&nbsp;return ret == 1 ? 0 : ret;<BR>+}<BR>+<BR>+static
int send_xfer(int size)<BR>+{<BR>+&nbsp;struct pollfd fds;<BR>+&nbsp;int offset,
ret;<BR>+&nbsp;<BR>+&nbsp;if (verify)<BR>+&nbsp;&nbsp;format_buf(buf,
size);<BR>+<BR>+&nbsp;if (use_async) {<BR>+&nbsp;&nbsp;fds.fd =
rs;<BR>+&nbsp;&nbsp;fds.events = POLLOUT;<BR>+&nbsp;}<BR>+<BR>+&nbsp;for (offset
= 0; offset &lt; size; ) {<BR>+&nbsp;&nbsp;if (use_async)
{<BR>+&nbsp;&nbsp;&nbsp;ret = do_poll(&amp;fds);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;ret = (int)rs_send(rs, (char *)buf +
offset, size - offset, flags);<BR>+&nbsp;&nbsp;if (ret &gt; 0)
{<BR>+&nbsp;&nbsp;&nbsp;offset += ret;<BR>+&nbsp;&nbsp;} else if (errno !=
EWOULDBLOCK &amp;&amp; errno != EAGAIN)
{<BR>+&nbsp;&nbsp;&nbsp;perror("rsend");<BR>+&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+static int
recv_xfer(int size)<BR>+{<BR>+&nbsp;struct pollfd fds;<BR>+&nbsp;int offset,
ret;<BR>+&nbsp;<BR>+&nbsp;if (use_async) {<BR>+&nbsp;&nbsp;fds.fd =
rs;<BR>+&nbsp;&nbsp;fds.events = POLLIN;<BR>+&nbsp;}<BR>+<BR>+&nbsp;for (offset
= 0; offset &lt; size; ) {<BR>+&nbsp;&nbsp;if (use_async)
{<BR>+&nbsp;&nbsp;&nbsp;ret = do_poll(&amp;fds);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;ret = (int)rs_recv(rs, (char *)buf +
offset, size - offset, flags);<BR>+&nbsp;&nbsp;if (ret &gt; 0)
{<BR>+&nbsp;&nbsp;&nbsp;offset += ret;<BR>+&nbsp;&nbsp;} else if (errno !=
EWOULDBLOCK &amp;&amp; errno != EAGAIN)
{<BR>+&nbsp;&nbsp;&nbsp;perror("rrecv");<BR>+&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (verify)
{<BR>+&nbsp;&nbsp;ret = verify_buf(buf, size);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;return ret;<BR>+&nbsp;}<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+static int sync_test(void)<BR>+{<BR>+&nbsp;int
ret;<BR>+<BR>+&nbsp;ret = dst_addr ? send_xfer(16) : recv_xfer(16);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;return ret;<BR>+<BR>+&nbsp;return dst_addr ? recv_xfer(16)
: send_xfer(16);<BR>+}<BR>+<BR>+static int run_test(void)<BR>+{<BR>+&nbsp;int
ret, i, t;<BR>+<BR>+&nbsp;ret = sync_test();<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;goto out;<BR>+<BR>+&nbsp;gettimeofday(&amp;start,
NULL);<BR>+&nbsp;for (i = 0; i &lt; iterations; i++) {<BR>+&nbsp;&nbsp;for (t =
0; t &lt; transfer_count; t++) {<BR>+&nbsp;&nbsp;&nbsp;ret = dst_addr ?
send_xfer(transfer_size) :<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
recv_xfer(transfer_size);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;for (t = 0; t &lt; transfer_count; t++)
{<BR>+&nbsp;&nbsp;&nbsp;ret = dst_addr ? recv_xfer(transfer_size)
:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
send_xfer(transfer_size);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;gettimeofday(&amp;end,
NULL);<BR>+&nbsp;show_perf();<BR>+&nbsp;ret = 0;<BR>+<BR>+out:<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static void set_options(int rs)<BR>+{<BR>+&nbsp;int
val;<BR>+<BR>+&nbsp;if (buffer_size) {<BR>+&nbsp;&nbsp;rs_setsockopt(rs,
SOL_SOCKET, SO_SNDBUF, (void *)
&amp;buffer_size,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sizeof
buffer_size);<BR>+&nbsp;&nbsp;rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *)
&amp;buffer_size,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sizeof
buffer_size);<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;val = 1 &lt;&lt;
19;<BR>+&nbsp;&nbsp;rs_setsockopt(rs, SOL_SOCKET, SO_SNDBUF, (void *) &amp;val,
sizeof val);<BR>+&nbsp;&nbsp;rs_setsockopt(rs, SOL_SOCKET, SO_RCVBUF, (void *)
&amp;val, sizeof val);<BR>+&nbsp;}<BR>+<BR>+&nbsp;val =
1;<BR>+&nbsp;rs_setsockopt(rs, IPPROTO_TCP, TCP_NODELAY, (void *) &amp;val,
sizeof(val));<BR>+<BR>+&nbsp;val = 1;<BR>+&nbsp;if (flags &amp;
MSG_DONTWAIT)<BR>+&nbsp;&nbsp;rs_ioctlsocket(rs, FIONBIO, (u_long
*)&amp;val);<BR>+<BR>+&nbsp;if (use_rs) {<BR>+&nbsp;&nbsp;/* Inline size based
on experimental data */<BR>+&nbsp;&nbsp;if (optimization == opt_latency)
{<BR>+&nbsp;&nbsp;&nbsp;val = 384;<BR>+&nbsp;&nbsp;&nbsp;rs_setsockopt(rs,
SOL_RDMA, RDMA_INLINE, (char *)&amp;val, sizeof val);<BR>+&nbsp;&nbsp;} else if
(optimization == opt_bandwidth) {<BR>+&nbsp;&nbsp;&nbsp;val =
0;<BR>+&nbsp;&nbsp;&nbsp;rs_setsockopt(rs, SOL_RDMA, RDMA_INLINE, (char
*)&amp;val, sizeof val);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+}<BR>+<BR>+static int
server_listen(void)<BR>+{<BR>+&nbsp;struct addrinfo hints, *res;<BR>+&nbsp;int
val, ret;<BR>+<BR>+&nbsp;memset(&amp;hints, 0, sizeof
hints);<BR>+&nbsp;hints.ai_flags&nbsp; = RAI_PASSIVE;<BR>+&nbsp;hints.ai_family
= AF_INET;<BR>+&nbsp;hints.ai_socktype =
SOCK_STREAM;<BR>+&nbsp;hints.ai_protocol = IPPROTO_TCP;<BR>+&nbsp;<BR>+
&nbsp;ret = getaddrinfo(src_addr, port, &amp;hints, &amp;res);<BR>+&nbsp;if
(ret) {<BR>+&nbsp;&nbsp;perror("getaddrinfo");<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+<BR>+&nbsp;lrs = (int)(rs_socket(res-&gt;ai_family,
res-&gt;ai_socktype, res-&gt;ai_protocol));<BR>+&nbsp;if (lrs &lt; 0)
{<BR>+&nbsp;&nbsp;perror("rsocket");<BR>+&nbsp;&nbsp;ret =
lrs;<BR>+&nbsp;&nbsp;goto free;<BR>+&nbsp;}<BR>+<BR>+&nbsp;val =
1;<BR>+&nbsp;ret = rs_setsockopt(lrs, SOL_SOCKET, SO_REUSEADDR, (char
*)&amp;val, sizeof val);<BR>+&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;perror("rsetsockopt SO_REUSEADDR");<BR>+&nbsp;&nbsp;goto
close;<BR>+&nbsp;}<BR>+<BR>+&nbsp;ret = rs_bind(lrs, res-&gt;ai_addr,
res-&gt;ai_addrlen);<BR>+&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;perror("rbind");<BR>+&nbsp;&nbsp;goto
close;<BR>+&nbsp;}<BR>+<BR>+&nbsp;ret = rs_listen(lrs, 1);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;perror("rlisten");<BR>+<BR>+close:<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;rs_close(lrs);<BR>+free:<BR>+&nbsp;freeaddrinfo(res);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int server_connect(void)<BR>+{<BR>+&nbsp;struct
pollfd fds;<BR>+&nbsp;int ret = 0;<BR>+<BR>+&nbsp;set_options(lrs);<BR>+&nbsp;do
{<BR>+&nbsp;&nbsp;if (use_async) {<BR>+&nbsp;&nbsp;&nbsp;fds.fd =
lrs;<BR>+&nbsp;&nbsp;&nbsp;fds.events = POLLIN;<BR>+<BR>+&nbsp;&nbsp;&nbsp;ret =
do_poll(&amp;fds);<BR>+&nbsp;&nbsp;&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;perror("rpoll");<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;rs =
(int)(rs_accept(lrs, NULL, 0));<BR>+&nbsp;} while (rs &lt; 0 &amp;&amp; (errno
== EAGAIN || errno == EWOULDBLOCK));<BR>+<BR>+&nbsp;if (rs &lt; 0)
{<BR>+&nbsp;&nbsp;ret =
rs;<BR>+&nbsp;&nbsp;perror("raccept");<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+&nbsp;set_options(rs);<BR>+<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int client_connect(void)<BR>+{<BR>+&nbsp;struct
addrinfo hints, *res;<BR>+&nbsp;struct pollfd fds;<BR>+&nbsp;int ret,
err;<BR>+&nbsp;socklen_t len;<BR>+&nbsp;<BR>+&nbsp;memset(&amp;hints, 0, sizeof
hints);<BR>+&nbsp;hints.ai_flags&nbsp; = RAI_PASSIVE;<BR>+&nbsp;hints.ai_family
= AF_INET;<BR>+&nbsp;hints.ai_socktype =
SOCK_STREAM;<BR>+&nbsp;hints.ai_protocol = IPPROTO_TCP;<BR>+&nbsp;<BR>+
&nbsp;ret = getaddrinfo(dst_addr, port, &amp;hints, &amp;res);<BR>+&nbsp;if
(ret) {<BR>+&nbsp;&nbsp;perror("getaddrinfo");<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+<BR>+&nbsp;rs = (int)(rs_socket(res-&gt;ai_family,
res-&gt;ai_socktype, res-&gt;ai_protocol));<BR>+&nbsp;if (rs &lt; 0)
{<BR>+&nbsp;&nbsp;perror("rsocket");<BR>+&nbsp;&nbsp;ret =
rs;<BR>+&nbsp;&nbsp;goto
free;<BR>+&nbsp;}<BR>+<BR>+&nbsp;set_options(rs);<BR>+&nbsp;/* TODO: bind client
to src_addr */<BR>+<BR>+&nbsp;ret = rs_connect(rs, res-&gt;ai_addr,
res-&gt;ai_addrlen);<BR>+&nbsp;if (ret &amp;&amp; (errno != EINPROGRESS))
{<BR>+&nbsp;&nbsp;perror("rconnect");<BR>+&nbsp;&nbsp;goto
close;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (ret &amp;&amp; (errno == EINPROGRESS))
{<BR>+&nbsp;&nbsp;fds.fd = rs;<BR>+&nbsp;&nbsp;fds.events =
POLLOUT;<BR>+&nbsp;&nbsp;ret = do_poll(&amp;fds);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;goto close;<BR>+<BR>+&nbsp;&nbsp;len = sizeof
err;<BR>+&nbsp;&nbsp;ret = rs_getsockopt(rs, SOL_SOCKET, SO_ERROR, (char
*)&amp;err, &amp;len);<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;goto
close;<BR>+&nbsp;&nbsp;if (err) {<BR>+&nbsp;&nbsp;&nbsp;ret =
-1;<BR>+&nbsp;&nbsp;&nbsp;errno = err;<BR>+&nbsp;&nbsp;&nbsp;perror("async
rconnect");<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+close:<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;rs_close(rs);<BR>+free:<BR>+&nbsp;freeaddrinfo(res);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int run(void)<BR>+{<BR>+&nbsp;int i, ret =
0;<BR>+&nbsp;DWORD dwBytesReturned = 0;<BR>+&nbsp;<BR>+&nbsp;buf =
malloc(!custom ? test_size[TEST_CNT - 1].size : transfer_size);<BR>+&nbsp;if
(!buf) {<BR>+&nbsp;&nbsp;perror("malloc");<BR>+&nbsp;&nbsp;return
-1;<BR>+&nbsp;}<BR>+&nbsp;if (!dst_addr) {<BR>+&nbsp;&nbsp;ret =
server_listen();<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;goto
free;<BR>+&nbsp;}<BR>+&nbsp;printf("%-10s%-8s%-8s%-8s%-8s%8s
%10s%13s\n",<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "name", "bytes",
"xfers", "iters", "total", "time", "Gb/sec", "usec/xfer");<BR>+&nbsp;if
(!custom) {<BR>+&nbsp;&nbsp;optimization = opt_latency;<BR>+&nbsp;&nbsp;ret =
dst_addr ? client_connect() : server_connect();<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;goto free;<BR>+<BR>+&nbsp;&nbsp;for (i = 0; i &lt;
TEST_CNT; i++) {<BR>+&nbsp;&nbsp;&nbsp;if (test_size[i].option &gt;
size_option)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;continue;<BR>+&nbsp;&nbsp;&nbsp;init_latency_test(test_size[i].size);<BR>+&nbsp;&nbsp;&nbsp;run_test();<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;rs_shutdown(rs,
SHUT_RDWR);<BR>+&nbsp;&nbsp;rs_close(rs);<BR>+<BR>+&nbsp;&nbsp;optimization =
opt_bandwidth;<BR>+&nbsp;&nbsp;ret = dst_addr ? client_connect() :
server_connect();<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;goto
free;<BR>+<BR>+&nbsp;&nbsp;for (i = 0; i &lt; TEST_CNT; i++)
{<BR>+&nbsp;&nbsp;&nbsp;if (test_size[i].option &gt;
size_option)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;continue;<BR>+&nbsp;&nbsp;&nbsp;init_bandwidth_test(test_size[i].size);<BR>+&nbsp;&nbsp;&nbsp;run_test();<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}
else {<BR>+&nbsp;&nbsp;ret = dst_addr ? client_connect() :
server_connect();<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;goto
free;<BR>+<BR>+&nbsp;&nbsp;ret =
run_test();<BR>+&nbsp;}<BR>+<BR>+&nbsp;rs_shutdown(rs,
SHUT_RDWR);<BR>+&nbsp;rs_close(rs);<BR>+free:<BR>+&nbsp;free(buf);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int set_test_opt(char *optarg)<BR>+{<BR>+&nbsp;if
(strlen(optarg) == 1) {<BR>+&nbsp;&nbsp;switch (optarg[0])
{<BR>+&nbsp;&nbsp;case 's':<BR>+&nbsp;&nbsp;&nbsp;use_rs =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+/* async not yet supported<BR>+
*&nbsp;&nbsp;case 'a':<BR>+ *&nbsp;&nbsp;&nbsp;use_async = 1;<BR>+
*&nbsp;&nbsp;&nbsp;break;<BR>+ */<BR>+&nbsp;&nbsp;case
'b':<BR>+&nbsp;&nbsp;&nbsp;flags &amp;=
~MSG_DONTWAIT;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'n':<BR>+&nbsp;&nbsp;&nbsp;flags |=
MSG_DONTWAIT;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'v':<BR>+&nbsp;&nbsp;&nbsp;verify =
1;<BR>+&nbsp;&nbsp;&nbsp;break;&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;return
-1;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;if
(!_strnicmp("socket", optarg, 6)) {<BR>+&nbsp;&nbsp;&nbsp;use_rs =
0;<BR>+&nbsp;&nbsp;} /* async not yet supported<BR>+&nbsp;&nbsp;&nbsp;&nbsp;
*&nbsp;else if (!_strnicmp("async", optarg, 5)) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;
*&nbsp;use_async = 1;<BR>+&nbsp;&nbsp;&nbsp;&nbsp; *
}<BR>+&nbsp;&nbsp;&nbsp;&nbsp; */<BR>+&nbsp;&nbsp;&nbsp; else if
(!_strnicmp("block", optarg, 5)) {<BR>+&nbsp;&nbsp;&nbsp;flags &amp;=
~MSG_DONTWAIT;<BR>+&nbsp;&nbsp;} else if (!_strnicmp("nonblock", optarg, 8))
{<BR>+&nbsp;&nbsp;&nbsp;flags |= MSG_DONTWAIT;<BR>+&nbsp;&nbsp;} else if
(!_strnicmp("verify", optarg, 6)) {<BR>+&nbsp;&nbsp;&nbsp;verify =
1;<BR>+&nbsp;&nbsp;} else {<BR>+&nbsp;&nbsp;&nbsp;return
-1;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+int
main(int argc, char **argv)<BR>+{<BR>+&nbsp;int op, ret;<BR>+&nbsp;WSADATA
wsaData;<BR>+<BR>+&nbsp;&nbsp;&nbsp; if (0 != (ret =
WSAStartup(0x202,&amp;wsaData)) )
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr, "WSAStartup
failed with error %d\n",ret);<BR>+&nbsp;&nbsp;ret =
-1;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto
out;<BR>+&nbsp;&nbsp;&nbsp; }<BR>+&nbsp;while ((op = getopt(argc, argv,
"s:b:B:I:C:S:p:T:")) != -1) {<BR>+&nbsp;&nbsp;switch (op) {<BR>+&nbsp;&nbsp;case
's':<BR>+&nbsp;&nbsp;&nbsp;dst_addr =
optarg;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'b':<BR>+&nbsp;&nbsp;&nbsp;src_addr =
optarg;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'B':<BR>+&nbsp;&nbsp;&nbsp;buffer_size =
atoi(optarg);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'I':<BR>+&nbsp;&nbsp;&nbsp;custom = 1;<BR>+&nbsp;&nbsp;&nbsp;iterations =
atoi(optarg);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'C':<BR>+&nbsp;&nbsp;&nbsp;custom = 1;<BR>+&nbsp;&nbsp;&nbsp;transfer_count =
atoi(optarg);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'S':<BR>+&nbsp;&nbsp;&nbsp;if (!_strnicmp("all", optarg, 3))
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;size_option = 1;<BR>+&nbsp;&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;custom =
1;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;transfer_size =
atoi(optarg);<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'p':<BR>+&nbsp;&nbsp;&nbsp;port =
optarg;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
'T':<BR>+&nbsp;&nbsp;&nbsp;if
(!set_test_opt(optarg))<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;/*
invalid option - fall through
*/<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;printf("usage: %s\n",
argv[0]);<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-s
server_address]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-b
bind_address]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-B
buffer_size]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-I
iterations]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-C
transfer_count]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-S transfer_size or
all]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-p
port_number]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t[-T
test_option]\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t&nbsp;&nbsp;&nbsp; s|sockets -
use standard tcp/ip
sockets\n");<BR>+//&nbsp;&nbsp;&nbsp;printf("\t&nbsp;&nbsp;&nbsp; a|async -
asynchronous operation (use
poll)\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t&nbsp;&nbsp;&nbsp; b|blocking - use
blocking calls\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t&nbsp;&nbsp;&nbsp;
n|nonblocking - use nonblocking
calls\n");<BR>+&nbsp;&nbsp;&nbsp;printf("\t&nbsp;&nbsp;&nbsp; v|verify - verify
data\n");<BR>+&nbsp;&nbsp;&nbsp;exit(1);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;if
(!(flags &amp; MSG_DONTWAIT))<BR>+&nbsp;&nbsp;poll_timeout =
-1;<BR>+<BR>+&nbsp;ret = run();<BR>+<BR>+out:<BR>+&nbsp;&nbsp;&nbsp;
WSACleanup();<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>Index:
ulp/librdmacm/examples/rstream/rstream.rc<BR>===================================================================<BR>---
ulp/librdmacm/examples/rstream/rstream.rc&nbsp;(revision 0)<BR>+++
ulp/librdmacm/examples/rstream/rstream.rc&nbsp;(working copy)<BR>@@ -0,0 +1,45
@@<BR>+/*<BR>+ * Copyright (c) 2005 Mellanox Technologies.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the OpenIB.org
BSD license<BR>+ * below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution
and use in source and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
without modification, are permitted provided that the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp; conditions are met:<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source code must retain the
above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this
list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer.<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary form must reproduce
the above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice,
this list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided
with the distribution.<BR>+ *<BR>+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
WARRANTY OF ANY KIND,<BR>+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF<BR>+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>+ *
SOFTWARE.<BR>+ */<BR>+<BR>+<BR>+#include &lt;oib_ver.h&gt;<BR>+<BR>+#define
VER_FILETYPE&nbsp;&nbsp;&nbsp;&nbsp;VFT_APP<BR>+#define
VER_FILESUBTYPE&nbsp;&nbsp;&nbsp;&nbsp;VFT2_UNKNOWN<BR>+<BR>+#ifdef
DBG<BR>+#define VER_FILEDESCRIPTION_STR&nbsp;&nbsp;"(R)Socket Test
(Debug)"<BR>+#else<BR>+#define VER_FILEDESCRIPTION_STR&nbsp;&nbsp;"(R)Socket
Test "<BR>+#endif<BR>+<BR>+#define
VER_INTERNALNAME_STR&nbsp;&nbsp;"rstream.exe"<BR>+#define
VER_ORIGINALFILENAME_STR&nbsp;"rstream.exe"<BR>+<BR>+#include
&lt;common.ver&gt;<BR>Index:
ulp/librdmacm/examples/rstream/SOURCES<BR>===================================================================<BR>---
ulp/librdmacm/examples/rstream/SOURCES&nbsp;(revision 0)<BR>+++
ulp/librdmacm/examples/rstream/SOURCES&nbsp;(working copy)<BR>@@ -0,0 +1,32
@@<BR>+TARGETNAME=rstream<BR>+TARGETPATH=..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)<BR>+TARGETTYPE=PROGRAM<BR>+UMTYPE=console<BR>+USE_MSVCRT=1<BR>+NTTARGETFILES=Custom_target<BR>+<BR>+C_DEFINES=$(C_DEFINES)
/D__WIN__ <BR>+<BR>+SOURCES=rstream.rc
\<BR>+&nbsp;rstream.c<BR>+<BR>+INCLUDES=&nbsp;..;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\inc;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\inc\user;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\inc\user\linux;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\include;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\libibverbs\include;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\hw\mlx4\user\hca;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\inc\complib;
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\core\complib\user\$(O);
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\core\al\user\$(O);
\<BR>+&nbsp;&nbsp;&nbsp;..\..\..\..\etc\user;<BR>+<BR>+RCOPTIONS=/I..\..\win\include<BR>+<BR>+TARGETLIBS=
\<BR>+&nbsp;&nbsp;&nbsp;$(DDK_LIB_PATH)\Ws2_32.lib
\<BR>+&nbsp;&nbsp;&nbsp;$(TARGETPATH)\*\complib.lib
\<BR>+&nbsp;&nbsp;&nbsp;$(TARGETPATH)\*\ibal.lib<BR>+<BR>+MSC_WARNING_LEVEL=
/W3<BR>Index:
ulp/librdmacm/include/rdma/rdma_cma.h<BR>===================================================================<BR>---
ulp/librdmacm/include/rdma/rdma_cma.h&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/include/rdma/rdma_cma.h&nbsp;(working copy)<BR>@@ -1,8 +1,8
@@<BR>&nbsp;/*<BR>&nbsp; * Copyright (c) 2005-2009 Intel Corporation.&nbsp; All
rights reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All
rights reserved.<BR>&nbsp; *<BR>- * This software is available to you under the
OpenFabrics.org BSD license<BR>- * below:<BR>+ * This software is available to
you under the BSD license below:<BR>&nbsp; *<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>@@ -17,14 +17,24 @@<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
provided with the distribution.<BR>&nbsp; *<BR>- * THE SOFTWARE IS PROVIDED "AS
IS", WITHOUT WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AWV<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing
Systems GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
the authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>&nbsp; */<BR>&nbsp;<BR>&nbsp;#pragma once<BR>@@ -678,7 +688,10
@@<BR>&nbsp;/* Option details
*/<BR>&nbsp;enum<BR>&nbsp;{<BR>-&nbsp;RDMA_OPTION_ID_TOS&nbsp;= 0&nbsp;/*
uint8_t: RFC 2474 */<BR>+&nbsp;RDMA_OPTION_ID_TOS&nbsp;= 0,&nbsp;&nbsp;/*
uint8_t: RFC 2474 */<BR>+&nbsp;RDMA_OPTION_ID_REUSEADDR = 1,&nbsp;&nbsp; /* int:
~SO_REUSEADDR */<BR>+&nbsp;RDMA_OPTION_ID_AFONLY&nbsp; = 2,&nbsp;&nbsp; /* int:
~IPV6_V6ONLY */<BR>+&nbsp;RDMA_OPTION_IB_PATH&nbsp; = 1&nbsp;&nbsp;/* struct
ibv_path_data[] */<BR>&nbsp;};<BR>&nbsp;<BR>&nbsp;/**<BR>Index:
ulp/librdmacm/include/rdma/rdma_verbs.h<BR>===================================================================<BR>---
ulp/librdmacm/include/rdma/rdma_verbs.h&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/include/rdma/rdma_verbs.h&nbsp;(working copy)<BR>@@ -1,297 +1,297
@@<BR>-/*<BR>- * Copyright (c) 2010 Intel Corporation.&nbsp; All rights
reserved.<BR>- *<BR>- * This software is available to you under a choice of one
of two<BR>- * licenses.&nbsp; You may choose to be licensed under the terms of
the GNU<BR>- * General Public License (GPL) Version 2, available from the
file<BR>- * COPYING in the main directory of this source tree, or the<BR>- *
OpenIB.org BSD license below:<BR>- *<BR>- *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>-
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>- *&nbsp;&nbsp;&nbsp;&nbsp; conditions are met:<BR>- *<BR>-
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source code must retain the
above<BR>- *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this
list of conditions and the following<BR>-
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer.<BR>- *<BR>-
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary form must reproduce
the above<BR>- *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice,
this list of conditions and the following<BR>-
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>- *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided
with the distribution.<BR>- *<BR>- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>- */<BR>-<BR>-#if !defined(RDMA_VERBS_H)<BR>-#define
RDMA_VERBS_H<BR>-<BR>-#include &lt;assert.h&gt;<BR>-#include
&lt;infiniband/verbs.h&gt;<BR>-#include &lt;rdma/rdma_cma.h&gt;<BR>-#include
&lt;errno.h&gt;<BR>-<BR>-#ifdef __cplusplus<BR>-extern "C"
{<BR>-#endif<BR>-<BR>-static __inline int rdma_seterrno(int
ret)<BR>-{<BR>-&nbsp;if (ret) {<BR>-&nbsp;&nbsp;errno = ret;<BR>-&nbsp;&nbsp;ret
= -1;<BR>-&nbsp;}<BR>-&nbsp;return ret;<BR>-}<BR>-<BR>-/*<BR>- * Memory
registration helpers.<BR>- */<BR>-static __inline struct ibv_mr
*<BR>-rdma_reg_msgs(struct rdma_cm_id *id, void *addr, size_t
length)<BR>-{<BR>-&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE);<BR>-}<BR>-<BR>-static __inline struct ibv_mr
*<BR>-rdma_reg_read(struct rdma_cm_id *id, void *addr, size_t
length)<BR>-{<BR>-&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE
|<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
IBV_ACCESS_REMOTE_READ);<BR>-}<BR>-<BR>-static __inline struct ibv_mr
*<BR>-rdma_reg_write(struct rdma_cm_id *id, void *addr, size_t
length)<BR>-{<BR>-&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE
|<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
IBV_ACCESS_REMOTE_WRITE);<BR>-}<BR>-<BR>-static __inline
int<BR>-rdma_dereg_mr(struct ibv_mr *mr)<BR>-{<BR>-&nbsp;return
rdma_seterrno(ibv_dereg_mr(mr));<BR>-}<BR>-<BR>-<BR>-/*<BR>- * Vectored send,
receive, and RDMA operations.<BR>- * Support multiple scatter-gather
entries.<BR>- */<BR>-static __inline int<BR>-rdma_post_recvv(struct rdma_cm_id
*id, void *context, struct ibv_sge *sgl,<BR>-&nbsp;&nbsp;int
nsge)<BR>-{<BR>-&nbsp;struct ibv_recv_wr wr, *bad;<BR>-<BR>-&nbsp;wr.wr_id =
(uintptr_t) context;<BR>-&nbsp;wr.next = NULL;<BR>-&nbsp;wr.sg_list =
sgl;<BR>-&nbsp;wr.num_sge = nsge;<BR>-<BR>-&nbsp;return
rdma_seterrno(ibv_post_recv(id-&gt;qp, &amp;wr,
&amp;bad));<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_sendv(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>-&nbsp;&nbsp;int nsge,
int flags)<BR>-{<BR>-&nbsp;struct ibv_send_wr wr, *bad;<BR>-<BR>-&nbsp;wr.wr_id
= (uintptr_t) context;<BR>-&nbsp;wr.next = NULL;<BR>-&nbsp;wr.sg_list =
sgl;<BR>-&nbsp;wr.num_sge = nsge;<BR>-&nbsp;wr.opcode =
IBV_WR_SEND;<BR>-&nbsp;wr.send_flags = flags;<BR>-<BR>-&nbsp;return
rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_readv(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>-&nbsp;&nbsp;int nsge,
int flags, uint64_t remote_addr, uint32_t rkey)<BR>-{<BR>-&nbsp;struct
ibv_send_wr wr, *bad;<BR>-<BR>-&nbsp;wr.wr_id = (uintptr_t)
context;<BR>-&nbsp;wr.next = NULL;<BR>-&nbsp;wr.sg_list =
sgl;<BR>-&nbsp;wr.num_sge = nsge;<BR>-&nbsp;wr.opcode =
IBV_WR_RDMA_READ;<BR>-&nbsp;wr.send_flags =
flags;<BR>-&nbsp;wr.wr.rdma.remote_addr = remote_addr;<BR>-&nbsp;wr.wr.rdma.rkey
= rkey;<BR>-<BR>-&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_writev(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>-&nbsp;&nbsp; int nsge,
int flags, uint64_t remote_addr, uint32_t rkey)<BR>-{<BR>-&nbsp;struct
ibv_send_wr wr, *bad;<BR>-<BR>-&nbsp;wr.wr_id = (uintptr_t)
context;<BR>-&nbsp;wr.next = NULL;<BR>-&nbsp;wr.sg_list =
sgl;<BR>-&nbsp;wr.num_sge = nsge;<BR>-&nbsp;wr.opcode =
IBV_WR_RDMA_WRITE;<BR>-&nbsp;wr.send_flags =
flags;<BR>-&nbsp;wr.wr.rdma.remote_addr = remote_addr;<BR>-&nbsp;wr.wr.rdma.rkey
= rkey;<BR>-<BR>-&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>-}<BR>-<BR>-/*<BR>- * Simple send, receive, and RDMA calls.<BR>-
*/<BR>-static __inline int<BR>-rdma_post_recv(struct rdma_cm_id *id, void
*context, void *addr,<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t
length, struct ibv_mr *mr)<BR>-{<BR>-&nbsp;struct ibv_sge
sge;<BR>-<BR>-&nbsp;assert((addr &gt;= mr-&gt;addr)
&amp;&amp;<BR>-&nbsp;&nbsp;&nbsp;&nbsp; (((uint8_t) addr + length) &lt;=
((uint8_t) mr-&gt;addr + mr-&gt;length)));<BR>-&nbsp;sge.addr = (uint64_t)
(uintptr_t) addr;<BR>-&nbsp;sge.length = (uint32_t) length;<BR>-&nbsp;sge.lkey =
mr-&gt;lkey;<BR>-<BR>-&nbsp;return rdma_post_recvv(id, context, &amp;sge,
1);<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_send(struct rdma_cm_id *id,
void *context, void *addr,<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t
length, struct ibv_mr *mr, int flags)<BR>-{<BR>-&nbsp;struct ibv_sge
sge;<BR>-<BR>-&nbsp;sge.addr = (uint64_t) (uintptr_t) addr;<BR>-&nbsp;sge.length
= (uint32_t) length;<BR>-&nbsp;sge.lkey = mr ? mr-&gt;lkey :
0;<BR>-<BR>-&nbsp;return rdma_post_sendv(id, context, &amp;sge, 1,
flags);<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_read(struct rdma_cm_id
*id, void *context, void *addr,<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
size_t length, struct ibv_mr *mr, int
flags,<BR>-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64_t remote_addr,
uint32_t rkey)<BR>-{<BR>-&nbsp;struct ibv_sge sge;<BR>-<BR>-&nbsp;sge.addr =
(uint64_t) (uintptr_t) addr;<BR>-&nbsp;sge.length = (uint32_t)
length;<BR>-&nbsp;sge.lkey = mr-&gt;lkey;<BR>-<BR>-&nbsp;return
rdma_post_readv(id, context, &amp;sge, 1, flags, remote_addr,
rkey);<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_post_write(struct rdma_cm_id
*id, void *context, void *addr,<BR>-&nbsp;&nbsp;size_t length, struct ibv_mr
*mr, int flags,<BR>-&nbsp;&nbsp;uint64_t remote_addr, uint32_t
rkey)<BR>-{<BR>-&nbsp;struct ibv_sge sge;<BR>-<BR>-&nbsp;sge.addr = (uint64_t)
(uintptr_t) addr;<BR>-&nbsp;sge.length = (uint32_t) length;<BR>-&nbsp;sge.lkey =
mr ? mr-&gt;lkey : 0;<BR>-<BR>-&nbsp;return rdma_post_writev(id, context,
&amp;sge, 1, flags, remote_addr, rkey);<BR>-}<BR>-<BR>-static __inline
int<BR>-rdma_post_ud_send(struct rdma_cm_id *id, void *context, void
*addr,<BR>-&nbsp;&nbsp;&nbsp; size_t length, struct ibv_mr *mr, int
flags,<BR>-&nbsp;&nbsp;&nbsp; struct ibv_ah *ah, uint32_t
remote_qpn)<BR>-{<BR>-&nbsp;struct ibv_send_wr wr, *bad;<BR>-&nbsp;struct
ibv_sge sge;<BR>-<BR>-&nbsp;sge.addr = (uint64_t) (uintptr_t)
addr;<BR>-&nbsp;sge.length = (uint32_t) length;<BR>-&nbsp;sge.lkey = mr ?
mr-&gt;lkey : 0;<BR>-<BR>-&nbsp;wr.wr_id = (uintptr_t)
context;<BR>-&nbsp;wr.next = NULL;<BR>-&nbsp;wr.sg_list =
&amp;sge;<BR>-&nbsp;wr.num_sge = 1;<BR>-&nbsp;wr.opcode =
IBV_WR_SEND;<BR>-&nbsp;wr.send_flags = flags;<BR>-&nbsp;wr.wr.ud.ah =
ah;<BR>-&nbsp;wr.wr.ud.remote_qpn = remote_qpn;<BR>-&nbsp;wr.wr.ud.remote_qkey =
RDMA_UDP_QKEY;<BR>-<BR>-&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp,
&amp;wr, &amp;bad));<BR>-}<BR>-<BR>-// Comment out until patch to automatically
create CQs<BR>-static __inline int<BR>-rdma_get_send_comp(struct rdma_cm_id *id,
struct ibv_wc *wc)<BR>-{<BR>-&nbsp;struct ibv_cq *cq;<BR>-&nbsp;void
*context;<BR>-&nbsp;int ret;<BR>-<BR>-&nbsp;ret = ibv_poll_cq(id-&gt;send_cq, 1,
wc);<BR>-&nbsp;if (ret)<BR>-&nbsp;&nbsp;goto out;<BR>-<BR>-&nbsp;ret =
ibv_req_notify_cq(id-&gt;send_cq, 0);<BR>-&nbsp;if (ret)<BR>-&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>-<BR>-&nbsp;while (!(ret = ibv_poll_cq(id-&gt;send_cq, 1,
wc))) {<BR>-&nbsp;&nbsp;ret = ibv_get_cq_event(id-&gt;send_cq_channel, &amp;cq,
&amp;context);<BR>-&nbsp;&nbsp;if (ret)<BR>-&nbsp;&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>-<BR>-&nbsp;&nbsp;assert(cq == id-&gt;send_cq &amp;&amp;
context == id);<BR>-&nbsp;&nbsp;ibv_ack_cq_events(id-&gt;send_cq,
1);<BR>-&nbsp;}<BR>-out:<BR>-&nbsp;return (ret &lt; 0) ? rdma_seterrno(ret) :
ret;<BR>-}<BR>-<BR>-static __inline int<BR>-rdma_get_recv_comp(struct rdma_cm_id
*id, struct ibv_wc *wc)<BR>-{<BR>-&nbsp;struct ibv_cq *cq;<BR>-&nbsp;void
*context;<BR>-&nbsp;int ret;<BR>-<BR>-&nbsp;ret = ibv_poll_cq(id-&gt;recv_cq, 1,
wc);<BR>-&nbsp;if (ret)<BR>-&nbsp;&nbsp;goto out;<BR>-<BR>-&nbsp;ret =
ibv_req_notify_cq(id-&gt;recv_cq, 0);<BR>-&nbsp;if (ret)<BR>-&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>-<BR>-&nbsp;while (!(ret = ibv_poll_cq(id-&gt;recv_cq, 1,
wc))) {<BR>-&nbsp;&nbsp;ret = ibv_get_cq_event(id-&gt;recv_cq_channel, &amp;cq,
&amp;context);<BR>-&nbsp;&nbsp;if (ret)<BR>-&nbsp;&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>-<BR>-&nbsp;&nbsp;assert(cq == id-&gt;recv_cq &amp;&amp;
context == id);<BR>-&nbsp;&nbsp;ibv_ack_cq_events(id-&gt;recv_cq,
1);<BR>-&nbsp;}<BR>-out:<BR>-&nbsp;return (ret &lt; 0) ? rdma_seterrno(ret) :
ret;<BR>-}<BR>-<BR>-#ifdef __cplusplus<BR>-}<BR>-#endif<BR>-<BR>-#endif /*
RDMA_CMA_H */<BR>+/*<BR>+ * Copyright (c) 2010 Intel Corporation.&nbsp; All
rights reserved.<BR>+ *<BR>+ * This software is available to you under a choice
of one of two<BR>+ * licenses.&nbsp; You may choose to be licensed under the
terms of the GNU<BR>+ * General Public License (GPL) Version 2, available from
the file<BR>+ * COPYING in the main directory of this source tree, or the<BR>+ *
OpenIB.org BSD license below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; conditions are met:<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source code must retain the
above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this
list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer.<BR>+ *<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary form must reproduce
the above<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice,
this list of conditions and the following<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided
with the distribution.<BR>+ *<BR>+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
WARRANTY OF ANY KIND,<BR>+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF<BR>+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>+ *
SOFTWARE.<BR>+ */<BR>+<BR>+#if !defined(RDMA_VERBS_H)<BR>+#define
RDMA_VERBS_H<BR>+<BR>+#include &lt;assert.h&gt;<BR>+#include
&lt;infiniband/verbs.h&gt;<BR>+#include &lt;rdma/rdma_cma.h&gt;<BR>+#include
&lt;errno.h&gt;<BR>+<BR>+#ifdef __cplusplus<BR>+extern "C"
{<BR>+#endif<BR>+<BR>+static __inline int rdma_seterrno(int
ret)<BR>+{<BR>+&nbsp;if (ret) {<BR>+&nbsp;&nbsp;errno = ret;<BR>+&nbsp;&nbsp;ret
= -1;<BR>+&nbsp;}<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+/*<BR>+ * Memory
registration helpers.<BR>+ */<BR>+static __inline struct ibv_mr
*<BR>+rdma_reg_msgs(struct rdma_cm_id *id, void *addr, size_t
length)<BR>+{<BR>+&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE);<BR>+}<BR>+<BR>+static __inline struct ibv_mr
*<BR>+rdma_reg_read(struct rdma_cm_id *id, void *addr, size_t
length)<BR>+{<BR>+&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE
|<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
IBV_ACCESS_REMOTE_READ);<BR>+}<BR>+<BR>+static __inline struct ibv_mr
*<BR>+rdma_reg_write(struct rdma_cm_id *id, void *addr, size_t
length)<BR>+{<BR>+&nbsp;return ibv_reg_mr(id-&gt;qp-&gt;pd, addr, length,
IBV_ACCESS_LOCAL_WRITE
|<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
IBV_ACCESS_REMOTE_WRITE);<BR>+}<BR>+<BR>+static __inline
int<BR>+rdma_dereg_mr(struct ibv_mr *mr)<BR>+{<BR>+&nbsp;return
rdma_seterrno(ibv_dereg_mr(mr));<BR>+}<BR>+<BR>+<BR>+/*<BR>+ * Vectored send,
receive, and RDMA operations.<BR>+ * Support multiple scatter-gather
entries.<BR>+ */<BR>+static __inline int<BR>+rdma_post_recvv(struct rdma_cm_id
*id, void *context, struct ibv_sge *sgl,<BR>+&nbsp;&nbsp;int
nsge)<BR>+{<BR>+&nbsp;struct ibv_recv_wr wr, *bad;<BR>+<BR>+&nbsp;wr.wr_id =
(uintptr_t) context;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
sgl;<BR>+&nbsp;wr.num_sge = nsge;<BR>+<BR>+&nbsp;return
rdma_seterrno(ibv_post_recv(id-&gt;qp, &amp;wr,
&amp;bad));<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_sendv(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>+&nbsp;&nbsp;int nsge,
int flags)<BR>+{<BR>+&nbsp;struct ibv_send_wr wr, *bad;<BR>+<BR>+&nbsp;wr.wr_id
= (uintptr_t) context;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
sgl;<BR>+&nbsp;wr.num_sge = nsge;<BR>+&nbsp;wr.opcode =
IBV_WR_SEND;<BR>+&nbsp;wr.send_flags = flags;<BR>+<BR>+&nbsp;return
rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_readv(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>+&nbsp;&nbsp;int nsge,
int flags, uint64_t remote_addr, uint32_t rkey)<BR>+{<BR>+&nbsp;struct
ibv_send_wr wr, *bad;<BR>+<BR>+&nbsp;wr.wr_id = (uintptr_t)
context;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
sgl;<BR>+&nbsp;wr.num_sge = nsge;<BR>+&nbsp;wr.opcode =
IBV_WR_RDMA_READ;<BR>+&nbsp;wr.send_flags =
flags;<BR>+&nbsp;wr.wr.rdma.remote_addr = remote_addr;<BR>+&nbsp;wr.wr.rdma.rkey
= rkey;<BR>+<BR>+&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_writev(struct
rdma_cm_id *id, void *context, struct ibv_sge *sgl,<BR>+&nbsp;&nbsp; int nsge,
int flags, uint64_t remote_addr, uint32_t rkey)<BR>+{<BR>+&nbsp;struct
ibv_send_wr wr, *bad;<BR>+<BR>+&nbsp;wr.wr_id = (uintptr_t)
context;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
sgl;<BR>+&nbsp;wr.num_sge = nsge;<BR>+&nbsp;wr.opcode =
IBV_WR_RDMA_WRITE;<BR>+&nbsp;wr.send_flags =
flags;<BR>+&nbsp;wr.wr.rdma.remote_addr = remote_addr;<BR>+&nbsp;wr.wr.rdma.rkey
= rkey;<BR>+<BR>+&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp, &amp;wr,
&amp;bad));<BR>+}<BR>+<BR>+/*<BR>+ * Simple send, receive, and RDMA calls.<BR>+
*/<BR>+static __inline int<BR>+rdma_post_recv(struct rdma_cm_id *id, void
*context, void *addr,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t
length, struct ibv_mr *mr)<BR>+{<BR>+&nbsp;struct ibv_sge
sge;<BR>+<BR>+&nbsp;assert((addr &gt;= mr-&gt;addr)
&amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp; (((uint8_t) addr + length) &lt;=
((uint8_t) mr-&gt;addr + mr-&gt;length)));<BR>+&nbsp;sge.addr = (uint64_t)
(uintptr_t) addr;<BR>+&nbsp;sge.length = (uint32_t) length;<BR>+&nbsp;sge.lkey =
mr-&gt;lkey;<BR>+<BR>+&nbsp;return rdma_post_recvv(id, context, &amp;sge,
1);<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_send(struct rdma_cm_id *id,
void *context, void *addr,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t
length, struct ibv_mr *mr, int flags)<BR>+{<BR>+&nbsp;struct ibv_sge
sge;<BR>+<BR>+&nbsp;sge.addr = (uint64_t) (uintptr_t) addr;<BR>+&nbsp;sge.length
= (uint32_t) length;<BR>+&nbsp;sge.lkey = mr ? mr-&gt;lkey :
0;<BR>+<BR>+&nbsp;return rdma_post_sendv(id, context, &amp;sge, 1,
flags);<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_read(struct rdma_cm_id
*id, void *context, void *addr,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
size_t length, struct ibv_mr *mr, int
flags,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uint64_t remote_addr,
uint32_t rkey)<BR>+{<BR>+&nbsp;struct ibv_sge sge;<BR>+<BR>+&nbsp;sge.addr =
(uint64_t) (uintptr_t) addr;<BR>+&nbsp;sge.length = (uint32_t)
length;<BR>+&nbsp;sge.lkey = mr-&gt;lkey;<BR>+<BR>+&nbsp;return
rdma_post_readv(id, context, &amp;sge, 1, flags, remote_addr,
rkey);<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_post_write(struct rdma_cm_id
*id, void *context, void *addr,<BR>+&nbsp;&nbsp;size_t length, struct ibv_mr
*mr, int flags,<BR>+&nbsp;&nbsp;uint64_t remote_addr, uint32_t
rkey)<BR>+{<BR>+&nbsp;struct ibv_sge sge;<BR>+<BR>+&nbsp;sge.addr = (uint64_t)
(uintptr_t) addr;<BR>+&nbsp;sge.length = (uint32_t) length;<BR>+&nbsp;sge.lkey =
mr ? mr-&gt;lkey : 0;<BR>+<BR>+&nbsp;return rdma_post_writev(id, context,
&amp;sge, 1, flags, remote_addr, rkey);<BR>+}<BR>+<BR>+static __inline
int<BR>+rdma_post_ud_send(struct rdma_cm_id *id, void *context, void
*addr,<BR>+&nbsp;&nbsp;&nbsp; size_t length, struct ibv_mr *mr, int
flags,<BR>+&nbsp;&nbsp;&nbsp; struct ibv_ah *ah, uint32_t
remote_qpn)<BR>+{<BR>+&nbsp;struct ibv_send_wr wr, *bad;<BR>+&nbsp;struct
ibv_sge sge;<BR>+<BR>+&nbsp;sge.addr = (uint64_t) (uintptr_t)
addr;<BR>+&nbsp;sge.length = (uint32_t) length;<BR>+&nbsp;sge.lkey = mr ?
mr-&gt;lkey : 0;<BR>+<BR>+&nbsp;wr.wr_id = (uintptr_t)
context;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
&amp;sge;<BR>+&nbsp;wr.num_sge = 1;<BR>+&nbsp;wr.opcode =
IBV_WR_SEND;<BR>+&nbsp;wr.send_flags = flags;<BR>+&nbsp;wr.wr.ud.ah =
ah;<BR>+&nbsp;wr.wr.ud.remote_qpn = remote_qpn;<BR>+&nbsp;wr.wr.ud.remote_qkey =
RDMA_UDP_QKEY;<BR>+<BR>+&nbsp;return rdma_seterrno(ibv_post_send(id-&gt;qp,
&amp;wr, &amp;bad));<BR>+}<BR>+<BR>+// Comment out until patch to automatically
create CQs<BR>+static __inline int<BR>+rdma_get_send_comp(struct rdma_cm_id *id,
struct ibv_wc *wc)<BR>+{<BR>+&nbsp;struct ibv_cq *cq;<BR>+&nbsp;void
*context;<BR>+&nbsp;int ret;<BR>+<BR>+&nbsp;ret = ibv_poll_cq(id-&gt;send_cq, 1,
wc);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;goto out;<BR>+<BR>+&nbsp;ret =
ibv_req_notify_cq(id-&gt;send_cq, 0);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>+<BR>+&nbsp;while (!(ret = ibv_poll_cq(id-&gt;send_cq, 1,
wc))) {<BR>+&nbsp;&nbsp;ret = ibv_get_cq_event(id-&gt;send_cq_channel, &amp;cq,
&amp;context);<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>+<BR>+&nbsp;&nbsp;assert(cq == id-&gt;send_cq &amp;&amp;
context == id);<BR>+&nbsp;&nbsp;ibv_ack_cq_events(id-&gt;send_cq,
1);<BR>+&nbsp;}<BR>+out:<BR>+&nbsp;return (ret &lt; 0) ? rdma_seterrno(ret) :
ret;<BR>+}<BR>+<BR>+static __inline int<BR>+rdma_get_recv_comp(struct rdma_cm_id
*id, struct ibv_wc *wc)<BR>+{<BR>+&nbsp;struct ibv_cq *cq;<BR>+&nbsp;void
*context;<BR>+&nbsp;int ret;<BR>+<BR>+&nbsp;ret = ibv_poll_cq(id-&gt;recv_cq, 1,
wc);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;goto out;<BR>+<BR>+&nbsp;ret =
ibv_req_notify_cq(id-&gt;recv_cq, 0);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>+<BR>+&nbsp;while (!(ret = ibv_poll_cq(id-&gt;recv_cq, 1,
wc))) {<BR>+&nbsp;&nbsp;ret = ibv_get_cq_event(id-&gt;recv_cq_channel, &amp;cq,
&amp;context);<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;return
rdma_seterrno(ret);<BR>+<BR>+&nbsp;&nbsp;assert(cq == id-&gt;recv_cq &amp;&amp;
context == id);<BR>+&nbsp;&nbsp;ibv_ack_cq_events(id-&gt;recv_cq,
1);<BR>+&nbsp;}<BR>+out:<BR>+&nbsp;return (ret &lt; 0) ? rdma_seterrno(ret) :
ret;<BR>+}<BR>+<BR>+#ifdef __cplusplus<BR>+}<BR>+#endif<BR>+<BR>+#endif /*
RDMA_CMA_H */<BR>Index:
ulp/librdmacm/include/rdma/rs_regpath.h<BR>===================================================================<BR>---
ulp/librdmacm/include/rdma/rs_regpath.h&nbsp;(revision 0)<BR>+++
ulp/librdmacm/include/rdma/rs_regpath.h&nbsp;(working copy)<BR>@@ -0,0 +1,71
@@<BR>+/*<BR>+ * Copyright (c) 2005 SilverStorm Technologies.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+#ifndef _RS_REGPATH_H_<BR>+#define _RS_REGPATH_H_<BR>+<BR>+/*
these definitions are common for installSP and WSD projects */<BR>+#define
RS_PM_REGISTRY_PATH&nbsp;\<BR>+&nbsp;TEXT("SYSTEM\\CurrentControlSet\\Services\\RSockets\\")<BR>+#define
RS_PM_EVENTLOG_PATH&nbsp;\<BR>+&nbsp;TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\RSockets")<BR>+#define
RS_PM_SUBKEY_NAME&nbsp;&nbsp;TEXT("RSockets")<BR>+#define
RS_PM_SUBKEY_PERF&nbsp;&nbsp;TEXT("Performance")<BR>+#define
RS_PM_INI_FILE&nbsp;&nbsp;"rs_perfcounters.ini"<BR>+#define
RS_PM_SYM_H_FILE&nbsp;&nbsp;"rs_perfini.h"<BR>+<BR>+enum
RS_PM_COUNTERS<BR>+{<BR>+&nbsp;BYTES_SEND =
0,<BR>+&nbsp;BYTES_RECV,<BR>+&nbsp;BYTES_WRITE,<BR>+&nbsp;BYTES_READ,<BR>+&nbsp;BYTES_TOTAL,<BR>+&nbsp;COMP_SEND,<BR>+&nbsp;COMP_RECV,<BR>+&nbsp;COMP_TOTAL,<BR>+&nbsp;INTR_TOTAL,<BR>+&nbsp;RS_PM_NUM_COUNTERS<BR>+};<BR>+<BR>+/*
counter symbol names */<BR>+#define
RS_PM_OBJ&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0<BR>+#define RS_PM_COUNTER( X
)&nbsp;&nbsp;&nbsp;((X + 1) * 2)<BR>+<BR>+#endif /* _RS_REGPATH_H_ */<BR>Index:
ulp/librdmacm/include/rdma/rsocket.h<BR>===================================================================<BR>---
ulp/librdmacm/include/rdma/rsocket.h&nbsp;(revision 0)<BR>+++
ulp/librdmacm/include/rdma/rsocket.h&nbsp;(working copy)<BR>@@ -0,0 +1,134
@@<BR>+/*<BR>+ * Copyright (c) 2011 Intel Corporation.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+#if !defined(RSOCKET_H)<BR>+#define
RSOCKET_H<BR>+<BR>+#include &lt;infiniband/verbs.h&gt;<BR>+#include
&lt;rdma/rdma_cma.h&gt;<BR>+#include &lt;sys/socket.h&gt;<BR>+#include
&lt;errno.h&gt;<BR>+#include &lt;ws2spi.h&gt;<BR>+<BR>+typedef unsigned int
nfds_t; // Under Linux from poll.h<BR>+<BR>+#ifdef __cplusplus<BR>+extern "C"
{<BR>+#endif<BR>+__declspec(dllexport)<BR>+int rsocket(int domain, int type, int
protocol);<BR>+__declspec(dllexport)<BR>+int rbind(int socket, const struct
sockaddr *addr, socklen_t addrlen);<BR>+__declspec(dllexport)<BR>+int
rlisten(int socket, int backlog);<BR>+__declspec(dllexport)<BR>+int raccept(int
socket, struct sockaddr *addr, socklen_t *addrlen);<BR>+SOCKET WSPAPI
WSPAccept(<BR>+&nbsp;SOCKET&nbsp;&nbsp;&nbsp; socket,<BR>+&nbsp;struct
sockaddr&nbsp;*addr,<BR>+&nbsp;LPINT&nbsp;&nbsp;&nbsp;
addrlen,<BR>+&nbsp;LPCONDITIONPROC&nbsp;
lpfnCondition,<BR>+&nbsp;DWORD_PTR&nbsp;&nbsp;
dwCallbackData,<BR>+&nbsp;LPINT&nbsp;&nbsp;&nbsp;
lpErrno<BR>+);<BR>+__declspec(dllexport)<BR>+int rconnect(int socket, const
struct sockaddr *addr, socklen_t addrlen);<BR>+__declspec(dllexport)<BR>+int
rshutdown(int socket, int how);<BR>+__declspec(dllexport)<BR>+int rclose(int
socket);<BR>+__declspec(dllexport)<BR>+ssize_t rrecv(int socket, void *buf,
size_t len, int flags);<BR>+__declspec(dllexport)<BR>+ssize_t rrecvfrom(int
socket, void *buf, size_t len, int flags,<BR>+&nbsp;&nbsp;&nbsp; struct sockaddr
*src_addr, socklen_t *addrlen);<BR>+__declspec(dllexport)<BR>+ssize_t
rrecvmsg(int socket, struct msghdr *msg, int
flags);<BR>+__declspec(dllexport)<BR>+ssize_t rsend(int socket, const void *buf,
size_t len, int flags);<BR>+__declspec(dllexport)<BR>+ssize_t rsendto(int
socket, const void *buf, size_t len, int flags,<BR>+&nbsp;&nbsp;const struct
sockaddr *dest_addr, socklen_t addrlen);<BR>+__declspec(dllexport)<BR>+ssize_t
rsendmsg(int socket, const struct msghdr *msg, int
flags);<BR>+__declspec(dllexport)<BR>+ssize_t rread(int socket, void *buf,
size_t count);<BR>+__declspec(dllexport)<BR>+ssize_t rreadv(int socket, const
struct iovec *iov, int iovcnt);<BR>+__declspec(dllexport)<BR>+ssize_t rwrite(int
socket, const void *buf, size_t count);<BR>+__declspec(dllexport)<BR>+ssize_t
rwritev(int socket, const struct iovec *iov, int
iovcnt);<BR>+__declspec(dllexport)<BR>+int rpoll(struct pollfd *fds, nfds_t
nfds, int timeout);<BR>+__declspec(dllexport)<BR>+int rselect(int nfds, fd_set
*readfds, fd_set *writefds,<BR>+&nbsp;&nbsp;&nbsp;&nbsp; fd_set *exceptfds,
struct timeval *timeout);<BR>+__declspec(dllexport)<BR>+int rgetpeername(int
socket, struct sockaddr *addr, socklen_t
*addrlen);<BR>+__declspec(dllexport)<BR>+int rgetsockname(int socket, struct
sockaddr *addr, socklen_t *addrlen);<BR>+<BR>+#ifndef SOL_RDMA<BR>+#define
SOL_RDMA 0x10000<BR>+enum
{<BR>+&nbsp;RDMA_SQSIZE,<BR>+&nbsp;RDMA_RQSIZE,<BR>+&nbsp;RDMA_INLINE<BR>+};<BR>+#endif<BR>+<BR>+__declspec(dllexport)<BR>+int
rsetsockopt(int socket, int level, int optname,<BR>+&nbsp;&nbsp;const void
*optval, socklen_t optlen);<BR>+__declspec(dllexport)<BR>+int rgetsockopt(int
socket, int level, int optname,<BR>+&nbsp;&nbsp;void *optval, socklen_t
*optlen);<BR>+__declspec(dllexport)<BR>+int rfcntl(int socket, int cmd, ... /*
arg */ );<BR>+__declspec(dllexport)<BR>+int rioctlsocket(int socket, long cmd,
u_long* argp);<BR>+<BR>+int rsGetStatus ( __out LPRS_STATUS *lppStatusBuffer
);<BR>+<BR>+#ifdef __cplusplus<BR>+}<BR>+#endif<BR>+<BR>+#endif /* RSOCKET_H
*/<BR>Index:
ulp/librdmacm/include/rdma/rwinsock.h<BR>===================================================================<BR>---
ulp/librdmacm/include/rdma/rwinsock.h&nbsp;(revision 0)<BR>+++
ulp/librdmacm/include/rdma/rwinsock.h&nbsp;(working copy)<BR>@@ -0,0 +1,132
@@<BR>+/*<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+#if !defined(RWINSOCK_H)<BR>+#define
RWINSOCK_H<BR>+<BR>+#include &lt;winsock2.h&gt;<BR>+#include
&lt;ws2tcpip.h&gt;<BR>+#include &lt;stdlib.h&gt;<BR>+#include
&lt;string.h&gt;<BR>+<BR>+static const GUID rsProviderGuid = {
//D478E78B-A803-4a25-A5E4-83BFB7EAF4A7<BR>+&nbsp;0xd478e78b,<BR>+&nbsp;0xa803,<BR>+&nbsp;0x4a25,<BR>+&nbsp;{
0xa5, 0xe4, 0x83, 0xbf, 0xb7, 0xea, 0xf4, 0xa7 }<BR>+};<BR>+<BR>+static
WSAPROTOCOL_INFO rsProtocolInfo = {0};<BR>+<BR>+/**<BR>+ *
\brief&nbsp;&nbsp;&nbsp;Get RSockets Winsock provider's WSAPROTOCOL_INFO
structure.<BR>+ *<BR>+ * \param lpStatus&nbsp;Pointer to status variable to be
returned. Can be NULL if not required.<BR>+ *<BR>+ *
\return&nbsp;&nbsp;&nbsp;Pointer to the RSockets Winsock provider's
WSAPROTOCOL_INFO structure<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(NULL if the
RSockets provider is not found or another error occured).<BR>+ */<BR>+static
LPWSAPROTOCOL_INFO rsGetProtocolInfo (LPINT
lpStatus)<BR>+{<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Status&nbsp;&nbsp;&nbsp;= ERROR_SUCCESS;<BR>+&nbsp;LPWSAPROTOCOL_INFO
lpProtocolBuffer&nbsp;= NULL;<BR>+&nbsp;LPWSAPROTOCOL_INFO
lpReturn&nbsp;&nbsp;&nbsp;= NULL;
<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
BufferLength&nbsp;&nbsp;=
0;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
i;<BR>+<BR>+&nbsp;WSAEnumProtocols (NULL, NULL, &amp;BufferLength); // Should
always return the BufferLength<BR>+<BR>+&nbsp;if (NULL == (lpProtocolBuffer =
(LPWSAPROTOCOL_INFO)malloc (BufferLength)))<BR>+&nbsp;{<BR>+&nbsp;&nbsp;Status =
ERROR_NOT_ENOUGH_MEMORY;<BR>+&nbsp;&nbsp;goto
cleanup;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (SOCKET_ERROR == WSAEnumProtocols (NULL,
lpProtocolBuffer, &amp;BufferLength))<BR>+&nbsp;{<BR>+&nbsp;&nbsp;Status =
WSAGetLastError();<BR>+&nbsp;&nbsp;goto
cleanup;<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;for (i = 0; i &lt; BufferLength /
sizeof(*lpProtocolBuffer); i++)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;if (0 == memcmp
(&amp;lpProtocolBuffer[i].ProviderId, &amp;rsProviderGuid,
sizeof(rsProviderGuid)))<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;rsProtocolInfo&nbsp;=
lpProtocolBuffer[i];<BR>+&nbsp;&nbsp;&nbsp;lpReturn&nbsp;&nbsp;=
&amp;rsProtocolInfo;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;cleanup:<BR>+&nbsp;if
(lpProtocolBuffer)<BR>+&nbsp;&nbsp;free (lpProtocolBuffer);<BR>+&nbsp;&nbsp;
<BR>+&nbsp;if (lpStatus)<BR>+&nbsp;&nbsp;*lpStatus =
Status;<BR>+<BR>+&nbsp;return lpReturn;<BR>+}<BR>+<BR>+#ifndef
SOL_RDMA<BR>+#define SOL_RDMA 0x10000 // for getsockopt + setsockopt<BR>+enum
{<BR>+&nbsp;RDMA_SQSIZE,<BR>+&nbsp;RDMA_RQSIZE,<BR>+&nbsp;RDMA_INLINE<BR>+};<BR>+#endif
/* SOL_RDMA */<BR>+<BR>+typedef struct {<BR>+&nbsp;struct
sockaddr&nbsp;src_addr;<BR>+&nbsp;struct
sockaddr&nbsp;dst_addr;<BR>+&nbsp;char&nbsp;&nbsp;&nbsp;state[16];<BR>+}
RS_STATUS, *LPRS_STATUS;<BR>+<BR>+typedef struct {<BR>+&nbsp;char
szLine[128];<BR>+} RS_TRACE_OUT, *LPRS_TRACE_OUT;<BR>+<BR>+/*<BR>+ * IOCTL code
definition to get RS_STATUS information via WSAIoctl():<BR>+ */<BR>+#define
IOC_VENDOR_OFA&nbsp;&nbsp;0x0FA0000<BR>+#define SIO_RS_GET_STATUS&nbsp;(IOC_OUT
| IOC_VENDOR | IOC_VENDOR_OFA | 1)<BR>+#define SIO_RS_GET_TRACE&nbsp;(IOC_OUT |
IOC_VENDOR | IOC_VENDOR_OFA | 2)<BR>+<BR>+#endif /* RWINSOCK_H */<BR>Index:
ulp/librdmacm/RSocket.txt<BR>===================================================================<BR>---
ulp/librdmacm/RSocket.txt&nbsp;(revision 0)<BR>+++
ulp/librdmacm/RSocket.txt&nbsp;(working copy)<BR>@@ -0,0 +1,105 @@<BR>+<BR>+
Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+<BR>+ This software is available to you under the BSD license
below:<BR>+<BR>+&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source and
binary forms, with or<BR>+&nbsp;&nbsp;&nbsp;&nbsp; without modification, are
permitted provided that the following<BR>+&nbsp;&nbsp;&nbsp;&nbsp; conditions
are met:<BR>+<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions of source
code must retain the above<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
copyright notice, this list of conditions and the
following<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in binary
form must reproduce the above<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
copyright notice, this list of conditions and the
following<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the
documentation and/or other
materials<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the
distribution.<BR>+<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce
Printing Systems GmbH nor the
names<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the authors may be used
to endorse or promote products<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
derived from this software without specific prior
written<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; permission.<BR>+<BR>+
THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY EXPRESS OR IMPLIED<BR>+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF<BR>+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND<BR>+ NON-INFRINGEMENT
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ OR CONTRIBUTOR OR COPYRIGHT
HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL<BR>+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF<BR>+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;<BR>+ OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF<BR>+ LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+ (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY<BR>+ OF SUCH DAMAGE.
<BR>+<BR>+#############################################################################<BR>+<BR>+<BR>+GENERAL<BR>+=======<BR>+The
RSockets protocol provides socket-based RDMA communication between<BR>+Windows
nodes (like to WSD or ND) as well as between Windows and Linux
nodes.<BR>+<BR>+The RSockets functionality is contained within the librdmacm.dll
which now<BR>+is capable to act as a Winsock base transport
provider.<BR>+<BR>+For now the librdmacm.dll still exports the direct rsocket
calls<BR>+(rsocket, rbind, rrecv etc.) as well. So application developers
can<BR>+alternatively circumvent Winsock and call those functions
directly<BR>+(by including rsocket.h instead of rwinsock.h).<BR>+Aside from a
slight performance gain, this might be useful in case of<BR>+quickly porting a
Linux app to Windows(?).<BR>+But beware of using both access methods
concurrently in the same
application!<BR>+<BR>+<BR>+INSTALLATION<BR>+============<BR>+Installation of
that Winsock provider (i.e. registration of the<BR>+librdmacm.dll in the Windows
Registry) can be done with the rsinstall<BR>+tool (see tools/rsinstall) which
works similar to wsdinstall for the<BR>+WSD Winsock provider.<BR>+For a list of
available options, just call rsinstall.exe without<BR>+parameters. (Note that
rsinstall.exe requires administrative privileges<BR>+to run
properly!)<BR>+<BR>+<BR>+USAGE<BR>+=====<BR>+Usage of the RSocket provider at
application level is quite simple,<BR>+as demonstrated by the rstream tool (see
ulp/librdmacm/examples/rstream)<BR>+which is also a porting from Linux OFED. In
contrast to a 'normal' Winsock<BR>+application there are just two essential
differences:<BR>+<BR>+- The ulp\librdmacm\include\rdma\rwinsock.h header has to
be included<BR>+&nbsp; instead of winsock2.h. (Nonetheless it's still necessary
to call<BR>+&nbsp; WSAStartup() and WSACleanup() during initialization and
shutdown of<BR>+&nbsp; your application, respectivily).<BR>+<BR>+- Instead of
calling socket() for socket creation, a WSASocket() has to<BR>+&nbsp; be
performed with a WSAPROTOCOL_INFO structure selecting the appropriate<BR>+&nbsp;
Winsock provider. For convenience there is a little helper function<BR>+&nbsp;
rsGetProtocolInfo() implemented in rwinsock.h which provides this
structure<BR>+&nbsp; based on the provider's GUID (static variable
'rsProviderGuid' which is<BR>+&nbsp; also contained in
rwinsock.h).<BR>+<BR>+<BR>+RESTRICTIONS<BR>+============<BR>+Generally there are
the same restrictions for socket applications as<BR>+described in the Linux
RSockets man page (e.g. no UDP / SOCK_DGRAM).<BR>+Moreover the following
restrictions apply:<BR>+<BR>+- The MSG_DONTWAIT flag is not supported when
calling WSASocket().<BR>+&nbsp; Instead to configure a socket for non-blocking
operation,<BR>+&nbsp; ioctlsocket(FIONBIO) can be used.<BR>+<BR>+- Overlapped
operation is currently not supported, i.e. a WSASocket() with<BR>+&nbsp; the
WSA_FLAG_OVERLAPPED flag set will be rejected with a WSAEINVAL error.<BR>+<BR>+-
The WSAPoll() function (in Windows Vista and later) is not supported,<BR>+&nbsp;
hence the select() function has to be used instead.<BR>+<BR>+- IPv6 should work,
but has not been tested yet.<BR>Index:
ulp/librdmacm/src/addrinfo.cpp<BR>===================================================================<BR>---
ulp/librdmacm/src/addrinfo.cpp&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/addrinfo.cpp&nbsp;(working copy)<BR>@@ -1,11 +1,8
@@<BR>&nbsp;/*<BR>&nbsp; * Copyright (c) 2010 Intel Corporation.&nbsp; All
rights reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All
rights reserved.<BR>&nbsp; *<BR>- * This software is available to you under a
choice of one of two<BR>- * licenses.&nbsp; You may choose to be licensed under
the terms of the GNU<BR>- * General Public License (GPL) Version 2, available
from the file<BR>- * COPYING in the main directory of this source tree, or
the<BR>- * OpenIB.org BSD license below:<BR>+ * This software is available to
you under the BSD license below:<BR>&nbsp; *<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>@@ -20,14 +17,24 @@<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
provided with the distribution.<BR>&nbsp; *<BR>- * THE SOFTWARE IS PROVIDED "AS
IS", WITHOUT WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing
Systems GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
the authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>&nbsp; */<BR>&nbsp;<BR>&nbsp;#if HAVE_CONFIG_H<BR>@@ -47,7 +54,7
@@<BR>&nbsp;{<BR>&nbsp;&nbsp;WSADATA
wsadata;<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;if
(addr_ref++) {<BR>&nbsp;&nbsp;&nbsp;goto out;<BR>&nbsp;&nbsp;}<BR>@@ -57,16
+64,16
@@<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;out:<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;static
void
ucma_shutdown(void)<BR>&nbsp;{<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;if
(--addr_ref == 0)
{<BR>&nbsp;&nbsp;&nbsp;WSACleanup();<BR>&nbsp;&nbsp;}<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;static
void ucma_convert_to_ai(struct addrinfo *ai, struct rdma_addrinfo
*rai)<BR>Index:
ulp/librdmacm/src/cma.cpp<BR>===================================================================<BR>---
ulp/librdmacm/src/cma.cpp&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/cma.cpp&nbsp;(working copy)<BR>@@ -1,8 +1,8
@@<BR>&nbsp;/*<BR>&nbsp; * Copyright (c) 2005-2009 Intel Corporation.&nbsp; All
rights reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All
rights reserved.<BR>&nbsp; *<BR>- * This software is available to you under the
OpenIB.org BSD license<BR>- * below:<BR>+ * This software is available to you
under the BSD license below:<BR>&nbsp; *<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>@@ -17,21 +17,31 @@<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
provided with the distribution.<BR>&nbsp; *<BR>- * THE SOFTWARE IS PROVIDED "AS
IS", WITHOUT WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AWV<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing
Systems GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
the authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE. <BR>&nbsp; */<BR>&nbsp;<BR>&nbsp;#include &lt;windows.h&gt;<BR>&nbsp;#include
&lt;winsock2.h&gt;<BR>+#include "openib_osd.h"<BR>&nbsp;#include
&lt;stdio.h&gt;<BR>&nbsp;#include &lt;iphlpapi.h&gt;<BR>-<BR>&nbsp;#include
&lt;rdma/rdma_cma.h&gt;<BR>&nbsp;#include
&lt;rdma/rdma_verbs.h&gt;<BR>&nbsp;#include &lt;infiniband/verbs.h&gt;<BR>@@
-88,6 +98,7
@@<BR>&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port_cnt;<BR>&nbsp;&nbsp;uint8_t&nbsp;&nbsp;&nbsp;&nbsp;max_initiator_depth;<BR>&nbsp;&nbsp;uint8_t&nbsp;&nbsp;&nbsp;&nbsp;max_responder_resources;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max_qpsize;<BR>&nbsp;};<BR>&nbsp;<BR>&nbsp;struct
cma_event {<BR>@@ -100,6 +111,59 @@<BR>&nbsp;static int
cma_dev_cnt;<BR>&nbsp;static DWORD ref;<BR>&nbsp;<BR>+void wsa_setlasterror(int
err)<BR>+{<BR>+&nbsp;int wsa_err = 0;<BR>+&nbsp;switch (err)
{<BR>+&nbsp;&nbsp;case
0:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
EADDRINUSE:&nbsp;&nbsp;{wsa_err =
WSAEADDRINUSE;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EADDRNOTAVAIL:&nbsp;&nbsp;{wsa_err =
WSAEADDRNOTAVAIL;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EAFNOSUPPORT:&nbsp;&nbsp;{wsa_err =
WSAEAFNOSUPPORT;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EALREADY:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAEALREADY;&nbsp;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
EBADMSG:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
ECANCELED:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAECANCELLED;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ECONNABORTED:&nbsp;&nbsp;{wsa_err =
WSAECONNABORTED;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ECONNREFUSED:&nbsp;&nbsp;{wsa_err =
WSAECONNREFUSED;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ECONNRESET:&nbsp;&nbsp;{wsa_err =
WSAECONNRESET;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EDESTADDRREQ:&nbsp;&nbsp;{wsa_err =
WSAEDESTADDRREQ;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EHOSTUNREACH:&nbsp;&nbsp;{wsa_err =
WSAEHOSTUNREACH;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
EIDRM:&nbsp;&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
EINPROGRESS:&nbsp;&nbsp;{wsa_err =
WSAEINPROGRESS;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EISCONN:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAEISCONN;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ELOOP:&nbsp;&nbsp;&nbsp;&nbsp;{wsa_err =
WSAELOOP;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EMSGSIZE:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAEMSGSIZE;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENETDOWN:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAENETDOWN;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENETRESET:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAENETRESET;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENETUNREACH:&nbsp;&nbsp;{wsa_err =
WSAENETUNREACH;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENOBUFS:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAENOBUFS;&nbsp;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
ENODATA:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+//&nbsp;&nbsp;case
ENOLINK:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+//&nbsp;&nbsp;case
ENOMSG:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
ENOPROTOOPT:&nbsp;&nbsp;{wsa_err =
WSAENOPROTOOPT;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
ENOSR:&nbsp;&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+//&nbsp;&nbsp;case
ENOSTR:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
ENOTCONN:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAENOTCONN;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENOTRECOVERABLE:&nbsp;{wsa_err =
WSANO_RECOVERY;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENOTSOCK:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAENOTSOCK;&nbsp;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;case
ENOTSUP:&nbsp;&nbsp;&nbsp;{wsa_err = WSAEINVAL;&nbsp;&nbsp;&nbsp;break;}
//???<BR>+&nbsp;&nbsp;case EOPNOTSUPP:&nbsp;&nbsp;{wsa_err =
WSAEOPNOTSUPP;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
EOTHER:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+//&nbsp;&nbsp;case
EOVERFLOW:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+//&nbsp;&nbsp;case
EOWNERDEAD:&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
EPROTO:&nbsp;&nbsp;&nbsp;{wsa_err = WSAENOPROTOOPT;&nbsp;&nbsp;break;}
//???<BR>+&nbsp;&nbsp;case EPROTONOSUPPORT:&nbsp;{wsa_err =
WSAEPROTONOSUPPORT;&nbsp;break;}<BR>+&nbsp;&nbsp;case
EPROTOTYPE:&nbsp;&nbsp;{wsa_err =
WSAEPROTOTYPE;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
ETIME:&nbsp;&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
ETIMEDOUT:&nbsp;&nbsp;&nbsp;{wsa_err =
WSAETIMEDOUT;&nbsp;&nbsp;break;}<BR>+//&nbsp;&nbsp;case
ETXTBSY:&nbsp;&nbsp;&nbsp;{wsa_err = ; break;}<BR>+&nbsp;&nbsp;case
ENOMEM:&nbsp;&nbsp;&nbsp;{wsa_err = WSA_NOT_ENOUGH_MEMORY;
break;}<BR>+&nbsp;&nbsp;case EAGAIN:<BR>+&nbsp;&nbsp;case
EWOULDBLOCK:&nbsp;&nbsp;{wsa_err =
WSAEWOULDBLOCK;&nbsp;&nbsp;break;}<BR>+&nbsp;&nbsp;default:
;<BR>+&nbsp;}<BR>+&nbsp;WSASetLastError(wsa_err);<BR>+}<BR>+<BR>&nbsp;static int
ucma_acquire(void)<BR>&nbsp;{<BR>&nbsp;&nbsp;struct ibv_device **dev_list =
NULL;<BR>@@ -107,7 +171,7 @@<BR>&nbsp;&nbsp;struct ibv_device_attr
attr;<BR>&nbsp;&nbsp;int i, ret,
dev_cnt;<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;if
(ref++) {<BR>&nbsp;&nbsp;&nbsp;goto out;<BR>&nbsp;&nbsp;}<BR>@@ -153,13 +217,14
@@<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;cma_dev-&gt;port_cnt =
attr.phys_port_cnt;<BR>+&nbsp;&nbsp;cma_dev-&gt;max_qpsize =
attr.max_qp_wr;<BR>&nbsp;&nbsp;&nbsp;cma_dev-&gt;max_initiator_depth = (uint8_t)
attr.max_qp_init_rd_atom;<BR>&nbsp;&nbsp;&nbsp;cma_dev-&gt;max_responder_resources
= (uint8_t)
attr.max_qp_rd_atom;<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;ibv_free_device_list(dev_list);<BR>&nbsp;&nbsp;cma_dev_cnt
=
dev_cnt;<BR>&nbsp;out:<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;&nbsp;return
0;<BR>&nbsp;<BR>&nbsp;err4:<BR>@@ -174,7 +239,7
@@<BR>&nbsp;&nbsp;ibvw_release_windata(&amp;windata,
IBVW_WINDATA_VERSION);<BR>&nbsp;err1:<BR>&nbsp;&nbsp;ref--;<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;&nbsp;return
ret;<BR>&nbsp;}<BR>&nbsp;<BR>@@ -182,7 +247,7 @@<BR>&nbsp;{<BR>&nbsp;&nbsp;int
i;<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;if
(--ref == 0) {<BR>&nbsp;&nbsp;&nbsp;for (i = 0; i &lt; cma_dev_cnt; i++)
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;ibv_dealloc_pd(cma_dev_array[i].pd);<BR>@@ -192,7
+257,7 @@<BR>&nbsp;&nbsp;&nbsp;cma_dev_cnt =
0;<BR>&nbsp;&nbsp;&nbsp;ibvw_release_windata(&amp;windata,
IBVW_WINDATA_VERSION);<BR>&nbsp;&nbsp;}<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;__declspec(dllexport)<BR>@@
-329,9 +394,9 @@<BR>&nbsp;<BR>&nbsp;&nbsp;id_priv = CONTAINING_RECORD(id, struct
cma_id_private,
id);<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;id_priv-&gt;state
=
cma_destroying;<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;<BR>&nbsp;&nbsp;if
(id-&gt;ps == RDMA_PS_TCP)
{<BR>&nbsp;&nbsp;&nbsp;id-&gt;ep.connect-&gt;CancelOverlappedRequests();<BR>@@
-502,13 +567,20 @@<BR>&nbsp;&nbsp;return ret;<BR>&nbsp;}<BR>&nbsp;<BR>-static
int ucma_complete(struct cma_id_private *id_priv)<BR>+static int
ucma_complete_priv(struct cma_id_private *id_priv)<BR>&nbsp;{<BR>+&nbsp;return
ucma_complete(&amp;id_priv-&gt;id);<BR>+}<BR>+<BR>+int ucma_complete(struct
rdma_cm_id *id)<BR>+{<BR>+&nbsp;struct cma_id_private
*id_priv;<BR>&nbsp;&nbsp;int ret;<BR>&nbsp;<BR>-&nbsp;if (!id_priv-&gt;sync)
{<BR>+&nbsp;id_priv = container_of(id, struct cma_id_private,
id);<BR>+<BR>+&nbsp;if (!id_priv-&gt;sync)<BR>&nbsp;&nbsp;&nbsp;return
0;<BR>-&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;if (id_priv-&gt;id.event)
{<BR>&nbsp;&nbsp;&nbsp;rdma_ack_cm_event(id_priv-&gt;id.event);<BR>@@ -516,11
+588,18 @@<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;ret =
rdma_get_cm_event(id_priv-&gt;id.channel,
&amp;id_priv-&gt;id.event);<BR>-&nbsp;if (ret) {<BR>+&nbsp;if
(ret)<BR>&nbsp;&nbsp;&nbsp;return ret;<BR>+<BR>+&nbsp;if
(id_priv-&gt;id.event-&gt;status) {<BR>+&nbsp;&nbsp;if
(id_priv-&gt;id.event-&gt;event ==
RDMA_CM_EVENT_REJECTED)<BR>+&nbsp;&nbsp;&nbsp;ret =
ERR(ECONNREFUSED);<BR>+&nbsp;&nbsp;else if (id_priv-&gt;id.event-&gt;status &lt;
0)<BR>+&nbsp;&nbsp;&nbsp;ret =
ERR(-id_priv-&gt;id.event-&gt;status);<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;ret
= ERR(-id_priv-&gt;id.event-&gt;status);<BR>&nbsp;&nbsp;}<BR>-<BR>-&nbsp;return
id_priv-&gt;id.event-&gt;status;<BR>+&nbsp;return
ret;<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;__declspec(dllexport)<BR>@@ -561,12 +640,17
@@<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>-&nbsp;RtlCopyMemory(&amp;id-&gt;route.addr.dst_addr,
dst_addr, ucma_addrlen(dst_addr));<BR>+&nbsp;if (((struct sockaddr_in
*)&amp;id-&gt;route.addr.dst_addr)-&gt;sin_port ==
0)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;// port = 0 =&gt; Assume that entire dst_addr
hasn't been set
yet<BR>+&nbsp;&nbsp;RtlCopyMemory(&amp;id-&gt;route.addr.dst_addr, dst_addr,
ucma_addrlen(dst_addr));<BR>+&nbsp;}<BR>+<BR>&nbsp;&nbsp;id_priv-&gt;state =
cma_addr_resolve;<BR>&nbsp;<BR>&nbsp;&nbsp;id_priv-&gt;refcnt++;<BR>&nbsp;&nbsp;CompEntryPost(&amp;id-&gt;comp_entry);<BR>-&nbsp;return
ucma_complete(id_priv);<BR>+&nbsp;return
ucma_complete_priv(id_priv);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;__declspec(dllexport)<BR>@@
-594,7 +678,7
@@<BR>&nbsp;<BR>&nbsp;&nbsp;id_priv-&gt;refcnt++;<BR>&nbsp;&nbsp;CompEntryPost(&amp;id-&gt;comp_entry);<BR>-&nbsp;return
ucma_complete(id_priv);<BR>+&nbsp;return
ucma_complete_priv(id_priv);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;static int
ucma_modify_qp_init(struct cma_id_private *id_priv, struct ibv_qp *qp)<BR>@@
-648,10 +732,10 @@<BR>&nbsp;&nbsp;if
(id-&gt;recv_cq_channel)<BR>&nbsp;&nbsp;&nbsp;ibv_destroy_comp_channel(id-&gt;recv_cq_channel);<BR>&nbsp;<BR>-&nbsp;if
(id-&gt;send_cq)<BR>+&nbsp;if (id-&gt;send_cq &amp;&amp; id-&gt;send_cq !=
id-&gt;recv_cq)<BR>&nbsp;&nbsp;&nbsp;ibv_destroy_cq(id-&gt;send_cq);<BR>&nbsp;<BR>-&nbsp;if
(id-&gt;send_cq_channel)<BR>+&nbsp;if (id-&gt;send_cq_channel &amp;&amp;
id-&gt;send_cq_channel !=
id-&gt;recv_cq_channel)<BR>&nbsp;&nbsp;&nbsp;ibv_destroy_comp_channel(id-&gt;send_cq_channel);<BR>&nbsp;}<BR>&nbsp;<BR>@@
-832,7 +916,7 @@<BR>&nbsp;&nbsp;&nbsp;return
ibvw_wv_errno(hr);<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>-&nbsp;return
ucma_complete(id_priv);<BR>+&nbsp;return
ucma_complete_priv(id_priv);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;static int
ucma_get_request(struct cma_id_private *listen, int index)<BR>@@ -841,7 +925,7
@@<BR>&nbsp;&nbsp;HRESULT hr;<BR>&nbsp;&nbsp;int
ret;<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;if
(listen-&gt;state != cma_listening) {<BR>&nbsp;&nbsp;&nbsp;ret =
ibvw_wv_errno(WV_INVALID_PARAMETER);<BR>&nbsp;&nbsp;&nbsp;goto err1;<BR>@@
-873,14 +957,14
@@<BR>&nbsp;&nbsp;&nbsp;id_priv-&gt;refcnt--;<BR>&nbsp;&nbsp;&nbsp;goto
err2;<BR>&nbsp;&nbsp;}<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;<BR>&nbsp;&nbsp;return
0;<BR>&nbsp;<BR>&nbsp;err2:<BR>&nbsp;&nbsp;InterlockedDecrement(&amp;listen-&gt;refcnt);<BR>&nbsp;err1:<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;&nbsp;if
(id_priv != NULL)
{<BR>&nbsp;&nbsp;&nbsp;rdma_destroy_id(&amp;id_priv-&gt;id);<BR>&nbsp;&nbsp;}<BR>@@
-1011,7 +1095,7 @@<BR>&nbsp;&nbsp;&nbsp;return
ibvw_wv_errno(hr);<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>-&nbsp;return
ucma_complete(id_priv);<BR>+&nbsp;return
ucma_complete_priv(id_priv);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;__declspec(dllexport)<BR>@@
-1053,7 +1137,7 @@<BR>&nbsp;&nbsp;&nbsp;return
ibvw_wv_errno(hr);<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>-&nbsp;return
ucma_complete(id_priv);<BR>+&nbsp;return
ucma_complete_priv(id_priv);<BR>&nbsp;}<BR>&nbsp;<BR>&nbsp;__declspec(dllexport)<BR>@@
-1179,7 +1263,7 @@<BR>&nbsp;<BR>&nbsp;&nbsp;id_priv =
event-&gt;id_priv;<BR>&nbsp;<BR>-&nbsp;EnterCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_acquire(&amp;lock);<BR>&nbsp;&nbsp;switch
(id_priv-&gt;state) {<BR>&nbsp;&nbsp;case
cma_get_request:<BR>&nbsp;&nbsp;&nbsp;listen = (struct cma_id_private *)
id_priv-&gt;id.context;<BR>@@ -1190,7 +1274,7
@@<BR>&nbsp;&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;listen-&gt;req_list[id_priv-&gt;index]
=
NULL;<BR>-&nbsp;&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;&nbsp;&nbsp;return
ucma_process_conn_req(event);<BR>&nbsp;&nbsp;case
cma_addr_resolve:<BR>&nbsp;&nbsp;&nbsp;event-&gt;event.event =
RDMA_CM_EVENT_ADDR_RESOLVED;<BR>@@ -1216,7 +1300,7
@@<BR>&nbsp;&nbsp;&nbsp;InterlockedDecrement(&amp;id_priv-&gt;refcnt);<BR>&nbsp;&nbsp;&nbsp;ret
=
ECANCELED;<BR>&nbsp;&nbsp;}<BR>-&nbsp;LeaveCriticalSection(&amp;lock);<BR>+&nbsp;fastlock_release(&amp;lock);<BR>&nbsp;<BR>&nbsp;&nbsp;return
ret;<BR>&nbsp;}<BR>@@ -1240,6 +1324,8 @@<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;ret =
CompChannelPoll(&amp;channel-&gt;channel, &amp;entry);<BR>&nbsp;&nbsp;&nbsp;if
(ret) {<BR>+&nbsp;&nbsp;&nbsp;if (ret ==
WAIT_TIMEOUT)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;ret =
ERR(EWOULDBLOCK);<BR>&nbsp;&nbsp;&nbsp;&nbsp;delete
evt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;return ret;<BR>&nbsp;&nbsp;&nbsp;}<BR>@@ -1473,3
+1559,11 @@<BR>&nbsp;&nbsp;}<BR>&nbsp;&nbsp;return -1;<BR>&nbsp;}<BR>+<BR>+int
ucma_max_qpsize(struct rdma_cm_id *id)<BR>+{<BR>+&nbsp;struct cma_id_private
*id_priv;<BR>+<BR>+&nbsp;id_priv = container_of(id, struct cma_id_private,
id);<BR>+&nbsp;return id_priv-&gt;cma_dev-&gt;max_qpsize;<BR>+}<BR>Index:
ulp/librdmacm/src/cma.h<BR>===================================================================<BR>---
ulp/librdmacm/src/cma.h&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/cma.h&nbsp;(working copy)<BR>@@ -1,9 +1,9
@@<BR>&nbsp;/*<BR>&nbsp; * Copyright (c) 2004, 2005 Topspin
Communications.&nbsp; All rights reserved.<BR>&nbsp; * Copyright (c) 2008-2009
Intel Corp.&nbsp; All rights reserved.<BR>+ * Copyright (c) 2012 Oce Printing
Systems GmbH.&nbsp; All rights reserved.<BR>&nbsp; *<BR>- * This software is
available to you under the OpenIB.org BSD license<BR>- * below:<BR>+ * This
software is available to you under the BSD license below:<BR>&nbsp; *<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source and binary forms,
with or<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted
provided that the following<BR>@@ -18,24 +18,60 @@<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
provided with the distribution.<BR>&nbsp; *<BR>- * THE SOFTWARE IS PROVIDED "AS
IS", WITHOUT WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AWV<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing
Systems GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
the authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>&nbsp; */<BR>&nbsp;<BR>&nbsp;#ifndef CMA_H<BR>&nbsp;#define
CMA_H<BR>&nbsp;<BR>-extern CRITICAL_SECTION lock;<BR>-extern HANDLE
heap;<BR>+#include &lt;complib/cl_spinlock.h&gt;<BR>+#include
&lt;rdma/rdma_verbs.h&gt;<BR>&nbsp;<BR>+/*<BR>+ * Fast synchronization for low
contention locking.<BR>+ */<BR>+#define
fastlock_t&nbsp;&nbsp;&nbsp;&nbsp;cl_spinlock_t<BR>+#define
fastlock_init(lock)&nbsp;&nbsp;cl_spinlock_init(lock)<BR>+#define
fastlock_destroy(lock)&nbsp;cl_spinlock_destroy(lock)<BR>+#define
fastlock_acquire(lock)&nbsp;cl_spinlock_acquire(lock)<BR>+#define
fastlock_release(lock)&nbsp;cl_spinlock_release(lock)<BR>+<BR>+extern fastlock_t
lock;<BR>+extern HANDLE&nbsp;&nbsp;&nbsp;&nbsp; heap;<BR>+<BR>+#define
TRACE(fmt, ...) Trace(__FUNCTION__": " fmt "\n", __VA_ARGS__)<BR>+<BR>+void
Trace(const char* fmt, ...);<BR>&nbsp;void ucma_cleanup();<BR>+int
ucma_max_qpsize(struct rdma_cm_id *id);<BR>+int ucma_complete(struct rdma_cm_id
*id);<BR>+void wsa_setlasterror(int err);<BR>&nbsp;<BR>+static __inline int
ERR(int err)<BR>+{<BR>+&nbsp;&nbsp;&nbsp; int ret =
rdma_seterrno(err);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;wsa_setlasterror(err);<BR>+&nbsp;return ret;<BR>+}<BR>+
<BR>&nbsp;__inline void* __cdecl operator new(size_t
size)<BR>&nbsp;{<BR>&nbsp;&nbsp;return HeapAlloc(heap, 0, size);<BR>@@ -46,4
+82,13 @@<BR>&nbsp;&nbsp;HeapFree(heap, 0,
pObj);<BR>&nbsp;}<BR>&nbsp;<BR>+#ifndef SYSCONFDIR<BR>+#define SYSCONFDIR
"/etc"<BR>+#endif<BR>+#ifndef RDMADIR<BR>+#define RDMADIR
"rdma"<BR>+#endif<BR>+#define RDMA_CONF_DIR&nbsp; SYSCONFDIR "/"
RDMADIR<BR>+#define RS_CONF_DIR RDMA_CONF_DIR "/rsocket"<BR>+<BR>&nbsp;#endif /*
CMA_H */<BR>Index:
ulp/librdmacm/src/cma_exports.src<BR>===================================================================<BR>---
ulp/librdmacm/src/cma_exports.src&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/cma_exports.src&nbsp;(working copy)<BR>@@ -30,4 +30,30
@@<BR>&nbsp;rdma_freeaddrinfo<BR>&nbsp;rdma_get_request<BR>&nbsp;rdmaw_wsa_errno<BR>+rsocket<BR>+rbind<BR>+rlisten<BR>+raccept<BR>+rconnect<BR>+rshutdown<BR>+rclose<BR>+rrecv<BR>+rrecvfrom<BR>+rrecvmsg<BR>+rsend<BR>+rsendto<BR>+rsendmsg<BR>+rread<BR>+rreadv<BR>+rwrite<BR>+rwritev<BR>+rgetpeername<BR>+rgetsockname<BR>+rsetsockopt<BR>+rgetsockopt<BR>+rfcntl<BR>+rioctlsocket<BR>+rselect<BR>+rpoll<BR>+WSPStartup<BR>&nbsp;#endif<BR>Index:
ulp/librdmacm/src/cma_main.cpp<BR>===================================================================<BR>---
ulp/librdmacm/src/cma_main.cpp&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/cma_main.cpp&nbsp;(working copy)<BR>@@ -1,8 +1,8
@@<BR>&nbsp;/*<BR>- * Copyright (c) 2008-2009 Intel Corporation. All rights
reserved.<BR>+ * Copyright (c) 2008-2009 Intel Corporation.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>&nbsp; *<BR>- * This software is available to you under the
OpenIB.org BSD license<BR>- * below:<BR>+ * This software is available to you
under the BSD license below:<BR>&nbsp; *<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;
Redistribution and use in source and binary forms, with or<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp; without modification, are permitted provided that the
following<BR>@@ -17,22 +17,1173 @@<BR>&nbsp;
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; disclaimer in the documentation
and/or other materials<BR>&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
provided with the distribution.<BR>&nbsp; *<BR>- * THE SOFTWARE IS PROVIDED "AS
IS", WITHOUT WARRANTY OF ANY KIND,<BR>- * EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF<BR>- * MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AWV<BR>- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS<BR>- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN<BR>- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<BR>-
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<BR>- *
SOFTWARE.<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing
Systems GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
the authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE. <BR>&nbsp; */<BR>-<BR>-#include &lt;windows.h&gt;<BR>+ <BR>+#include
"openib_osd.h" <BR>&nbsp;#include "cma.h"<BR>+#include
"rdma/rwinsock.h"<BR>+#include "rdma/rsocket.h"<BR>+#include
&lt;complib/cl_debug.h&gt;<BR>+#include "../../../etc/user/gtod.c" //
getimeofday()<BR>&nbsp;<BR>-CRITICAL_SECTION lock;<BR>-HANDLE heap;<BR>+#include
&lt;strsafe.h&gt;<BR>+#include &lt;stdio.h&gt;<BR>+#include
&lt;stdlib.h&gt;<BR>&nbsp;<BR>+#define MAX_TRACE_INDEX 4096 // Has to be a power
of 2<BR>+<BR>+typedef struct {<BR>+&nbsp;FILETIME&nbsp;
fTime;<BR>+&nbsp;char*&nbsp;&nbsp; pszFormat;<BR>+&nbsp;ULONG64&nbsp;
qwArgs[4];<BR>+} RS_TRACE, *LPRS_TRACE;<BR>+<BR>+/*<BR>+ * Globals used across
files<BR>+ */<BR>+CRITICAL_SECTION&nbsp;&nbsp;&nbsp;
gCriticalSection;&nbsp;&nbsp; // Critical section to protect
startup/cleanup<BR>+WSPUPCALLTABLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
gMainUpCallTable;&nbsp;&nbsp; // Winsock upcall
table<BR>+WSAPROTOCOL_INFOW&nbsp;gProtocolInfo;<BR>+BOOL&nbsp;&nbsp;&nbsp;&nbsp;gDetached
= FALSE;&nbsp; // Indicates if process is detaching from
DLL<BR>+fastlock_t&nbsp;&nbsp;&nbsp;lock;<BR>+fastlock_t&nbsp;&nbsp;&nbsp;mut;<BR>+HANDLE&nbsp;&nbsp;&nbsp;&nbsp;heap;<BR>+<BR>+/*<BR>+
* Globals local to this file<BR>+ */<BR>+static const WCHAR
*Description&nbsp;&nbsp;&nbsp; = L"OpenFabrics RSockets for
InfiniBand";<BR>+static
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gStartupCount =
0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Global startup count (for every WSPStartup
call)<BR>+static uint32_t&nbsp;&nbsp;
iTrace&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;<BR>+static
RS_TRACE&nbsp;&nbsp;rsTrace[MAX_TRACE_INDEX] = {0};<BR>+static
fastlock_t&nbsp;&nbsp;&nbsp;&nbsp; TraceLock;<BR>+<BR>+/*<BR>+ * Create trace
entries at runtime<BR>+ */<BR>+void Trace (const char* fmt,
...)<BR>+{<BR>+&nbsp;struct
timeval&nbsp;time;<BR>+&nbsp;va_list&nbsp;&nbsp;&nbsp;argptr;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;i;<BR>+<BR>+&nbsp;fastlock_acquire(&amp;TraceLock);<BR>+<BR>+&nbsp;GetSystemTimeAsFileTime(&amp;rsTrace[iTrace].fTime);<BR>+&nbsp;rsTrace[iTrace].pszFormat
= (char *)fmt;<BR>+<BR>+&nbsp;va_start(argptr, fmt);<BR>+&nbsp;for (i = 0; i
&lt; sizeof(rsTrace[0].qwArgs) / sizeof(rsTrace[0].qwArgs[0]);
i++)<BR>+&nbsp;&nbsp;rsTrace[iTrace].qwArgs[i] = va_arg(argptr,
uint64_t);<BR>+&nbsp;va_end(argptr);<BR>+<BR>+&nbsp;iTrace = (iTrace + 1) &amp;
(MAX_TRACE_INDEX-1);<BR>+<BR>+&nbsp;fastlock_release(&amp;TraceLock);<BR>+&nbsp;<BR>+&nbsp;return;<BR>+}<BR>+<BR>+/**<BR>+
* \brief&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get current RSockets trace information for
the calling process<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(by calling
librdmacm.dll directly).<BR>+ *<BR>+ * \param lppTraceBuffer&nbsp;Pointer to a
buffer with an array of RS_TRACE information entries<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to be allocated and returned. The
caller is responsible for<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deallocating that buffer via free()
when it is no longer needed.<BR>+ *<BR>+ *
\return&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The number of RS_TRACE entries contained in
the trace buffer<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returned by
*lppTraceBuffer.<BR>+ */<BR>+static uint32_t rsGetTrace ( __out LPRS_TRACE_OUT
*lppTraceBuffer )<BR>+{<BR>+&nbsp;uint32_t i, e, count = 0;<BR>+&nbsp;struct
timeval tvTime;<BR>+<BR>+&nbsp;if (NULL ==&nbsp;&nbsp; lppTraceBuffer
||<BR>+&nbsp;&nbsp;NULL == (*lppTraceBuffer =
(LPRS_TRACE_OUT)malloc(MAX_TRACE_INDEX *
sizeof(**lppTraceBuffer)))<BR>+&nbsp;&nbsp;&nbsp; )<BR>+&nbsp;&nbsp;return
0;<BR>+<BR>+&nbsp;memset( *lppTraceBuffer, 0, MAX_TRACE_INDEX *
sizeof(**lppTraceBuffer)
);<BR>+&nbsp;<BR>+&nbsp;fastlock_acquire(&amp;TraceLock);<BR>+&nbsp;for
(<BR>+&nbsp;&nbsp;&nbsp;i = 0, e = iTrace;<BR>+&nbsp;&nbsp;&nbsp;i &lt;
MAX_TRACE_INDEX;<BR>+&nbsp;&nbsp;&nbsp;i++, e = (e+1) &amp; (MAX_TRACE_INDEX -
1)<BR>+&nbsp;&nbsp;)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;if
(rsTrace[e].pszFormat)<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;FileTimeToTimeval(&amp;rsTrace[e].fTime,
&amp;tvTime);<BR>+&nbsp;&nbsp;&nbsp;sprintf_s(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(*lppTraceBuffer)[i].szLine,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;sizeof((*lppTraceBuffer)[0].szLine),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;"%010d:%010d
%s",<BR>+&nbsp;&nbsp;&nbsp;&nbsp;tvTime.tv_sec,
tvTime.tv_usec,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rsTrace[e].pszFormat,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rsTrace[e].qwArgs[0],
rsTrace[e].qwArgs[1], rsTrace[e].qwArgs[2],
rsTrace[e].qwArgs[3]<BR>+&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;&nbsp;cl_dbg_out("%s",
(*lppTraceBuffer)[i].szLine);<BR>+&nbsp;&nbsp;&nbsp;count++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;fastlock_release(&amp;TraceLock);<BR>+&nbsp;<BR>+&nbsp;return
count;<BR>+}<BR>+<BR>+/*<BR>+ * SPI Function Implementation<BR>+ */<BR>+<BR>+/*
<BR>+ * Function: WSPCleanup<BR>+ *<BR>+ * Description:<BR>+ *&nbsp;&nbsp;&nbsp;
Decrement the entry count. If equal to zero then we can prepare to have us<BR>+
*&nbsp;&nbsp;&nbsp; unloaded so all resources should be freed<BR>+ */<BR>+int
WSPAPI <BR>+WSPCleanup(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPINT
lpErrno&nbsp; <BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
)<BR>+{<BR>+&nbsp;&nbsp;&nbsp; int rc =
SOCKET_ERROR;<BR>+<BR>+&nbsp;&nbsp;&nbsp; if ( gDetached )
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rc =
NO_ERROR;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto
cleanup;<BR>+&nbsp;&nbsp;&nbsp; }<BR>+<BR>+&nbsp;&nbsp;&nbsp;
//<BR>+&nbsp;&nbsp;&nbsp; // Grab the DLL global critical
section<BR>+&nbsp;&nbsp;&nbsp; //<BR>+&nbsp;&nbsp;&nbsp; EnterCriticalSection(
&amp;gCriticalSection );<BR>+<BR>+&nbsp;&nbsp;&nbsp; // Verify WSPStartup has
been called<BR>+&nbsp;&nbsp;&nbsp; if ( 0 == gStartupCount )
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *lpErrno =
WSANOTINITIALISED;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto
cleanup;<BR>+&nbsp;&nbsp;&nbsp; }<BR>+<BR>+&nbsp;&nbsp;&nbsp; // Decrement the
global entry count<BR>+&nbsp;&nbsp;&nbsp;
gStartupCount--;<BR>+<BR>+TRACE("StartupCount decremented to %d",
gStartupCount);<BR>+<BR>+&nbsp;&nbsp;&nbsp; if ( 0 == gStartupCount )
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Free LSP structures if still
present as well as call
WSPCleanup<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;
for all providers this LSP loaded<BR>+&nbsp;&nbsp;&nbsp;
}<BR>+&nbsp;&nbsp;&nbsp; rc = NO_ERROR;<BR>+<BR>+cleanup:<BR>+&nbsp;&nbsp;&nbsp;
LeaveCriticalSection( &amp;gCriticalSection );<BR>+<BR>+&nbsp;&nbsp;&nbsp;
return rc;<BR>+}<BR>+<BR>+/*<BR>+ * Function: WSPSocket<BR>+ *<BR>+ *
Description:<BR>+ *&nbsp;&nbsp;&nbsp; This routine creates a socket. For an IFS
LSP the lower provider's socket<BR>+ *&nbsp;&nbsp;&nbsp; handle is returned to
the uppler layer. When a socket is created, a socket<BR>+ *&nbsp;&nbsp;&nbsp;
context structure is created for the socket returned from the lower
provider.<BR>+ *&nbsp;&nbsp;&nbsp; This context is used if the socket is later
connected to a proxied address.<BR>+ */<BR>+SOCKET WSPAPI
<BR>+WSPSocket(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
af,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
type,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
protocol,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPWSAPROTOCOL_INFOW
lpProtocolInfo,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
GROUP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
g,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
dwFlags,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
LPINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
lpErrno<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
)<BR>+{<BR>+&nbsp;&nbsp;&nbsp; WSAPROTOCOL_INFOW&nbsp;&nbsp; InfoCopy =
{0};<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs =
(int)INVALID_SOCKET;<BR>+&nbsp;&nbsp;&nbsp;
SOCKET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
winSocket =
INVALID_SOCKET,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sret = INVALID_SOCKET;<BR>+&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rc;<BR>+<BR>+TRACE("af=%d&nbsp; type=%d&nbsp; protocol=%d&nbsp; flags=0x%X", af,
type, protocol, dwFlags);<BR>+<BR>+&nbsp;if (af != AF_INET)
{<BR>+&nbsp;&nbsp;*lpErrno = WSAEAFNOSUPPORT;<BR>+&nbsp;&nbsp;return
INVALID_SOCKET;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (type != SOCK_STREAM)
{<BR>+&nbsp;&nbsp;*lpErrno = WSAEPROTOTYPE;<BR>+&nbsp;&nbsp;return
INVALID_SOCKET;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (protocol != IPPROTO_TCP)
{<BR>+&nbsp;&nbsp;*lpErrno = WSAEPROTONOSUPPORT;<BR>+&nbsp;&nbsp;return
INVALID_SOCKET;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (dwFlags != 0)
{<BR>+&nbsp;&nbsp;*lpErrno = WSAEINVAL;<BR>+&nbsp;&nbsp;return
INVALID_SOCKET;<BR>+&nbsp;}<BR>+<BR>+&nbsp;&nbsp;&nbsp;
//<BR>+&nbsp;&nbsp;&nbsp; // Create the socket from the lower
layer<BR>+&nbsp;&nbsp;&nbsp; //<BR>+&nbsp;if ( INVALID_SOCKET == (rs = rsocket(
af, type, protocol)) ) {<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; goto
cleanup;<BR>+&nbsp;&nbsp;&nbsp; }<BR>+<BR>+&nbsp;winSocket =
gMainUpCallTable.lpWPUCreateSocketHandle(<BR>+&nbsp;&nbsp;&nbsp;gProtocolInfo.dwCatalogEntryId,<BR>+&nbsp;&nbsp;&nbsp;rs,&nbsp;//
__in&nbsp; DWORD_PTR
dwContext<BR>+&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;);<BR>+&nbsp;if
(INVALID_SOCKET == winSocket)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
goto cleanup;<BR>+<BR>+TRACE("&nbsp; New socket handle = %d",
winSocket);<BR>+<BR>+&nbsp;&nbsp;&nbsp; return
winSocket;<BR>+<BR>+cleanup:<BR>+<BR>+&nbsp;&nbsp;&nbsp; // If an error occured
close the socket if it was already created<BR>+&nbsp;&nbsp;&nbsp; if
(INVALID_SOCKET != rs)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rclose((int)rs);<BR>+&nbsp;<BR>+&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+&nbsp;&nbsp;&nbsp; return
INVALID_SOCKET;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPBind(<BR>+&nbsp;__in&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp; const struct sockaddr*
name,<BR>+&nbsp;__in&nbsp;&nbsp; int namelen,<BR>+&nbsp;__out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;struct sockaddr_in * name_in&nbsp; = (struct
sockaddr_in *)name;<BR>+&nbsp;struct sockaddr_in6* name_in6 = (struct
sockaddr_in6*)name;<BR>+<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;ret = rbind((int)rs, name, namelen);<BR>+&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+TRACE("Socket = %d:", s);<BR>+&nbsp;if (AF_INET ==
name-&gt;sa_family) {<BR>+&nbsp;&nbsp;TRACE("&nbsp; Addr =
%d.%d.%d.%d",<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b1,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b2,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b3,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b4<BR>+&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;TRACE("&nbsp;
Port = %d,&nbsp;&nbsp; Returning %d", name_in-&gt;sin_port, ret);<BR>+&nbsp;}
else {<BR>+&nbsp;&nbsp;TRACE("&nbsp; Addr =
%d:%d:%d:%d:%d:%d:%d:%d",<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[0],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[1],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[2],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[3],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[4],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[5],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[6],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[7]<BR>+&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;TRACE("&nbsp;
Port = %d ,&nbsp; Returning %d", name_in6-&gt;sin6_port,
ret);<BR>+&nbsp;}<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPListen(<BR>+&nbsp;__in&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp; int backlog,<BR>+&nbsp;__out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;<BR>+&nbsp;ret = rlisten((int)rs, backlog);<BR>+&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+TRACE("Socket = %d: Backlog=%d, Returning %d", s,
backlog, ret);<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPConnect(<BR>+&nbsp;__in&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp; const struct sockaddr*
name,<BR>+&nbsp;__in&nbsp;&nbsp; int namelen,<BR>+&nbsp;__in&nbsp;&nbsp;
LPWSABUF lpCallerData,<BR>+&nbsp;__out&nbsp; LPWSABUF
lpCalleeData,<BR>+&nbsp;__in&nbsp;&nbsp; LPQOS
lpSQOS,<BR>+&nbsp;__in&nbsp;&nbsp; LPQOS lpGQOS,<BR>+&nbsp;__out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;struct sockaddr_in * name_in&nbsp; = (struct
sockaddr_in *)name;<BR>+&nbsp;struct sockaddr_in6* name_in6 = (struct
sockaddr_in6*)name;<BR>+<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;<BR>+&nbsp;ret = rconnect((int)rs, name, namelen);<BR>+&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+&nbsp;if
(lpCalleeData)<BR>+&nbsp;&nbsp;lpCalleeData-&gt;len = 0;<BR>+<BR>+TRACE("Socket
= %d:", s);<BR>+&nbsp;if (AF_INET == name-&gt;sa_family)
{<BR>+&nbsp;&nbsp;TRACE("&nbsp; Addr =
%d.%d.%d.%d",<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b1,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b2,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b3,<BR>+&nbsp;&nbsp;&nbsp;name_in-&gt;sin_addr.S_un.S_un_b.s_b4<BR>+&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;TRACE("&nbsp;
Port = %d,&nbsp;&nbsp; Returning %d", name_in-&gt;sin_port, ret);<BR>+&nbsp;}
else {<BR>+&nbsp;&nbsp;TRACE("&nbsp; Addr =
%d:%d:%d:%d:%d:%d:%d:%d",<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[0],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[1],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[2],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[3],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[4],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[5],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[6],<BR>+&nbsp;&nbsp;&nbsp;name_in6-&gt;sin6_addr.u.Word[7]<BR>+&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;TRACE("&nbsp;
Port = %d ,&nbsp; Returning %d", name_in6-&gt;sin6_port,
ret);<BR>+&nbsp;}<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPShutdown(<BR>+&nbsp;__in&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp; int how,<BR>+&nbsp;__out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;<BR>+&nbsp;ret = rshutdown((int)rs, how);<BR>+&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+TRACE("Socket = %d: how=%d, Returning %d", s, how,
ret);<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPCloseSocket(<BR>+&nbsp;__in&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__out&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;<BR>+&nbsp;ret = rclose((int)rs);<BR>+&nbsp;if (SOCKET_ERROR ==
ret)<BR>+&nbsp;&nbsp;*lpErrno = WSAGetLastError();<BR>+&nbsp;<BR>+&nbsp;ret =
gMainUpCallTable.lpWPUCloseSocketHandle(s, lpErrno);<BR>+<BR>+TRACE("Socket
handle %s closed", s);<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPRecv(<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;
SOCKET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s,<BR>+&nbsp;__inout
LPWSABUF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwBufferCount,<BR>+&nbsp;__out&nbsp;&nbsp;
LPDWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpNumberOfBytesRecvd,<BR>+&nbsp;__inout
LPDWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpFlags,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;
LPWSAOVERLAPPED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpOverlapped,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;
LPWSAOVERLAPPED_COMPLETION_ROUTINE&nbsp;lpCompletionRoutine,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;
LPWSATHREADID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpThreadId,<BR>+&nbsp;__out&nbsp;&nbsp;
LPINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR
rs&nbsp; = INVALID_SOCKET;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;
i;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp; dwNumberOfBytesRecvd =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; len =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;for (i = 0; i &lt; dwBufferCount; i++) {<BR>+&nbsp;&nbsp;len
= (int)rrecv((int)rs, lpBuffers[i].buf, lpBuffers[i].len,
*lpFlags);<BR>+&nbsp;&nbsp;switch (len) {<BR>+&nbsp;&nbsp;case&nbsp;
0:<BR>+&nbsp;&nbsp;&nbsp;goto out;<BR>+&nbsp;&nbsp;case
-1:<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp; =
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;dwNumberOfBytesRecvd +=
len;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+out:<BR>+&nbsp;*lpNumberOfBytesRecvd
= dwNumberOfBytesRecvd;<BR>+&nbsp;<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPSend(<BR>+&nbsp;__in&nbsp;
SOCKET&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s,<BR>+&nbsp;__in&nbsp;
LPWSABUF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers,<BR>+&nbsp;__in&nbsp;
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwBufferCount,<BR>+&nbsp;__out
LPDWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpNumberOfBytesSent,<BR>+&nbsp;__in&nbsp;
DWORD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwFlags,<BR>+&nbsp;__in&nbsp;
LPWSAOVERLAPPED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpOverlapped,<BR>+&nbsp;__in&nbsp;
LPWSAOVERLAPPED_COMPLETION_ROUTINE&nbsp;lpCompletionRoutine,<BR>+&nbsp;__in&nbsp;
LPWSATHREADID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpThreadId,<BR>+&nbsp;__out
LPINT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR
rs&nbsp; = INVALID_SOCKET;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;
i;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp; dwNumberOfBytesSent =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
len;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;for (i = 0; i &lt; dwBufferCount; i++) {<BR>+&nbsp;&nbsp;len
= (int)rsend((int)rs, lpBuffers[i].buf, lpBuffers[i].len,
dwFlags);<BR>+&nbsp;&nbsp;if (-1 == len) {<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp; =
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;&nbsp; break;<BR>+&nbsp;&nbsp;}
else<BR>+&nbsp;&nbsp;&nbsp;dwNumberOfBytesSent +=
len;<BR>+&nbsp;}<BR>+&nbsp;*lpNumberOfBytesSent =
dwNumberOfBytesSent;<BR>+&nbsp;<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPGetSockOpt(<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
level,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
optname,<BR>+&nbsp;__out&nbsp;&nbsp;&nbsp; char* optval,<BR>+&nbsp;__inout&nbsp;
LPINT optlen,<BR>+&nbsp;__out&nbsp;&nbsp;&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;<BR>+&nbsp;ret = rgetsockopt((int)rs, level, optname, optval,
optlen);<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPSetSockOpt(<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
level,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
optname,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; const char*
optval,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
optlen,<BR>+&nbsp;__out&nbsp;&nbsp;&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;ret = rsetsockopt((int)rs, level, optname, optval,
optlen);<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPSelect(<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; int
nfds,<BR>+&nbsp;__inout&nbsp; fd_set* readfds,<BR>+&nbsp;__inout&nbsp; fd_set*
writefds,<BR>+&nbsp;__inout&nbsp; fd_set*
exceptfds,<BR>+&nbsp;__in&nbsp;&nbsp;&nbsp;&nbsp; const struct timeval*
timeout,<BR>+&nbsp;__out&nbsp;&nbsp;&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;u_int&nbsp; i;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
ret;<BR>+&nbsp;fd_set rreadfds, rwritefds,
rexceptfds;<BR>+&nbsp;<BR>+&nbsp;FD_ZERO(&amp;rreadfds);<BR>+&nbsp;FD_ZERO(&amp;rwritefds);<BR>+&nbsp;FD_ZERO(&amp;rexceptfds);<BR>+&nbsp;<BR>+&nbsp;nfds
= 1;<BR>+<BR>+&nbsp;for (i = 0; readfds &amp;&amp; i &lt; readfds-&gt;fd_count;
i++) {<BR>+&nbsp;&nbsp;if (readfds-&gt;fd_array[i]) {<BR>+&nbsp;&nbsp;&nbsp;ret
=
gMainUpCallTable.lpWPUQuerySocketHandleContext(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
readfds-&gt;fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;rreadfds.fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;&nbsp;<BR>+&nbsp;&nbsp;&nbsp;if (rreadfds.fd_array[i] &gt;
nfds)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;nfds =
(int)rreadfds.fd_array[i];<BR>+<BR>+&nbsp;&nbsp;&nbsp;rreadfds.fd_count++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;for
(i = 0; writefds &amp;&amp; i &lt; writefds-&gt;fd_count; i++)
{<BR>+&nbsp;&nbsp;if (writefds-&gt;fd_array[i]) {<BR>+&nbsp;&nbsp;&nbsp;ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
writefds-&gt;fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;rwritefds.fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;&nbsp;&nbsp;if (rwritefds.fd_array[i] &gt;
nfds)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;nfds =
(int)rwritefds.fd_array[i];<BR>+<BR>+&nbsp;&nbsp;&nbsp;rwritefds.fd_count++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;for
(i = 0; exceptfds &amp;&amp; i &lt; exceptfds-&gt;fd_count; i++)
{<BR>+&nbsp;&nbsp;if (exceptfds-&gt;fd_array[i]) {<BR>+&nbsp;&nbsp;&nbsp;ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
exceptfds-&gt;fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;rexceptfds.fd_array[i],<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;&nbsp;&nbsp;if (rexceptfds.fd_array[i] &gt;
nfds)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;nfds =
(int)rexceptfds.fd_array[i];<BR>+<BR>+&nbsp;&nbsp;&nbsp;rexceptfds.fd_count++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;ret
= rselect(<BR>+&nbsp;&nbsp;&nbsp;nfds + 1, // Max. valid rsocket descriptor +
1<BR>+&nbsp;&nbsp;&nbsp;readfds&nbsp;&nbsp; ? &amp;rreadfds&nbsp;&nbsp; :
NULL,<BR>+&nbsp;&nbsp;&nbsp;writefds&nbsp; ? &amp;rwritefds&nbsp; :
NULL,<BR>+&nbsp;&nbsp;&nbsp;exceptfds ? &amp;rexceptfds :
NULL,<BR>+&nbsp;&nbsp;&nbsp;(struct
timeval*)timeout<BR>+&nbsp;&nbsp;);<BR>+&nbsp;if (SOCKET_ERROR == ret)
{<BR>+&nbsp;&nbsp;*lpErrno = WSAGetLastError();<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+&nbsp;nfds = ret;<BR>+&nbsp;<BR>+&nbsp;for (i = 0; ret
&amp;&amp; readfds &amp;&amp; i &lt; rreadfds.fd_count; i++)
{<BR>+&nbsp;&nbsp;if (rreadfds.fd_array[i] &amp;&amp; readfds-&gt;fd_array[i])
{<BR>+&nbsp;&nbsp;&nbsp;ret--;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;readfds-&gt;fd_array[i] =
0;<BR>+&nbsp;&nbsp;&nbsp;readfds-&gt;fd_count--;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;for
(i = 0; ret &amp;&amp; writefds &amp;&amp; i &lt; rwritefds.fd_count; i++)
{<BR>+&nbsp;&nbsp;if (rwritefds.fd_array[i] &amp;&amp; writefds-&gt;fd_array[i])
{<BR>+&nbsp;&nbsp;&nbsp;ret--;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;writefds-&gt;fd_array[i] =
0;<BR>+&nbsp;&nbsp;&nbsp;writefds-&gt;fd_count--;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;for
(i = 0; ret &amp;&amp; exceptfds &amp;&amp; i &lt; rexceptfds.fd_count; i++)
{<BR>+&nbsp;&nbsp;if (rexceptfds.fd_array[i] &amp;&amp;
exceptfds-&gt;fd_array[i]) {<BR>+&nbsp;&nbsp;&nbsp;ret--;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;exceptfds-&gt;fd_array[i] =
0;<BR>+&nbsp;&nbsp;&nbsp;exceptfds-&gt;fd_count--;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;return
(nfds - ret);<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPIoctl(<BR>+&nbsp;__in&nbsp;
SOCKET s,<BR>+&nbsp;__in&nbsp; DWORD dwIoControlCode,<BR>+&nbsp;__in&nbsp;
LPVOID lpvInBuffer,<BR>+&nbsp;__in&nbsp; DWORD cbInBuffer,<BR>+&nbsp;__out
LPVOID lpvOutBuffer,<BR>+&nbsp;__in&nbsp; DWORD cbOutBuffer,<BR>+&nbsp;__out
LPDWORD lpcbBytesReturned,<BR>+&nbsp;__in&nbsp; LPWSAOVERLAPPED
lpOverlapped,<BR>+&nbsp;__in&nbsp; LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,<BR>+&nbsp;__in&nbsp; LPWSATHREADID
lpThreadId,<BR>+&nbsp;__out LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
0;<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;
dwCount;<BR>+&nbsp;LPVOID&nbsp;&nbsp;&nbsp; lpResultBuffer =
NULL;<BR>+&nbsp;<BR>+&nbsp;*lpcbBytesReturned = 0;<BR>+&nbsp;<BR>+&nbsp;ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;switch (dwIoControlCode) {<BR>+&nbsp;case
SIO_RS_GET_STATUS:<BR>+&nbsp;&nbsp;if (lpvOutBuffer)
{<BR>+&nbsp;&nbsp;&nbsp;dwCount = rsGetStatus((LPRS_STATUS
*)&amp;lpResultBuffer);<BR>+&nbsp;&nbsp;&nbsp;if (lpResultBuffer)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if (cbOutBuffer &gt;= dwCount * sizeof(RS_STATUS))
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpcbBytesReturned = dwCount *
sizeof(RS_STATUS);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp;&nbsp;=
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpErrno&nbsp;&nbsp;&nbsp;=
WSA_IO_INCOMPLETE;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpcbBytesReturned&nbsp;=
cbOutBuffer; // Copy as much as possible
anyway<BR>+&nbsp;&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
SIO_RS_GET_TRACE:<BR>+&nbsp;&nbsp;if (lpvOutBuffer)
{<BR>+&nbsp;&nbsp;&nbsp;dwCount = rsGetTrace((LPRS_TRACE_OUT
*)&amp;lpResultBuffer);<BR>+&nbsp;&nbsp;&nbsp;if (lpResultBuffer)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if (cbOutBuffer &gt;= dwCount *
sizeof(RS_TRACE_OUT)) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpcbBytesReturned =
dwCount * sizeof(RS_TRACE_OUT);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp;&nbsp;&nbsp;=
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpErrno&nbsp;&nbsp;&nbsp;=
WSA_IO_INCOMPLETE;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpcbBytesReturned&nbsp;=
cbOutBuffer; // Copy as much as possible
anyway<BR>+&nbsp;&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
FIONBIO:<BR>+&nbsp;case FIONREAD:<BR>+&nbsp;case SIOCATMARK:<BR>+&nbsp;&nbsp;if
(lpvInBuffer &amp;&amp; cbInBuffer &gt;= sizeof(u_long))
{<BR>+&nbsp;&nbsp;&nbsp;ret =
rioctlsocket(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(int)rs,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwIoControlCode,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(u_long
*)lpvInBuffer<BR>+&nbsp;&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;ret
= SOCKET_ERROR;<BR>+&nbsp;&nbsp;*lpErrno = WSAEINVAL;<BR>+&nbsp;}<BR>+&nbsp;if
(lpResultBuffer)&nbsp;{<BR>+&nbsp;&nbsp;memcpy(lpvOutBuffer, lpResultBuffer,
*lpcbBytesReturned);<BR>+&nbsp;&nbsp;free(lpResultBuffer);<BR>+&nbsp;}<BR>+&nbsp;&nbsp;<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPAddressToString(<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; LPSOCKADDR lpsaAddress,<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwAddressLength,<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; LPWSAPROTOCOL_INFOW lpProtocolInfo,<BR>+&nbsp;
__out&nbsp;&nbsp;&nbsp; LPWSTR lpszAddressString,<BR>+&nbsp; __inout&nbsp;
LPDWORD lpdwAddressStringLength,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;int ret = 0;<BR>+&nbsp;<BR>+&nbsp;if
(lpProtocolInfo)&nbsp;{<BR>+&nbsp;&nbsp;if (0 !=
memcmp(&amp;lpProtocolInfo-&gt;ProviderId, &amp;rsProviderGuid,
sizeof(rsProviderGuid))) {<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAEINVALIDPROVIDER;<BR>+&nbsp;&nbsp;&nbsp;return
SOCKET_ERROR;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;if (SOCKET_ERROR == (ret =
WSAAddressToStringW(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpsaAddress,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwAddressLength,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpszAddressString,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpdwAddressStringLength<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)))<BR>+&nbsp;&nbsp;*lpErrno
= WSAGetLastError();<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPAsyncSelect(<BR>+&nbsp; __in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp;
__in&nbsp;&nbsp; HWND hWnd,<BR>+&nbsp; __in&nbsp;&nbsp; unsigned int
wMsg,<BR>+&nbsp; __in&nbsp;&nbsp; long lEvent,<BR>+&nbsp; __out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;*lpErrno = WSAEOPNOTSUPP;<BR>+&nbsp;return
SOCKET_ERROR;<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPCancelBlockingCall(<BR>+&nbsp;
__out&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;*lpErrno =
WSAEOPNOTSUPP;<BR>+&nbsp;return SOCKET_ERROR;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPDuplicateSocket(<BR>+&nbsp;&nbsp;&nbsp; IN SOCKET&nbsp;
s,<BR>+&nbsp;&nbsp;&nbsp; IN DWORD&nbsp; dwProcessId,<BR>+&nbsp;&nbsp;&nbsp; OUT
LPWSAPROTOCOL_INFOW&nbsp; lpProtocolInfo,<BR>+&nbsp;&nbsp;&nbsp; OUT LPINT&nbsp;
lpErrno<BR>+&nbsp;&nbsp;&nbsp; )<BR>+{<BR>+&nbsp;*lpErrno =
WSAEOPNOTSUPP;<BR>+&nbsp;return SOCKET_ERROR;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPEnumNetworkEvents(<BR>+&nbsp;&nbsp;&nbsp; IN SOCKET&nbsp;
s,<BR>+&nbsp;&nbsp;&nbsp; IN WSAEVENT&nbsp; hEventObject,<BR>+&nbsp;&nbsp;&nbsp;
OUT LPWSANETWORKEVENTS&nbsp; lpNetworkEvents,<BR>+&nbsp;&nbsp;&nbsp; OUT
LPINT&nbsp; lpErrno<BR>+&nbsp;&nbsp;&nbsp; )<BR>+{<BR>+&nbsp;*lpErrno =
WSAEOPNOTSUPP;<BR>+&nbsp;return SOCKET_ERROR;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPEventSelect(<BR>+&nbsp; __in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp;
__in&nbsp;&nbsp; WSAEVENT hEventObject,<BR>+&nbsp; __in&nbsp;&nbsp; long
lNetworkEvents,<BR>+&nbsp; __out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;*lpErrno = WSAEOPNOTSUPP;<BR>+&nbsp;return
SOCKET_ERROR;<BR>+}<BR>+<BR>+BOOL
WSPAPI<BR>+WSPGetOverlappedResult(<BR>+&nbsp;&nbsp;&nbsp; IN SOCKET&nbsp;
s,<BR>+&nbsp;&nbsp;&nbsp; IN LPWSAOVERLAPPED&nbsp;
lpOverlapped,<BR>+&nbsp;&nbsp;&nbsp; OUT LPDWORD&nbsp;
lpcbTransfer,<BR>+&nbsp;&nbsp;&nbsp; IN BOOL&nbsp; fWait,<BR>+&nbsp;&nbsp;&nbsp;
OUT LPDWORD&nbsp; lpdwFlags,<BR>+&nbsp;&nbsp;&nbsp; OUT LPINT&nbsp;
lpErrno<BR>+&nbsp;&nbsp;&nbsp; )<BR>+{<BR>+&nbsp;*lpErrno =
WSAEOPNOTSUPP;<BR>+&nbsp;return FALSE;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPGetPeerName(<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; struct sockaddr* name,<BR>+&nbsp;
__inout&nbsp; LPINT namelen,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;if (SOCKET_ERROR == (ret = rgetpeername((int)rs, name,
namelen)))<BR>+&nbsp;&nbsp;*lpErrno = WSAGetLastError();<BR>+<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPGetSockName(<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET s,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; struct
sockaddr* name,<BR>+&nbsp; __inout&nbsp; LPINT namelen,<BR>+&nbsp;
__out&nbsp;&nbsp;&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;if (SOCKET_ERROR == (ret = rgetsockname((int)rs, name,
namelen)))<BR>+&nbsp;&nbsp;*lpErrno = WSAGetLastError();<BR>+<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+BOOL WSPAPI<BR>+WSPGetQOSByName(<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET s,<BR>+&nbsp; __inout&nbsp; LPWSABUF
lpQOSName,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; LPQOS lpQOS,<BR>+&nbsp;
__out&nbsp;&nbsp;&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;*lpErrno =
WSAEOPNOTSUPP;<BR>+&nbsp;return FALSE;<BR>+}<BR>+<BR>+SOCKET
WSPAPI<BR>+WSPJoinLeaf(<BR>+&nbsp; __in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp;
__in&nbsp;&nbsp; const struct sockaddr* name,<BR>+&nbsp; __in&nbsp;&nbsp; int
namelen,<BR>+&nbsp; __in&nbsp;&nbsp; LPWSABUF lpCallerData,<BR>+&nbsp;
__out&nbsp; LPWSABUF lpCalleeData,<BR>+&nbsp; __in&nbsp;&nbsp; LPQOS
lpSQOS,<BR>+&nbsp; __in&nbsp;&nbsp; LPQOS lpGQOS,<BR>+&nbsp; __in&nbsp;&nbsp;
DWORD dwFlags,<BR>+&nbsp; __out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;*lpErrno = WSAEOPNOTSUPP;<BR>+&nbsp;return
INVALID_SOCKET;<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPRecvDisconnect(<BR>+&nbsp;
__in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp; __out&nbsp; LPWSABUF
lpInboundDisconnectData,<BR>+&nbsp; __out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;return WSPShutdown(s, SD_RECEIVE, lpErrno); //
Ignore lpInboundDisconnectData<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPRecvFrom(<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; SOCKET
s,<BR>+&nbsp; __inout&nbsp; LPWSABUF lpBuffers,<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; DWORD dwBufferCount,<BR>+&nbsp;
__out&nbsp;&nbsp;&nbsp; LPDWORD lpNumberOfBytesRecvd,<BR>+&nbsp; __inout&nbsp;
LPDWORD lpFlags,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; struct sockaddr*
lpFrom,<BR>+&nbsp; __inout&nbsp; LPINT lpFromlen,<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; LPWSAOVERLAPPED lpOverlapped,<BR>+&nbsp;
__in&nbsp;&nbsp;&nbsp;&nbsp; LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; LPWSATHREADID
lpThreadId,<BR>+&nbsp; __inout&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR rs&nbsp; =
INVALID_SOCKET;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;
i;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp; dwNumberOfBytesRecvd =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; len =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;for (i = 0; i &lt; dwBufferCount;
i++)&nbsp;{<BR>+&nbsp;&nbsp;switch (len =
(int)rrecvfrom(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(int)rs,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers[i].buf,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers[i].len,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*lpFlags,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpFrom,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpFromlen<BR>+&nbsp;&nbsp;&nbsp;&nbsp;))
{<BR>+&nbsp;&nbsp;case&nbsp; 0:<BR>+&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;case -1:<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAGetLastError();<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp; =
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;dwNumberOfBytesRecvd +=
len;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+out:<BR>+&nbsp;*lpNumberOfBytesRecvd
= dwNumberOfBytesRecvd;<BR>+&nbsp;<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPSendDisconnect(<BR>+&nbsp; __in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp;
__in&nbsp;&nbsp; LPWSABUF lpOutboundDisconnectData,<BR>+&nbsp; __out&nbsp; LPINT
lpErrno<BR>+)<BR>+{<BR>+&nbsp;return WSPShutdown(s, SD_SEND, lpErrno); // Ignore
lpOutboundDisconnectData<BR>+}<BR>+<BR>+int WSPAPI<BR>+WSPSendTo(<BR>+&nbsp;
__in&nbsp;&nbsp; SOCKET s,<BR>+&nbsp; __in&nbsp;&nbsp; LPWSABUF
lpBuffers,<BR>+&nbsp; __in&nbsp;&nbsp; DWORD dwBufferCount,<BR>+&nbsp;
__out&nbsp; LPDWORD lpNumberOfBytesSent,<BR>+&nbsp; __in&nbsp;&nbsp; DWORD
dwFlags,<BR>+&nbsp; __in&nbsp;&nbsp; const struct sockaddr* lpTo,<BR>+&nbsp;
__in&nbsp;&nbsp; int iTolen,<BR>+&nbsp; __in&nbsp;&nbsp; LPWSAOVERLAPPED
lpOverlapped,<BR>+&nbsp; __in&nbsp;&nbsp; LPWSAOVERLAPPED_COMPLETION_ROUTINE
lpCompletionRoutine,<BR>+&nbsp; __in&nbsp;&nbsp; LPWSATHREADID
lpThreadId,<BR>+&nbsp; __out&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;DWORD_PTR
rs&nbsp; = INVALID_SOCKET;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp;
i;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;&nbsp; dwNumberOfBytesSent =
0;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
len;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(s, &amp;rs,
lpErrno);<BR>+<BR>+&nbsp;if (SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;for (i = 0; i &lt; dwBufferCount;
i++)&nbsp;{<BR>+&nbsp;&nbsp;if (-1 == (len =
(int)rsendto(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(int)rs,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers[i].buf,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpBuffers[i].len,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dwFlags,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpTo,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTolen<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)))&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;*lpErrno
= WSAGetLastError();<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret&nbsp;&nbsp; =
SOCKET_ERROR;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;dwNumberOfBytesSent
+= len;<BR>+&nbsp;}<BR>+&nbsp;*lpNumberOfBytesSent =
dwNumberOfBytesSent;<BR>+&nbsp;<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+int
WSPAPI<BR>+WSPStringToAddress(<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; LPWSTR
AddressString,<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; INT
AddressFamily,<BR>+&nbsp; __in&nbsp;&nbsp;&nbsp;&nbsp; LPWSAPROTOCOL_INFO
lpProtocolInfo,<BR>+&nbsp; __out&nbsp;&nbsp;&nbsp; LPSOCKADDR
lpAddress,<BR>+&nbsp; __inout&nbsp; LPINT lpAddressLength,<BR>+&nbsp;
__out&nbsp;&nbsp;&nbsp; LPINT lpErrno<BR>+)<BR>+{<BR>+&nbsp;int ret =
0;<BR>+&nbsp;<BR>+&nbsp;if (AF_INET != AddressFamily &amp;&amp; AddressFamily !=
AF_INET6) {<BR>+&nbsp;&nbsp;*lpErrno = WSAEAFNOSUPPORT;<BR>+&nbsp;&nbsp;return
SOCKET_ERROR;<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;if
(lpProtocolInfo)&nbsp;{<BR>+&nbsp;&nbsp;if (0 !=
memcmp(&amp;lpProtocolInfo-&gt;ProviderId, &amp;rsProviderGuid,
sizeof(rsProviderGuid))) {<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAEINVALIDPROVIDER;<BR>+&nbsp;&nbsp;&nbsp;return
SOCKET_ERROR;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;if
(SOCKET_ERROR == (ret =
WSAStringToAddressW(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddressString,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddressFamily,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NULL,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpAddress,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpAddressLength<BR>+&nbsp;&nbsp;&nbsp;)))<BR>+&nbsp;&nbsp;*lpErrno
= WSAGetLastError();<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+/*<BR>+ *
Function: WSPStartup<BR>+ *<BR>+ * Description:<BR>+ *&nbsp;&nbsp;&nbsp; This
function initializes the base provider. <BR>+ */<BR>+#ifdef
__cplusplus<BR>+extern "C"
{<BR>+#endif<BR>+<BR>+__declspec(dllexport)<BR>+__checkReturn<BR>+int<BR>+WSPAPI<BR>+WSPStartup(<BR>+&nbsp;&nbsp;&nbsp;
__in WORD wVersion,<BR>+&nbsp;&nbsp;&nbsp; __in LPWSPDATA
lpWSPData,<BR>+&nbsp;&nbsp;&nbsp; __in LPWSAPROTOCOL_INFOW
lpProtocolInfo,<BR>+&nbsp;&nbsp;&nbsp; __in WSPUPCALLTABLE
UpCallTable,<BR>+&nbsp;&nbsp;&nbsp; __out LPWSPPROC_TABLE
lpProcTable<BR>+&nbsp;&nbsp;&nbsp; )<BR>+{<BR>+&nbsp;static
WSPDATA&nbsp;&nbsp;&nbsp;gWSPData;<BR>+&nbsp;static
WSPPROC_TABLE&nbsp;gProcTable;<BR>+&nbsp;&nbsp;&nbsp;
int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error =
NO_ERROR,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rc;<BR>+<BR>+TRACE("Requested
version = %d.%d", LOBYTE(wVersion), HIBYTE(wVersion));<BR>+<BR>+&nbsp;/* Make
sure that the version requested is &gt;= 2.2. The low byte is the
<BR>+&nbsp;&nbsp;&nbsp; major version and the high byte is the minor version.
*/<BR>+&nbsp;if( (LOBYTE(wVersion) &lt; 2) || ((LOBYTE(wVersion) == 2)
&amp;&amp; (HIBYTE(wVersion) &lt; 2)) )<BR>+&nbsp;&nbsp;return
WSAVERNOTSUPPORTED;<BR>+<BR>+&nbsp;&nbsp;&nbsp; EnterCriticalSection(
&amp;gCriticalSection );<BR>+<BR>+&nbsp;&nbsp;&nbsp; // The first time the
startup is called, create our heap and allocate some<BR>+&nbsp;&nbsp;&nbsp;
//&nbsp;&nbsp;&nbsp; data structures for tracking the LSP
providers<BR>+&nbsp;&nbsp;&nbsp; if ( 0 == gStartupCount
)<BR>+&nbsp;&nbsp;&nbsp; {<BR>+TRACE("Called 1st time =&gt; Initializing
ProtocolInfo...");<BR>+&nbsp;&nbsp;/* Save the global WSPData
*/<BR>+&nbsp;&nbsp;gWSPData.wVersion = MAKEWORD(2,
2);<BR>+&nbsp;&nbsp;gWSPData.wHighVersion = MAKEWORD(2,
2);<BR>+&nbsp;&nbsp;wcscpy_s( gWSPData.szDescription,
2*sizeof(gWSPData.szDescription), Description );<BR>+<BR>+&nbsp;&nbsp;/* provide
Service provider's entry points in proc table */<BR>+&nbsp;&nbsp;ZeroMemory(
&amp;gProcTable, sizeof(gProcTable)
);<BR>+&nbsp;&nbsp;gProcTable.lpWSPSocket&nbsp;&nbsp;&nbsp;&nbsp;=
WSPSocket;<BR>+&nbsp;&nbsp;gProcTable.lpWSPBind&nbsp;&nbsp;&nbsp;&nbsp;=
WSPBind;<BR>+&nbsp;&nbsp;gProcTable.lpWSPListen&nbsp;&nbsp;&nbsp;&nbsp;=
WSPListen;<BR>+&nbsp;&nbsp;gProcTable.lpWSPAccept&nbsp;&nbsp;&nbsp;&nbsp;=
WSPAccept;<BR>+&nbsp;&nbsp;gProcTable.lpWSPConnect&nbsp;&nbsp;&nbsp;&nbsp;=
WSPConnect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPShutdown&nbsp;&nbsp;&nbsp;=
WSPShutdown;<BR>+&nbsp;&nbsp;gProcTable.lpWSPCloseSocket&nbsp;&nbsp;&nbsp;=
WSPCloseSocket;<BR>+&nbsp;&nbsp;gProcTable.lpWSPRecv&nbsp;&nbsp;&nbsp;&nbsp;=
WSPRecv;<BR>+&nbsp;&nbsp;gProcTable.lpWSPSend&nbsp;&nbsp;&nbsp;&nbsp;=
WSPSend;<BR>+&nbsp;&nbsp;gProcTable.lpWSPGetSockOpt&nbsp;&nbsp;&nbsp;=
WSPGetSockOpt;<BR>+&nbsp;&nbsp;gProcTable.lpWSPSetSockOpt&nbsp;&nbsp;&nbsp;=
WSPSetSockOpt;<BR>+&nbsp;&nbsp;gProcTable.lpWSPSelect&nbsp;&nbsp;&nbsp;&nbsp;=
WSPSelect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPIoctl&nbsp;&nbsp;&nbsp;&nbsp;=
WSPIoctl;<BR>+&nbsp;&nbsp;gProcTable.lpWSPCleanup&nbsp;&nbsp;&nbsp;&nbsp;=
WSPCleanup;<BR>+// Additional functions required for (base provider's)
WSPStartup:<BR>+&nbsp;&nbsp;gProcTable.lpWSPAddressToString&nbsp;&nbsp;=
WSPAddressToString;<BR>+&nbsp;&nbsp;gProcTable.lpWSPAsyncSelect&nbsp;&nbsp;&nbsp;=
WSPAsyncSelect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPCancelBlockingCall&nbsp;=
WSPCancelBlockingCall;<BR>+&nbsp;&nbsp;gProcTable.lpWSPDuplicateSocket&nbsp;&nbsp;=
WSPDuplicateSocket;<BR>+&nbsp;&nbsp;gProcTable.lpWSPEnumNetworkEvents&nbsp;=
WSPEnumNetworkEvents;<BR>+&nbsp;&nbsp;gProcTable.lpWSPEventSelect&nbsp;&nbsp;&nbsp;=
WSPEventSelect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPGetOverlappedResult&nbsp;=
WSPGetOverlappedResult;<BR>+&nbsp;&nbsp;gProcTable.lpWSPGetPeerName&nbsp;&nbsp;&nbsp;=
WSPGetPeerName;<BR>+&nbsp;&nbsp;gProcTable.lpWSPGetSockName&nbsp;&nbsp;&nbsp;=
WSPGetSockName;<BR>+&nbsp;&nbsp;gProcTable.lpWSPGetQOSByName&nbsp;&nbsp;=
WSPGetQOSByName;<BR>+&nbsp;&nbsp;gProcTable.lpWSPJoinLeaf&nbsp;&nbsp;&nbsp;=
WSPJoinLeaf;<BR>+&nbsp;&nbsp;gProcTable.lpWSPRecvDisconnect&nbsp;&nbsp;=
WSPRecvDisconnect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPRecvFrom&nbsp;&nbsp;&nbsp;=
WSPRecvFrom;<BR>+&nbsp;&nbsp;gProcTable.lpWSPSendDisconnect&nbsp;&nbsp;=
WSPSendDisconnect;<BR>+&nbsp;&nbsp;gProcTable.lpWSPSendTo&nbsp;&nbsp;&nbsp;&nbsp;=
WSPSendTo;<BR>+&nbsp;&nbsp;gProcTable.lpWSPStringToAddress&nbsp;&nbsp;=
(LPWSPSTRINGTOADDRESS)WSPStringToAddress;<BR>+&nbsp;<BR>+&nbsp;&nbsp;gProtocolInfo
= *lpProtocolInfo;<BR>+&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;
gStartupCount++;<BR>+TRACE("StartupCount incremented to %d",
gStartupCount);<BR>+<BR>+&nbsp;&nbsp;&nbsp; LeaveCriticalSection(
&amp;gCriticalSection );<BR>+<BR>+&nbsp;/* Set the return parameters
*/<BR>+&nbsp;*lpWSPData&nbsp;&nbsp; = gWSPData;<BR>+&nbsp;*lpProcTable =
gProcTable;<BR>+&nbsp;<BR>+&nbsp;/* store the upcall function table
*/<BR>+&nbsp;&nbsp;&nbsp; gMainUpCallTable =
UpCallTable;<BR>+<BR>+&nbsp;&nbsp;&nbsp; return Error;<BR>+}<BR>+<BR>+#ifdef
__cplusplus<BR>+}<BR>+#endif<BR>+<BR>&nbsp;BOOL WINAPI DllMain(HINSTANCE
hInstance, DWORD dwReason, LPVOID
lpReserved)<BR>&nbsp;{<BR>&nbsp;&nbsp;UNREFERENCED_PARAMETER(hInstance);<BR>@@
-44,10 +1195,28 @@<BR>&nbsp;&nbsp;&nbsp;if (heap == NULL)
{<BR>&nbsp;&nbsp;&nbsp;&nbsp;return
FALSE;<BR>&nbsp;&nbsp;&nbsp;}<BR>-&nbsp;&nbsp;InitializeCriticalSection(&amp;lock);<BR>+&nbsp;&nbsp;fastlock_init(&amp;lock);<BR>+&nbsp;&nbsp;fastlock_init(&amp;mut);<BR>+&nbsp;&nbsp;fastlock_init(&amp;TraceLock);<BR>+<BR>+&nbsp;&nbsp;//<BR>+&nbsp;&nbsp;//
Initialize some critical section objects
<BR>+&nbsp;&nbsp;//<BR>+&nbsp;&nbsp;__try<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;InitializeCriticalSection(
&amp;gCriticalSection );<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;__except(
EXCEPTION_EXECUTE_HANDLER )<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;goto
cleanup;<BR>+&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;case
DLL_PROCESS_DETACH:<BR>-&nbsp;&nbsp;DeleteCriticalSection(&amp;lock);<BR>+&nbsp;&nbsp;gDetached
= TRUE;<BR>+&nbsp;&nbsp;DeleteCriticalSection( &amp;gCriticalSection
);<BR>+&nbsp;&nbsp;fastlock_destroy(&amp;mut);<BR>+&nbsp;&nbsp;fastlock_destroy(&amp;lock);<BR>+&nbsp;&nbsp;fastlock_destroy(&amp;TraceLock);<BR>&nbsp;&nbsp;&nbsp;HeapDestroy(heap);<BR>&nbsp;&nbsp;&nbsp;break;<BR>&nbsp;&nbsp;default:<BR>@@
-55,4 +1224,8 @@<BR>&nbsp;&nbsp;}<BR>&nbsp;<BR>&nbsp;&nbsp;return
TRUE;<BR>+<BR>+cleanup:<BR>+<BR>+&nbsp;&nbsp;&nbsp; return
FALSE;<BR>&nbsp;}<BR>Index:
ulp/librdmacm/src/indexer.cpp<BR>===================================================================<BR>---
ulp/librdmacm/src/indexer.cpp&nbsp;(revision 0)<BR>+++
ulp/librdmacm/src/indexer.cpp&nbsp;(working copy)<BR>@@ -0,0 +1,174
@@<BR>+/*<BR>+ * Copyright (c) 2011 Intel Corporation.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+#if HAVE_CONFIG_H<BR>+#&nbsp; include
&lt;config.h&gt;<BR>+#endif /* HAVE_CONFIG_H */<BR>+<BR>+#include
&lt;windows.h&gt;<BR>+<BR>+#include &lt;sys/types.h&gt;<BR>+#include
&lt;stdlib.h&gt;<BR>+<BR>+#include "indexer.h"<BR>+#include
"cma.h"<BR>+<BR>+/*<BR>+ * Indexer - to find a structure given an index<BR>+
*<BR>+ * We store pointers using a double lookup and return an index to the<BR>+
* user which is then used to retrieve the pointer.&nbsp; The upper bits of<BR>+
* the index are itself an index into an array of memory allocations.<BR>+ * The
lower bits specify the offset into the allocated memory where<BR>+ * the pointer
is stored.<BR>+ *<BR>+ * This allows us to adjust the number of pointers stored
by the index<BR>+ * list without taking a lock during data lookups.<BR>+
*/<BR>+<BR>+static int idx_grow(struct indexer *idx)<BR>+{<BR>+&nbsp;union
idx_entry *entry;<BR>+&nbsp;int i, start_index;<BR>+<BR>+&nbsp;if (idx-&gt;size
&gt;= IDX_ARRAY_SIZE)<BR>+&nbsp;&nbsp;goto
nomem;<BR>+<BR>+&nbsp;idx-&gt;array[idx-&gt;size] = (union idx_entry
*)calloc(IDX_ENTRY_SIZE, sizeof(union idx_entry));<BR>+&nbsp;if
(!idx-&gt;array[idx-&gt;size])<BR>+&nbsp;&nbsp;goto nomem;<BR>+<BR>+&nbsp;entry
= idx-&gt;array[idx-&gt;size];<BR>+&nbsp;start_index = idx-&gt;size &lt;&lt;
IDX_ENTRY_BITS;<BR>+&nbsp;entry[IDX_ENTRY_SIZE - 1].next =
idx-&gt;free_list;<BR>+<BR>+&nbsp;for (i = IDX_ENTRY_SIZE - 2; i &gt;= 0;
i--)<BR>+&nbsp;&nbsp;entry[i].next = start_index + i + 1;<BR>+<BR>+&nbsp;/*
Index 0 is reserved */<BR>+&nbsp;if (start_index ==
0)<BR>+&nbsp;&nbsp;start_index++;<BR>+&nbsp;idx-&gt;free_list =
start_index;<BR>+&nbsp;idx-&gt;size++;<BR>+&nbsp;return
start_index;<BR>+<BR>+nomem:<BR>+&nbsp;errno = ENOMEM;<BR>+&nbsp;return
-1;<BR>+}<BR>+<BR>+int idx_insert(struct indexer *idx, void
*item)<BR>+{<BR>+&nbsp;union idx_entry *entry;<BR>+&nbsp;int
index;<BR>+<BR>+&nbsp;if ((index = idx-&gt;free_list) == 0) {<BR>+&nbsp;&nbsp;if
((index = idx_grow(idx)) &lt;= 0)<BR>+&nbsp;&nbsp;&nbsp;return
index;<BR>+&nbsp;}<BR>+<BR>+&nbsp;entry =
idx-&gt;array[idx_array_index(index)];<BR>+&nbsp;idx-&gt;free_list =
entry[idx_entry_index(index)].next;<BR>+&nbsp;entry[idx_entry_index(index)].item
= item;<BR>+&nbsp;return index;<BR>+}<BR>+<BR>+void *idx_remove(struct indexer
*idx, int index)<BR>+{<BR>+&nbsp;union idx_entry *entry;<BR>+&nbsp;void
*item;<BR>+<BR>+&nbsp;entry =
idx-&gt;array[idx_array_index(index)];<BR>+&nbsp;item =
entry[idx_entry_index(index)].item;<BR>+&nbsp;entry[idx_entry_index(index)].next
= idx-&gt;free_list;<BR>+&nbsp;idx-&gt;free_list = index;<BR>+&nbsp;return
item;<BR>+}<BR>+<BR>+void idx_replace(struct indexer *idx, int index, void
*item)<BR>+{<BR>+&nbsp;union idx_entry *entry;<BR>+<BR>+&nbsp;entry =
idx-&gt;array[idx_array_index(index)];<BR>+&nbsp;entry[idx_entry_index(index)].item
= item;<BR>+}<BR>+<BR>+<BR>+static int idm_grow(struct index_map *idm, int
index)<BR>+{<BR>+&nbsp;idm-&gt;array[idx_array_index(index)] = (void
**)calloc(IDX_ENTRY_SIZE, sizeof(void *));<BR>+&nbsp;if
(!idm-&gt;array[idx_array_index(index)])<BR>+&nbsp;&nbsp;goto
nomem;<BR>+<BR>+&nbsp;return index;<BR>+<BR>+nomem:<BR>+&nbsp;errno =
ENOMEM;<BR>+&nbsp;return -1;<BR>+}<BR>+<BR>+int idm_set(struct index_map *idm,
int index, void *item)<BR>+{<BR>+&nbsp;void **entry;<BR>+<BR>+&nbsp;if (index
&gt; IDX_MAX_INDEX) {<BR>+&nbsp;&nbsp;errno = ENOMEM;<BR>+&nbsp;&nbsp;return
-1;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (!idm-&gt;array[idx_array_index(index)])
{<BR>+&nbsp;&nbsp;if (idm_grow(idm, index) &lt; 0)<BR>+&nbsp;&nbsp;&nbsp;return
-1;<BR>+&nbsp;}<BR>+<BR>+&nbsp;entry =
idm-&gt;array[idx_array_index(index)];<BR>+&nbsp;entry[idx_entry_index(index)] =
item;<BR>+&nbsp;return index;<BR>+}<BR>+<BR>+void *idm_clear(struct index_map
*idm, int index)<BR>+{<BR>+&nbsp;void **entry;<BR>+&nbsp;void
*item;<BR>+<BR>+&nbsp;entry =
idm-&gt;array[idx_array_index(index)];<BR>+&nbsp;item =
entry[idx_entry_index(index)];<BR>+&nbsp;entry[idx_entry_index(index)] =
NULL;<BR>+&nbsp;return item;<BR>+}<BR>Index:
ulp/librdmacm/src/indexer.h<BR>===================================================================<BR>---
ulp/librdmacm/src/indexer.h&nbsp;(revision 0)<BR>+++
ulp/librdmacm/src/indexer.h&nbsp;(working copy)<BR>@@ -0,0 +1,101 @@<BR>+/*<BR>+
* Copyright (c) 2011 Intel Corporation.&nbsp; All rights reserved.<BR>+ *<BR>+ *
This software is available to you under a choice of one of two<BR>+ *
licenses.&nbsp; You may choose to be licensed under the terms of the GNU<BR>+ *
General Public License (GPL) Version 2, available from the file<BR>+ * COPYING
in the main directory of this source tree, or the<BR>+ * OpenIB.org BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,<BR>+ *
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<BR>+ *
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND<BR>+ * NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS<BR>+ * BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN<BR>+ * ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN<BR>+ * CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE<BR>+ * SOFTWARE.<BR>+ *<BR>+ */<BR>+<BR>+#if
HAVE_CONFIG_H<BR>+#&nbsp; include &lt;config.h&gt;<BR>+#endif /* HAVE_CONFIG_H
*/<BR>+<BR>+#include &lt;sys/types.h&gt;<BR>+<BR>+/*<BR>+ * Indexer - to find a
structure given an index.&nbsp; Synchronization<BR>+ * must be provided by the
caller.&nbsp; Caller must initialize the<BR>+ * indexer by setting free_list and
size to 0.<BR>+ */<BR>+<BR>+union idx_entry {<BR>+&nbsp;void
*item;<BR>+&nbsp;int&nbsp;&nbsp; next;<BR>+};<BR>+<BR>+#define IDX_INDEX_BITS
16<BR>+#define IDX_ENTRY_BITS 10<BR>+#define IDX_ENTRY_SIZE (1 &lt;&lt;
IDX_ENTRY_BITS)<BR>+#define IDX_ARRAY_SIZE (1 &lt;&lt; (IDX_INDEX_BITS -
IDX_ENTRY_BITS))<BR>+#define IDX_MAX_INDEX&nbsp; ((1 &lt;&lt; IDX_INDEX_BITS) -
1)<BR>+<BR>+struct indexer<BR>+{<BR>+&nbsp;union idx_entry
*array[IDX_ARRAY_SIZE];<BR>+&nbsp;int&nbsp;&nbsp;
free_list;<BR>+&nbsp;int&nbsp;&nbsp; size;<BR>+};<BR>+<BR>+#define
idx_array_index(index) (index &gt;&gt; IDX_ENTRY_BITS)<BR>+#define
idx_entry_index(index) (index &amp; (IDX_ENTRY_SIZE - 1))<BR>+<BR>+int
idx_insert(struct indexer *idx, void *item);<BR>+void *idx_remove(struct indexer
*idx, int index);<BR>+void idx_replace(struct indexer *idx, int index, void
*item);<BR>+<BR>+static inline void *idx_at(struct indexer *idx, int
index)<BR>+{<BR>+&nbsp;return (idx-&gt;array[idx_array_index(index)] +
idx_entry_index(index))-&gt;item;<BR>+}<BR>+<BR>+/*<BR>+ * Index map -
associates a structure with an index.&nbsp; Synchronization<BR>+ * must be
provided by the caller.&nbsp; Caller must initialize the<BR>+ * index map by
setting it to 0.<BR>+ */<BR>+<BR>+struct index_map<BR>+{<BR>+&nbsp;void
**array[IDX_ARRAY_SIZE];<BR>+};<BR>+<BR>+int idm_set(struct index_map *idm, int
index, void *item);<BR>+void *idm_clear(struct index_map *idm, int
index);<BR>+<BR>+static inline void *idm_at(struct index_map *idm, int
index)<BR>+{<BR>+&nbsp;void **entry;<BR>+&nbsp;entry =
idm-&gt;array[idx_array_index(index)];<BR>+&nbsp;return
entry[idx_entry_index(index)];<BR>+}<BR>+<BR>+static inline void
*idm_lookup(struct index_map *idm, int index)<BR>+{<BR>+&nbsp;return ((index
&lt;= IDX_MAX_INDEX) &amp;&amp; idm-&gt;array[idx_array_index(index)])
?<BR>+&nbsp;&nbsp;idm_at(idm, index) : NULL;<BR>+}<BR>Index:
ulp/librdmacm/src/openib_osd.h<BR>===================================================================<BR>---
ulp/librdmacm/src/openib_osd.h&nbsp;(revision 0)<BR>+++
ulp/librdmacm/src/openib_osd.h&nbsp;(working copy)<BR>@@ -0,0 +1,47
@@<BR>+#ifndef OPENIB_OSD_H<BR>+#define OPENIB_OSD_H<BR>+<BR>+#if
defined(FD_SETSIZE) &amp;&amp; FD_SETSIZE != 1024<BR>+#undef
FD_SETSIZE<BR>+#endif<BR>+#define FD_SETSIZE 1024 /* Set before including
winsock2 - see select help */<BR>+<BR>+#include &lt;winsock2.h&gt;<BR>+#include
&lt;ws2tcpip.h&gt;<BR>+#include &lt;io.h&gt;<BR>+#include
&lt;fcntl.h&gt;<BR>+<BR>+#define container_of&nbsp;CONTAINING_RECORD<BR>+#define
offsetof&nbsp;&nbsp;FIELD_OFFSET<BR>+#define
ssize_t&nbsp;&nbsp;&nbsp;SSIZE_T<BR>+<BR>+#define
__thread&nbsp;&nbsp;/*???*/<BR>+<BR>+#define
ntohll&nbsp;&nbsp;&nbsp;_byteswap_uint64<BR>+#define
htonll&nbsp;&nbsp;&nbsp;_byteswap_uint64<BR>+<BR>+#define
SHUT_RD&nbsp;&nbsp;&nbsp;&nbsp;SD_RECEIVE<BR>+#define
SHUT_WR&nbsp;&nbsp;&nbsp;&nbsp;SD_SEND<BR>+#define
SHUT_RDWR&nbsp;&nbsp;&nbsp;SD_BOTH<BR>+<BR>+#define
O_NONBLOCK&nbsp;&nbsp;0x4000<BR>+<BR>+/* allow casting to WSABUF */<BR>+struct
iovec<BR>+{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; u_long
iov_len;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char FAR*
iov_base;<BR>+};<BR>+<BR>+struct
msghdr<BR>+{<BR>+&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
*msg_name;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // optional
address<BR>+&nbsp;socklen_t&nbsp;&nbsp;&nbsp;&nbsp;
msg_namelen;&nbsp;&nbsp;&nbsp; // size of address<BR>+&nbsp;struct iovec
*msg_iov;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // scatter/gather
array<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
msg_iovlen;&nbsp;&nbsp;&nbsp;&nbsp; // members in
msg_iov<BR>+&nbsp;void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
*msg_control;&nbsp;&nbsp;&nbsp; // ancillary data, see
below<BR>+&nbsp;socklen_t&nbsp;&nbsp;&nbsp;&nbsp; msg_controllen; // ancillary
data buffer
len<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
msg_flags;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // flags on received
message<BR>+};<BR>+<BR>+#endif // OPENIB_OSD_H<BR>Index:
ulp/librdmacm/src/rsocket.cpp<BR>===================================================================<BR>---
ulp/librdmacm/src/rsocket.cpp&nbsp;(revision 0)<BR>+++
ulp/librdmacm/src/rsocket.cpp&nbsp;(working copy)<BR>@@ -0,0 +1,2334
@@<BR>+/*<BR>+ * Copyright (c) 2008-2012 Intel Corporation.&nbsp; All rights
reserved.<BR>+ * Copyright (c) 2012 Oce Printing Systems GmbH.&nbsp; All rights
reserved.<BR>+ *<BR>+ * This software is available to you under the BSD license
below:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; Redistribution and use in source
and binary forms, with or<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp; without modification,
are permitted provided that the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;
conditions are met:<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -
Redistributions of source code must retain the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer.<BR>+ *<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Redistributions in
binary form must reproduce the above<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copyright notice, this list of
conditions and the following<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
disclaimer in the documentation and/or other materials<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; provided with the distribution.<BR>+
*<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Neither the name Oce Printing Systems
GmbH nor the names<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of the
authors may be used to endorse or promote products<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; derived from this software without
specific prior written<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
permission.<BR>+ *<BR>+ * THIS SOFTWARE IS PROVIDED&nbsp; “AS IS” AND ANY
EXPRESS OR IMPLIED<BR>+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
WARRANTIES OF<BR>+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
AND<BR>+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS<BR>+ *
OR CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT,<BR>+ * INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<BR>+ * DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF<BR>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS;<BR>+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF<BR>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT<BR>+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF<BR>+ * THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY<BR>+ * OF SUCH DAMAGE.
<BR>+ */<BR>+<BR>+#if HAVE_CONFIG_H<BR>+#&nbsp; include
&lt;config.h&gt;<BR>+#endif /* HAVE_CONFIG_H */<BR>+<BR>+#include
&lt;sys/types.h&gt;<BR>+<BR>+#include &lt;windows.h&gt;<BR>+#include
"openib_osd.h"<BR>+#include &lt;sys/time.h&gt;<BR>+#include
&lt;stdarg.h&gt;<BR>+#include &lt;netdb.h&gt;<BR>+#include
&lt;unistd.h&gt;<BR>+#include &lt;_fcntl.h&gt;<BR>+#include
&lt;stdio.h&gt;<BR>+#include &lt;string.h&gt;<BR>+#include
&lt;_errno.h&gt;<BR>+#include &lt;complib/cl_byteswap.h&gt;<BR>+#include
&lt;rdma/rdma_cma.h&gt;<BR>+#include &lt;rdma/rdma_verbs.h&gt;<BR>+#include
&lt;rdma/rwinsock.h&gt;<BR>+#include &lt;rdma/rsocket.h&gt;<BR>+#include
"cma.h"<BR>+#include "indexer.h"<BR>+#include "../../../etc/user/gtod.c" //
getimeofday()<BR>+<BR>+#define RS_OLAP_START_SIZE 2048<BR>+#define
RS_MAX_TRANSFER 65536<BR>+#define RS_MAX_BACKLOG&nbsp; 256<BR>+#define
RS_QP_MAX_SIZE 0xFFFE<BR>+#define RS_QP_CTRL_SIZE 4<BR>+#define RS_CONN_RETRIES
6<BR>+#define RS_SGL_SIZE 2<BR>+<BR>+static struct index_map idm;<BR>+static
uint16_t def_inline = 64;<BR>+static uint16_t def_sqsize = 384;<BR>+static
uint16_t def_rqsize = 384;<BR>+static uint32_t def_mem = (1 &lt;&lt;
17);<BR>+static uint32_t def_wmem = (1 &lt;&lt; 17);<BR>+static uint32_t
polling_time = 10;<BR>+<BR>+extern fastlock_t&nbsp;&nbsp;mut;<BR>+extern
BOOL&nbsp;&nbsp;&nbsp;&nbsp;gDetached;&nbsp;&nbsp;&nbsp;// Indicates if process
is detaching from DLL<BR>+extern CRITICAL_SECTION gCriticalSection;&nbsp;&nbsp;
// Critical section for initialization and <BR>+extern
WSPUPCALLTABLE&nbsp;&nbsp; gMainUpCallTable;&nbsp;&nbsp; // Upcall functions
given to us by Winsock<BR>+extern WSAPROTOCOL_INFOW
gProtocolInfo;<BR>+<BR>+/*<BR>+ * Immediate data format is determined by the
upper bits<BR>+ * bit 31: message type, 0 - data, 1 - control<BR>+ * bit 30:
buffers updated, 0 - target, 1 - direct-receive<BR>+ * bit 29: more data, 0 -
end of transfer, 1 - more data available<BR>+ *<BR>+ * for data transfers:<BR>+
* bits [28:0]: bytes transfered, 0 = 1 GB<BR>+ * for control messages:<BR>+ *
bits [28-0]: receive credits granted<BR>+ */<BR>+<BR>+enum
{<BR>+&nbsp;RS_OP_DATA,<BR>+&nbsp;RS_OP_RSVD_DATA_MORE,<BR>+&nbsp;RS_OP_RSVD_DRA,<BR>+&nbsp;RS_OP_RSVD_DRA_MORE,<BR>+&nbsp;RS_OP_SGL,<BR>+&nbsp;RS_OP_RSVD,<BR>+&nbsp;RS_OP_RSVD_DRA_SGL,<BR>+&nbsp;RS_OP_CTRL<BR>+};<BR>+#define
rs_msg_set(op, data)&nbsp; ((op &lt;&lt; 29) | (uint32_t) (data))<BR>+#define
rs_msg_op(imm_data)&nbsp;&nbsp; (imm_data &gt;&gt; 29)<BR>+#define
rs_msg_data(imm_data) (imm_data &amp; 0x1FFFFFFF)<BR>+<BR>+enum
{<BR>+&nbsp;RS_CTRL_DISCONNECT,<BR>+&nbsp;RS_CTRL_SHUTDOWN<BR>+};<BR>+<BR>+struct
rs_msg {<BR>+&nbsp;uint32_t op;<BR>+&nbsp;uint32_t data;<BR>+};<BR>+<BR>+struct
rs_sge {<BR>+&nbsp;uint64_t addr;<BR>+&nbsp;uint32_t key;<BR>+&nbsp;uint32_t
length;<BR>+};<BR>+<BR>+#define RS_MIN_INLINE&nbsp;&nbsp;&nbsp; (sizeof(struct
rs_sge))<BR>+#define rs_host_is_net() (1 == htonl(1))<BR>+#define
RS_CONN_FLAG_NET 1<BR>+<BR>+struct rs_conn_data
{<BR>+&nbsp;uint8_t&nbsp;&nbsp;&nbsp;
version;<BR>+&nbsp;uint8_t&nbsp;&nbsp;&nbsp;
flags;<BR>+&nbsp;uint16_t&nbsp;&nbsp; credits;<BR>+&nbsp;uint32_t&nbsp;&nbsp;
reserved2;<BR>+&nbsp;struct rs_sge&nbsp;&nbsp; target_sgl;<BR>+&nbsp;struct
rs_sge&nbsp;&nbsp; data_buf;<BR>+};<BR>+<BR>+#define RS_RECV_WR_ID (~((uint64_t)
0))<BR>+<BR>+/*<BR>+ * rsocket states are ordered as passive, connecting,
connected, disconnected.<BR>+ */<BR>+enum rs_state
{<BR>+&nbsp;rs_init,<BR>+&nbsp;rs_bound&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0001,<BR>+&nbsp;rs_listening&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0002,<BR>+&nbsp;rs_opening&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0004,<BR>+&nbsp;rs_resolving_addr&nbsp; =
rs_opening |&nbsp;&nbsp; 0x0010,<BR>+&nbsp;rs_resolving_route = rs_opening
|&nbsp;&nbsp; 0x0020,<BR>+&nbsp;rs_connecting&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =
rs_opening |&nbsp;&nbsp;
0x0040,<BR>+&nbsp;rs_accepting&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = rs_opening
|&nbsp;&nbsp; 0x0080,<BR>+&nbsp;rs_connected&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x0100,<BR>+&nbsp;rs_connect_wr
&nbsp;&nbsp;&nbsp; =&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0x0200,<BR>+&nbsp;rs_connect_rd&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0x0400,<BR>+&nbsp;rs_connect_rdwr&nbsp;&nbsp;&nbsp; = rs_connected |
rs_connect_rd | rs_connect_wr,<BR>+&nbsp;rs_connect_error&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
0x0800,<BR>+&nbsp;rs_disconnected&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x1000,<BR>+&nbsp;rs_error&nbsp;&nbsp;&nbsp;
=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0x2000,<BR>+};<BR>+<BR>+#define RS_OPT_SWAP_SGL
1<BR>+<BR>+struct rsocket {<BR>+&nbsp;struct rdma_cm_id
*cm_id;<BR>+&nbsp;fastlock_t&nbsp;&nbsp; slock;<BR>+&nbsp;fastlock_t&nbsp;&nbsp;
rlock;<BR>+&nbsp;fastlock_t&nbsp;&nbsp;
cq_lock;<BR>+&nbsp;fastlock_t&nbsp;&nbsp;
cq_wait_lock;<BR>+<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
opts;<BR>+&nbsp;long&nbsp;&nbsp;&nbsp; fd_flags;<BR>+&nbsp;uint64_t&nbsp;&nbsp;
so_opts;<BR>+&nbsp;uint64_t&nbsp;&nbsp; tcp_opts;<BR>+&nbsp;uint64_t&nbsp;&nbsp;
ipv6_opts;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
state;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp; cq_armed;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
retries;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp; err;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
index;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
ctrl_avail;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
sqe_avail;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
sbuf_bytes_avail;<BR>+&nbsp;uint16_t&nbsp;&nbsp;
sseq_no;<BR>+&nbsp;uint16_t&nbsp;&nbsp;
sseq_comp;<BR>+&nbsp;uint16_t&nbsp;&nbsp;
sq_size;<BR>+&nbsp;uint16_t&nbsp;&nbsp;
sq_inline;<BR>+<BR>+&nbsp;uint16_t&nbsp;&nbsp;
rq_size;<BR>+&nbsp;uint16_t&nbsp;&nbsp; rseq_no;<BR>+&nbsp;uint16_t&nbsp;&nbsp;
rseq_comp;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
rbuf_bytes_avail;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
rbuf_free_offset;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
rbuf_offset;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
rmsg_head;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp; rmsg_tail;<BR>+&nbsp;struct
rs_msg&nbsp;&nbsp; *rmsg;<BR>+<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;
remote_sge;<BR>+&nbsp;struct rs_sge&nbsp;&nbsp;
remote_sgl;<BR>+<BR>+&nbsp;struct ibv_mr&nbsp;
*target_mr;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp; target_sge;<BR>+&nbsp;volatile
struct rs_sge&nbsp;&nbsp;
target_sgl[RS_SGL_SIZE];<BR>+<BR>+&nbsp;uint32_t&nbsp;&nbsp;
rbuf_size;<BR>+&nbsp;struct ibv_mr&nbsp;
*rmr;<BR>+&nbsp;uint8_t&nbsp;&nbsp;&nbsp;
*rbuf;<BR>+<BR>+&nbsp;uint32_t&nbsp;&nbsp; sbuf_size;<BR>+&nbsp;struct
ibv_mr&nbsp; *smr;<BR>+&nbsp;struct ibv_sge&nbsp;&nbsp;
ssgl[2];<BR>+&nbsp;uint8_t&nbsp;&nbsp;&nbsp; *sbuf;<BR>+};<BR>+<BR>+static void
rs_configure(void)<BR>+{<BR>+&nbsp;FILE *f;<BR>+&nbsp;static int
init;<BR>+<BR>+&nbsp;if
(init)<BR>+&nbsp;&nbsp;return;<BR>+<BR>+&nbsp;fastlock_acquire(&amp;mut);<BR>+&nbsp;if
(init)<BR>+&nbsp;&nbsp;goto out;<BR>+<BR>+&nbsp;if ((f = fopen(RS_CONF_DIR
"/polling_time", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%u",
&amp;polling_time);<BR>+&nbsp;&nbsp;fclose(f);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if ((f
= fopen(RS_CONF_DIR "/inline_default", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%hu",
&amp;def_inline);<BR>+&nbsp;&nbsp;fclose(f);<BR>+<BR>+&nbsp;&nbsp;if (def_inline
&lt; RS_MIN_INLINE)<BR>+&nbsp;&nbsp;&nbsp;def_inline =
RS_MIN_INLINE;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if ((f = fopen(RS_CONF_DIR
"/sqsize_default", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%hu",
&amp;def_sqsize);<BR>+&nbsp;&nbsp;fclose(f);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if ((f =
fopen(RS_CONF_DIR "/rqsize_default", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%hu",
&amp;def_rqsize);<BR>+&nbsp;&nbsp;fclose(f);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if ((f =
fopen(RS_CONF_DIR "/mem_default", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%u",
&amp;def_mem);<BR>+&nbsp;&nbsp;fclose(f);<BR>+<BR>+&nbsp;&nbsp;if (def_mem &lt;
1)<BR>+&nbsp;&nbsp;&nbsp;def_mem = 1;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if ((f =
fopen(RS_CONF_DIR "/wmem_default", "r"))) {<BR>+&nbsp;&nbsp;fscanf(f, "%u",
&amp;def_wmem);<BR>+&nbsp;&nbsp;fclose(f);<BR>+<BR>+&nbsp;&nbsp;if (def_wmem
&lt; 1)<BR>+&nbsp;&nbsp;&nbsp;def_wmem = 1;<BR>+&nbsp;}<BR>+&nbsp;init =
1;<BR>+out:<BR>+&nbsp;fastlock_release(&amp;mut);<BR>+}<BR>+<BR>+static int
rs_insert(struct rsocket
*rs)<BR>+{<BR>+&nbsp;fastlock_acquire(&amp;mut);<BR>+&nbsp;rs-&gt;index =
idm_set(&amp;idm, ((int)rs-&gt;cm_id-&gt;channel-&gt;channel.Event &gt;&gt;
2)/*fd*/, rs);<BR>+&nbsp;fastlock_release(&amp;mut);<BR>+&nbsp;return
rs-&gt;index;<BR>+}<BR>+<BR>+static void rs_remove(struct rsocket
*rs)<BR>+{<BR>+&nbsp;fastlock_acquire(&amp;mut);<BR>+&nbsp;idm_clear(&amp;idm,
rs-&gt;index);<BR>+&nbsp;fastlock_release(&amp;mut);<BR>+}<BR>+<BR>+static
struct rsocket *rs_alloc(struct rsocket *inherited_rs)<BR>+{<BR>+&nbsp;struct
rsocket *rs;<BR>+<BR>+&nbsp;rs = (struct rsocket *)calloc(1, sizeof
*rs);<BR>+&nbsp;if (!rs)<BR>+&nbsp;&nbsp;return
NULL;<BR>+<BR>+&nbsp;rs-&gt;index = -1;<BR>+&nbsp;if (inherited_rs)
{<BR>+&nbsp;&nbsp;rs-&gt;sbuf_size =
inherited_rs-&gt;sbuf_size;<BR>+&nbsp;&nbsp;rs-&gt;rbuf_size =
inherited_rs-&gt;rbuf_size;<BR>+&nbsp;&nbsp;rs-&gt;sq_inline =
inherited_rs-&gt;sq_inline;<BR>+&nbsp;&nbsp;rs-&gt;sq_size =
inherited_rs-&gt;sq_size;<BR>+&nbsp;&nbsp;rs-&gt;rq_size =
inherited_rs-&gt;rq_size;<BR>+&nbsp;&nbsp;rs-&gt;ctrl_avail =
inherited_rs-&gt;ctrl_avail;<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;rs-&gt;sbuf_size
= def_wmem;<BR>+&nbsp;&nbsp;rs-&gt;rbuf_size =
def_mem;<BR>+&nbsp;&nbsp;rs-&gt;sq_inline =
def_inline;<BR>+&nbsp;&nbsp;rs-&gt;sq_size =
def_sqsize;<BR>+&nbsp;&nbsp;rs-&gt;rq_size =
def_rqsize;<BR>+&nbsp;&nbsp;rs-&gt;ctrl_avail =
RS_QP_CTRL_SIZE;<BR>+&nbsp;}<BR>+&nbsp;fastlock_init(&amp;rs-&gt;slock);<BR>+&nbsp;fastlock_init(&amp;rs-&gt;rlock);<BR>+&nbsp;fastlock_init(&amp;rs-&gt;cq_lock);<BR>+&nbsp;fastlock_init(&amp;rs-&gt;cq_wait_lock);<BR>+&nbsp;return
rs;<BR>+}<BR>+<BR>+static int rs_set_nonblocking(struct rsocket *rs, long
arg)<BR>+{<BR>+&nbsp;if
(rs-&gt;cm_id-&gt;recv_cq_channel)<BR>+&nbsp;&nbsp;rs-&gt;cm_id-&gt;recv_cq_channel-&gt;comp_channel.Milliseconds
= (arg == O_NONBLOCK ? 0 : INFINITE);<BR>+<BR>+&nbsp;if (rs-&gt;state &lt;
rs_connected)<BR>+&nbsp;&nbsp;rs-&gt;cm_id-&gt;channel-&gt;channel.Milliseconds
= (arg == O_NONBLOCK ? 0 : INFINITE);<BR>+<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+static void rs_set_qp_size(struct rsocket
*rs)<BR>+{<BR>+&nbsp;uint16_t max_size;<BR>+<BR>+&nbsp;max_size =
min(ucma_max_qpsize(rs-&gt;cm_id), RS_QP_MAX_SIZE);<BR>+<BR>+&nbsp;if
(rs-&gt;sq_size &gt; max_size)<BR>+&nbsp;&nbsp;rs-&gt;sq_size =
max_size;<BR>+&nbsp;else if (rs-&gt;sq_size &lt;
2)<BR>+&nbsp;&nbsp;rs-&gt;sq_size = 2;<BR>+&nbsp;if (rs-&gt;sq_size &lt;=
(RS_QP_CTRL_SIZE &lt;&lt; 2))<BR>+&nbsp;&nbsp;rs-&gt;ctrl_avail =
1;<BR>+<BR>+&nbsp;if (rs-&gt;rq_size &gt;
max_size)<BR>+&nbsp;&nbsp;rs-&gt;rq_size = max_size;<BR>+&nbsp;else if
(rs-&gt;rq_size &lt; 2)<BR>+&nbsp;&nbsp;rs-&gt;rq_size =
2;<BR>+}<BR>+<BR>+static int rs_init_bufs(struct rsocket
*rs)<BR>+{<BR>+&nbsp;rs-&gt;rmsg = (struct rs_msg *)calloc(rs-&gt;rq_size + 1,
sizeof(*rs-&gt;rmsg));<BR>+&nbsp;if (!rs-&gt;rmsg)<BR>+&nbsp;&nbsp;return
-1;<BR>+<BR>+&nbsp;rs-&gt;sbuf = (uint8_t *)calloc(rs-&gt;sbuf_size,
sizeof(*rs-&gt;sbuf));<BR>+&nbsp;if (!rs-&gt;sbuf)<BR>+&nbsp;&nbsp;return
-1;<BR>+<BR>+&nbsp;rs-&gt;smr = rdma_reg_msgs(rs-&gt;cm_id, rs-&gt;sbuf,
rs-&gt;sbuf_size);<BR>+&nbsp;if (!rs-&gt;smr)<BR>+&nbsp;&nbsp;return
-1;<BR>+<BR>+&nbsp;rs-&gt;target_mr = rdma_reg_write(rs-&gt;cm_id, (void *)
rs-&gt;target_sgl,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
sizeof(rs-&gt;target_sgl));<BR>+&nbsp;if
(!rs-&gt;target_mr)<BR>+&nbsp;&nbsp;return -1;<BR>+<BR>+&nbsp;rs-&gt;rbuf =
(uint8_t *)calloc(rs-&gt;rbuf_size, sizeof(*rs-&gt;rbuf));<BR>+&nbsp;if
(!rs-&gt;rbuf)<BR>+&nbsp;&nbsp;return -1;<BR>+<BR>+&nbsp;rs-&gt;rmr =
rdma_reg_write(rs-&gt;cm_id, rs-&gt;rbuf, rs-&gt;rbuf_size);<BR>+&nbsp;if
(!rs-&gt;rmr)<BR>+&nbsp;&nbsp;return -1;<BR>+<BR>+&nbsp;rs-&gt;ssgl[0].addr =
rs-&gt;ssgl[1].addr = (uintptr_t) rs-&gt;sbuf;<BR>+&nbsp;rs-&gt;sbuf_bytes_avail
= rs-&gt;sbuf_size;<BR>+&nbsp;rs-&gt;ssgl[0].lkey = rs-&gt;ssgl[1].lkey =
rs-&gt;smr-&gt;lkey;<BR>+<BR>+&nbsp;rs-&gt;rbuf_free_offset = rs-&gt;rbuf_size
&gt;&gt; 1;<BR>+&nbsp;rs-&gt;rbuf_bytes_avail = rs-&gt;rbuf_size &gt;&gt;
1;<BR>+&nbsp;rs-&gt;sqe_avail = rs-&gt;sq_size -
rs-&gt;ctrl_avail;<BR>+&nbsp;rs-&gt;rseq_comp = rs-&gt;rq_size &gt;&gt;
1;<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+static int rs_create_cq(struct rsocket
*rs)<BR>+{<BR>+&nbsp;rs-&gt;cm_id-&gt;recv_cq_channel =
ibv_create_comp_channel(rs-&gt;cm_id-&gt;verbs);<BR>+&nbsp;if
(!rs-&gt;cm_id-&gt;recv_cq_channel)<BR>+&nbsp;&nbsp;return
-1;<BR>+<BR>+&nbsp;rs-&gt;cm_id-&gt;recv_cq =
ibv_create_cq(rs-&gt;cm_id-&gt;verbs, rs-&gt;sq_size +
rs-&gt;rq_size,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs-&gt;cm_id,
rs-&gt;cm_id-&gt;recv_cq_channel, 0);<BR>+&nbsp;if
(!rs-&gt;cm_id-&gt;recv_cq)<BR>+&nbsp;&nbsp;goto err1;<BR>+<BR>+&nbsp;if
(rs-&gt;fd_flags &amp; O_NONBLOCK) {<BR>+&nbsp;&nbsp;if (rs_set_nonblocking(rs,
O_NONBLOCK))<BR>+&nbsp;&nbsp;&nbsp;goto
err2;<BR>+&nbsp;}<BR>+<BR>+&nbsp;rs-&gt;cm_id-&gt;send_cq_channel =
rs-&gt;cm_id-&gt;recv_cq_channel;<BR>+&nbsp;rs-&gt;cm_id-&gt;send_cq =
rs-&gt;cm_id-&gt;recv_cq;<BR>+&nbsp;return
0;<BR>+<BR>+err2:<BR>+&nbsp;ibv_destroy_cq(rs-&gt;cm_id-&gt;recv_cq);<BR>+&nbsp;rs-&gt;cm_id-&gt;recv_cq
=
NULL;<BR>+err1:<BR>+&nbsp;ibv_destroy_comp_channel(rs-&gt;cm_id-&gt;recv_cq_channel);<BR>+&nbsp;rs-&gt;cm_id-&gt;recv_cq_channel
= NULL;<BR>+&nbsp;return -1;<BR>+}<BR>+<BR>+static __inline
int<BR>+rs_post_recv(struct rsocket *rs)<BR>+{<BR>+&nbsp;struct ibv_recv_wr wr,
*bad;<BR>+<BR>+&nbsp;wr.wr_id = RS_RECV_WR_ID;<BR>+&nbsp;wr.next =
NULL;<BR>+&nbsp;wr.sg_list = NULL;<BR>+&nbsp;wr.num_sge =
0;<BR>+<BR>+&nbsp;return rdma_seterrno(ibv_post_recv(rs-&gt;cm_id-&gt;qp,
&amp;wr, &amp;bad));<BR>+}<BR>+<BR>+static int rs_create_ep(struct rsocket
*rs)<BR>+{<BR>+&nbsp;struct ibv_qp_init_attr qp_attr;<BR>+&nbsp;int i,
ret;<BR>+<BR>+&nbsp;rs_set_qp_size(rs);<BR>+<BR>+&nbsp;ret =
rs_create_cq(rs);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;memset(&amp;qp_attr, 0, sizeof
qp_attr);<BR>+&nbsp;qp_attr.qp_context = rs;<BR>+&nbsp;qp_attr.send_cq =
rs-&gt;cm_id-&gt;send_cq;<BR>+&nbsp;qp_attr.recv_cq =
rs-&gt;cm_id-&gt;recv_cq;<BR>+&nbsp;qp_attr.qp_type =
IBV_QPT_RC;<BR>+&nbsp;qp_attr.sq_sig_all = 1;<BR>+&nbsp;qp_attr.cap.max_send_wr
= rs-&gt;sq_size;<BR>+&nbsp;qp_attr.cap.max_recv_wr =
rs-&gt;rq_size;<BR>+&nbsp;qp_attr.cap.max_send_sge =
2;<BR>+&nbsp;qp_attr.cap.max_recv_sge = 1;<BR>+&nbsp;qp_attr.cap.max_inline_data
= rs-&gt;sq_inline;<BR>+<BR>+&nbsp;ret = rdma_create_qp(rs-&gt;cm_id, NULL,
&amp;qp_attr);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;return ret;<BR>+<BR>+&nbsp;ret
= rs_init_bufs(rs); <BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;return
ret;<BR>+<BR>+&nbsp;for (i = 0; i &lt; rs-&gt;rq_size; i++)
{<BR>+&nbsp;&nbsp;ret = rs_post_recv(rs);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;return ret;<BR>+&nbsp;}<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+static void rs_free(struct rsocket *rs)<BR>+{<BR>+&nbsp;if
(rs-&gt;index &gt;= 0)<BR>+&nbsp;&nbsp;rs_remove(rs);<BR>+<BR>+&nbsp;if
(rs-&gt;rmsg)<BR>+&nbsp;&nbsp;free(rs-&gt;rmsg);<BR>+<BR>+&nbsp;if (rs-&gt;sbuf)
{<BR>+&nbsp;&nbsp;if
(rs-&gt;smr)<BR>+&nbsp;&nbsp;&nbsp;rdma_dereg_mr(rs-&gt;smr);<BR>+&nbsp;&nbsp;free(rs-&gt;sbuf);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(rs-&gt;rbuf) {<BR>+&nbsp;&nbsp;if
(rs-&gt;rmr)<BR>+&nbsp;&nbsp;&nbsp;rdma_dereg_mr(rs-&gt;rmr);<BR>+&nbsp;&nbsp;free(rs-&gt;rbuf);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(rs-&gt;target_mr)<BR>+&nbsp;&nbsp;rdma_dereg_mr(rs-&gt;target_mr);<BR>+<BR>+&nbsp;if
(rs-&gt;cm_id) {<BR>+&nbsp;&nbsp;if
(rs-&gt;cm_id-&gt;qp)<BR>+&nbsp;&nbsp;&nbsp;rdma_destroy_qp(rs-&gt;cm_id);<BR>+&nbsp;&nbsp;rdma_destroy_id(rs-&gt;cm_id);<BR>+&nbsp;}<BR>+<BR>+&nbsp;fastlock_destroy(&amp;rs-&gt;cq_wait_lock);<BR>+&nbsp;fastlock_destroy(&amp;rs-&gt;cq_lock);<BR>+&nbsp;fastlock_destroy(&amp;rs-&gt;rlock);<BR>+&nbsp;fastlock_destroy(&amp;rs-&gt;slock);<BR>+&nbsp;free(rs);<BR>+}<BR>+<BR>+static
void rs_set_conn_data(struct rsocket *rs, struct rdma_conn_param
*param,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct rs_conn_data
*conn)<BR>+{<BR>+&nbsp;conn-&gt;version = 1;<BR>+&nbsp;conn-&gt;flags =
rs_host_is_net() ? RS_CONN_FLAG_NET : 0;<BR>+&nbsp;conn-&gt;credits =
htons(rs-&gt;rq_size);<BR>+&nbsp;conn-&gt;reserved2 =
0;<BR>+<BR>+&nbsp;conn-&gt;target_sgl.addr = htonll((uintptr_t)
rs-&gt;target_sgl);<BR>+&nbsp;conn-&gt;target_sgl.length =
htonl(RS_SGL_SIZE);<BR>+&nbsp;conn-&gt;target_sgl.key =
htonl(rs-&gt;target_mr-&gt;rkey);<BR>+<BR>+&nbsp;conn-&gt;data_buf.addr =
htonll((uintptr_t) rs-&gt;rbuf);<BR>+&nbsp;conn-&gt;data_buf.length =
htonl(rs-&gt;rbuf_size &gt;&gt; 1);<BR>+&nbsp;conn-&gt;data_buf.key =
htonl(rs-&gt;rmr-&gt;rkey);<BR>+<BR>+&nbsp;param-&gt;private_data =
conn;<BR>+&nbsp;param-&gt;private_data_len = sizeof *conn;<BR>+}<BR>+<BR>+static
void rs_save_conn_data(struct rsocket *rs, struct rs_conn_data
*conn)<BR>+{<BR>+&nbsp;rs-&gt;remote_sgl.addr =
ntohll(conn-&gt;target_sgl.addr);<BR>+&nbsp;rs-&gt;remote_sgl.length =
ntohl(conn-&gt;target_sgl.length);<BR>+&nbsp;rs-&gt;remote_sgl.key =
ntohl(conn-&gt;target_sgl.key);<BR>+&nbsp;rs-&gt;remote_sge = 1;<BR>+&nbsp;if
((rs_host_is_net() &amp;&amp; !(conn-&gt;flags &amp; RS_CONN_FLAG_NET))
||<BR>+&nbsp;&nbsp;&nbsp;&nbsp; (!rs_host_is_net() &amp;&amp; (conn-&gt;flags
&amp; RS_CONN_FLAG_NET)))<BR>+&nbsp;&nbsp;rs-&gt;opts =
RS_OPT_SWAP_SGL;<BR>+<BR>+&nbsp;rs-&gt;target_sgl[0].addr =
ntohll(conn-&gt;data_buf.addr);<BR>+&nbsp;rs-&gt;target_sgl[0].length =
ntohl(conn-&gt;data_buf.length);<BR>+&nbsp;rs-&gt;target_sgl[0].key =
ntohl(conn-&gt;data_buf.key);<BR>+<BR>+&nbsp;rs-&gt;sseq_comp =
ntohs(conn-&gt;credits);<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int
rsocket(int domain, int type, int protocol)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;int ret;<BR>+<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;if
((domain != PF_INET &amp;&amp; domain != PF_INET6)
||<BR>+&nbsp;&nbsp;&nbsp;&nbsp; (type != SOCK_STREAM) || (protocol &amp;&amp;
protocol != IPPROTO_TCP))<BR>+&nbsp;&nbsp;return
ERR(ENOTSUP);<BR>+<BR>+&nbsp;rs_configure();<BR>+&nbsp;rs =
rs_alloc(NULL);<BR>+&nbsp;if (!rs)<BR>+&nbsp;&nbsp;return
ERR(ENOMEM);<BR>+<BR>+&nbsp;ret = rdma_create_id(NULL, &amp;rs-&gt;cm_id, rs,
RDMA_PS_TCP);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;ret =
rs_insert(rs);<BR>+&nbsp;if (ret &lt; 0)<BR>+&nbsp;&nbsp;goto
err;<BR>+<BR>+&nbsp;rs-&gt;cm_id-&gt;route.addr.src_addr.sa_family =
(ADDRESS_FAMILY)domain;<BR>+&nbsp;return
rs-&gt;index;<BR>+<BR>+err:<BR>+&nbsp;rs_free(rs);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rbind(int socket, const struct
sockaddr *addr, socklen_t addrlen)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;int ret;<BR>+<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs =
(struct rsocket *)idm_at(&amp;idm, socket);<BR>+&nbsp;ret =
rdma_bind_addr(rs-&gt;cm_id, (struct sockaddr *) addr);<BR>+&nbsp;if
(!ret)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;rs-&gt;state =
rs_bound;<BR>+&nbsp;}<BR>+&nbsp;else<BR>+&nbsp;{<BR>+&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rlisten(int socket, int
backlog)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int
ret;<BR>+<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+<BR>+&nbsp;if (backlog &gt; RS_MAX_BACKLOG ||
backlog == SOMAXCONN)<BR>+&nbsp;&nbsp;backlog =
RS_MAX_BACKLOG;<BR>+<BR>+&nbsp;ret = rdma_listen(rs-&gt;cm_id,
backlog);<BR>+&nbsp;if (!ret)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;rs-&gt;state =
rs_listening;<BR>+&nbsp;}<BR>+&nbsp;else<BR>+&nbsp;{<BR>+&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int rs_do_connect(struct rsocket
*rs)<BR>+{<BR>+&nbsp;struct rdma_conn_param param;<BR>+&nbsp;struct rs_conn_data
creq, *cresp;<BR>+&nbsp;struct sockaddr_storage dst_addr;<BR>+&nbsp;int to,
ret;<BR>+<BR>+&nbsp;switch (rs-&gt;state) {<BR>+&nbsp;case
rs_init:<BR>+&nbsp;case rs_bound:<BR>+resolve_addr:<BR>+&nbsp;&nbsp;to = 1000
&lt;&lt;
rs-&gt;retries++;<BR>+&nbsp;&nbsp;RtlCopyMemory(<BR>+&nbsp;&nbsp;&nbsp;&amp;dst_addr,<BR>+&nbsp;&nbsp;&nbsp;&amp;rs-&gt;cm_id-&gt;route.addr.dst_addr,<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;cm_id-&gt;route.addr.dst_addr.sa_family
== AF_INET<BR>+&nbsp;&nbsp;&nbsp;? sizeof(struct
sockaddr_in)<BR>+&nbsp;&nbsp;&nbsp;: sizeof(struct
sockaddr_in6)<BR>+&nbsp;&nbsp;);<BR>+&nbsp;&nbsp;ret =
rdma_resolve_addr(rs-&gt;cm_id, NULL,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(struct
sockaddr *)&amp;dst_addr, to);<BR>+&nbsp;&nbsp;if
(!ret)<BR>+&nbsp;&nbsp;&nbsp;goto resolve_route;<BR>+&nbsp;&nbsp;if (errno ==
EAGAIN || errno == EWOULDBLOCK)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_resolving_addr;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
rs_resolving_addr:<BR>+&nbsp;&nbsp;ret =
ucma_complete(rs-&gt;cm_id);<BR>+&nbsp;&nbsp;if (ret) {<BR>+&nbsp;&nbsp;&nbsp;if
(errno == ETIMEDOUT &amp;&amp; rs-&gt;retries &lt;=
RS_CONN_RETRIES)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;goto
resolve_addr;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;rs-&gt;retries
= 0;<BR>+resolve_route:<BR>+&nbsp;&nbsp;to = 1000 &lt;&lt;
rs-&gt;retries++;<BR>+&nbsp;&nbsp;ret = rdma_resolve_route(rs-&gt;cm_id,
to);<BR>+&nbsp;&nbsp;if (!ret)<BR>+&nbsp;&nbsp;&nbsp;goto
do_connect;<BR>+&nbsp;&nbsp;if (errno == EAGAIN || errno ==
EWOULDBLOCK)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_resolving_route;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
rs_resolving_route:<BR>+&nbsp;&nbsp;ret =
ucma_complete(rs-&gt;cm_id);<BR>+&nbsp;&nbsp;if (ret) {<BR>+&nbsp;&nbsp;&nbsp;if
(errno == ETIMEDOUT &amp;&amp; rs-&gt;retries &lt;=
RS_CONN_RETRIES)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;goto
resolve_route;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+do_connect:<BR>+&nbsp;&nbsp;ret
= rs_create_ep(rs);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+<BR>+&nbsp;&nbsp;memset(&amp;param, 0,
sizeof param);<BR>+&nbsp;&nbsp;rs_set_conn_data(rs, &amp;param,
&amp;creq);<BR>+&nbsp;&nbsp;param.flow_control =
1;<BR>+&nbsp;&nbsp;param.retry_count = 7;<BR>+&nbsp;&nbsp;param.rnr_retry_count
= 7;<BR>+&nbsp;&nbsp;rs-&gt;retries = 0;<BR>+<BR>+&nbsp;&nbsp;ret =
rdma_connect(rs-&gt;cm_id, &amp;param);<BR>+&nbsp;&nbsp;if
(!ret)<BR>+&nbsp;&nbsp;&nbsp;goto connected;<BR>+&nbsp;&nbsp;if (errno == EAGAIN
|| errno == EWOULDBLOCK)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_connecting;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
rs_connecting:<BR>+&nbsp;&nbsp;ret =
ucma_complete(rs-&gt;cm_id);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+connected:<BR>+&nbsp;&nbsp;cresp =
(struct rs_conn_data *)
rs-&gt;cm_id-&gt;event-&gt;param.conn.private_data;<BR>+&nbsp;&nbsp;if
(cresp-&gt;version != 1) {<BR>+&nbsp;&nbsp;&nbsp;ret =
ERR(ENOTSUP);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;rs_save_conn_data(rs,
cresp);<BR>+&nbsp;&nbsp;rs-&gt;state =
rs_connect_rdwr;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
rs_accepting:<BR>+&nbsp;&nbsp;if (!(rs-&gt;fd_flags &amp;
O_NONBLOCK))<BR>+&nbsp;&nbsp;&nbsp;rs_set_nonblocking(rs,
0);<BR>+<BR>+&nbsp;&nbsp;ret = ucma_complete(rs-&gt;cm_id);<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+<BR>+&nbsp;&nbsp;rs-&gt;state =
rs_connect_rdwr;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;ret =
ERR(EINVAL);<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;if (errno == EAGAIN || errno == EWOULDBLOCK)
{<BR>+&nbsp;&nbsp;&nbsp;errno = EINPROGRESS;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_connect_error;<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;err =
errno;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;}<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rconnect(int socket, const
struct sockaddr *addr, socklen_t addrlen)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm,
socket);<BR>+&nbsp;memcpy(&amp;rs-&gt;cm_id-&gt;route.addr.dst_addr, addr,
addrlen);<BR>+&nbsp;return rs_do_connect(rs);<BR>+}<BR>+<BR>+static int
rs_post_write(struct rsocket *rs,<BR>+&nbsp;&nbsp;&nbsp; struct ibv_sge *sgl,
int nsge,<BR>+&nbsp;&nbsp;&nbsp; uint32_t imm_data, int
flags,<BR>+&nbsp;&nbsp;&nbsp; uint64_t addr, uint32_t
rkey)<BR>+{<BR>+&nbsp;struct ibv_send_wr wr, *bad;<BR>+<BR>+&nbsp;wr.wr_id =
(uint64_t) imm_data;<BR>+&nbsp;wr.next = NULL;<BR>+&nbsp;wr.sg_list =
sgl;<BR>+&nbsp;wr.num_sge = nsge;<BR>+&nbsp;wr.opcode =
IBV_WR_RDMA_WRITE_WITH_IMM;<BR>+&nbsp;wr.send_flags =
flags;<BR>+&nbsp;wr.imm_data = htonl(imm_data);<BR>+&nbsp;wr.wr.rdma.remote_addr
= addr;<BR>+&nbsp;wr.wr.rdma.rkey = rkey;<BR>+<BR>+&nbsp;return
rdma_seterrno(ibv_post_send(rs-&gt;cm_id-&gt;qp, &amp;wr,
&amp;bad));<BR>+}<BR>+<BR>+/*<BR>+ * Update target SGE before sending
data.&nbsp; Otherwise the remote side may<BR>+ * update the entry before we
do.<BR>+ */<BR>+static int rs_write_data(struct rsocket
*rs,<BR>+&nbsp;&nbsp;&nbsp; struct ibv_sge *sgl, int
nsge,<BR>+&nbsp;&nbsp;&nbsp; uint32_t length, int
flags)<BR>+{<BR>+&nbsp;uint64_t addr;<BR>+&nbsp;uint32_t
rkey;<BR>+<BR>+&nbsp;rs-&gt;sseq_no++;<BR>+&nbsp;rs-&gt;sqe_avail--;<BR>+&nbsp;rs-&gt;sbuf_bytes_avail
-= length;<BR>+<BR>+&nbsp;addr =
rs-&gt;target_sgl[rs-&gt;target_sge].addr;<BR>+&nbsp;rkey =
rs-&gt;target_sgl[rs-&gt;target_sge].key;<BR>+<BR>+&nbsp;rs-&gt;target_sgl[rs-&gt;target_sge].addr
+= length;<BR>+&nbsp;rs-&gt;target_sgl[rs-&gt;target_sge].length -=
length;<BR>+<BR>+&nbsp;if (!rs-&gt;target_sgl[rs-&gt;target_sge].length)
{<BR>+&nbsp;&nbsp;if (++rs-&gt;target_sge ==
RS_SGL_SIZE)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;target_sge =
0;<BR>+&nbsp;}<BR>+<BR>+&nbsp;return rs_post_write(rs, sgl, nsge,
rs_msg_set(RS_OP_DATA, length),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
flags, addr, rkey);<BR>+}<BR>+<BR>+static uint32_t rs_sbuf_left(struct rsocket
*rs)<BR>+{<BR>+&nbsp;return (uint32_t) (((uint64_t) (uintptr_t)
&amp;rs-&gt;sbuf[rs-&gt;sbuf_size]) -<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs-&gt;ssgl[0].addr);<BR>+}<BR>+<BR>+static void rs_send_credits(struct rsocket
*rs)<BR>+{<BR>+&nbsp;struct ibv_sge ibsge;<BR>+&nbsp;struct rs_sge
sge;<BR>+<BR>+&nbsp;rs-&gt;ctrl_avail--;<BR>+&nbsp;rs-&gt;rseq_comp =
rs-&gt;rseq_no + (rs-&gt;rq_size &gt;&gt; 1);<BR>+&nbsp;if
((uint32_t)rs-&gt;rbuf_bytes_avail &gt;= (rs-&gt;rbuf_size &gt;&gt; 1))
{<BR>+&nbsp;&nbsp;if (!(rs-&gt;opts &amp; RS_OPT_SWAP_SGL))
{<BR>+&nbsp;&nbsp;&nbsp;sge.addr = (uintptr_t)
&amp;rs-&gt;rbuf[rs-&gt;rbuf_free_offset];<BR>+&nbsp;&nbsp;&nbsp;sge.key =
rs-&gt;rmr-&gt;rkey;<BR>+&nbsp;&nbsp;&nbsp;sge.length = rs-&gt;rbuf_size
&gt;&gt; 1;<BR>+&nbsp;&nbsp;} else {<BR>+&nbsp;&nbsp;&nbsp;sge.addr =
cl_ntoh64((uintptr_t)
&amp;rs-&gt;rbuf[rs-&gt;rbuf_free_offset]);<BR>+&nbsp;&nbsp;&nbsp;sge.key =
cl_ntoh32(rs-&gt;rmr-&gt;rkey);<BR>+&nbsp;&nbsp;&nbsp;sge.length =
cl_ntoh32(rs-&gt;rbuf_size &gt;&gt;
1);<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;ibsge.addr = (uintptr_t)
&amp;sge;<BR>+&nbsp;&nbsp;ibsge.lkey = 0;<BR>+&nbsp;&nbsp;ibsge.length =
sizeof(sge);<BR>+<BR>+&nbsp;&nbsp;rs_post_write(rs, &amp;ibsge,
1,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs_msg_set(RS_OP_SGL,
rs-&gt;rseq_no +
rs-&gt;rq_size),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
IBV_SEND_INLINE,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs-&gt;remote_sgl.addr +<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs-&gt;remote_sge * sizeof(struct
rs_sge),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs-&gt;remote_sgl.key);<BR>+<BR>+&nbsp;&nbsp;rs-&gt;rbuf_bytes_avail -=
rs-&gt;rbuf_size &gt;&gt; 1;<BR>+&nbsp;&nbsp;rs-&gt;rbuf_free_offset +=
rs-&gt;rbuf_size &gt;&gt; 1;<BR>+&nbsp;&nbsp;if
((uint32_t)rs-&gt;rbuf_free_offset &gt;=
rs-&gt;rbuf_size)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_free_offset =
0;<BR>+&nbsp;&nbsp;if (++rs-&gt;remote_sge ==
rs-&gt;remote_sgl.length)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;remote_sge =
0;<BR>+&nbsp;} else {<BR>+&nbsp;&nbsp;rs_post_write(rs, NULL,
0,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs_msg_set(RS_OP_SGL,
rs-&gt;rseq_no + rs-&gt;rq_size), 0, 0, 0);<BR>+&nbsp;}<BR>+}<BR>+<BR>+static
int rs_give_credits(struct rsocket *rs)<BR>+{<BR>+&nbsp;return
(((uint32_t)rs-&gt;rbuf_bytes_avail &gt;= (rs-&gt;rbuf_size &gt;&gt; 1))
||<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ((short) ((short)
rs-&gt;rseq_no - (short) rs-&gt;rseq_comp) &gt;= 0))
&amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs-&gt;ctrl_avail
&amp;&amp; (rs-&gt;state &amp; rs_connected);<BR>+}<BR>+<BR>+static void
rs_update_credits(struct rsocket *rs)<BR>+{<BR>+&nbsp;if
(rs_give_credits(rs))<BR>+&nbsp;&nbsp;rs_send_credits(rs);<BR>+}<BR>+<BR>+static
int rs_poll_cq(struct rsocket *rs)<BR>+{<BR>+&nbsp;struct ibv_wc
wc;<BR>+&nbsp;uint32_t imm_data;<BR>+&nbsp;int ret, rcnt =
0;<BR>+<BR>+&nbsp;while ((ret = ibv_poll_cq(rs-&gt;cm_id-&gt;recv_cq, 1,
&amp;wc)) &gt; 0) {<BR>+&nbsp;&nbsp;if (wc.wr_id == RS_RECV_WR_ID)
{<BR>+&nbsp;&nbsp;&nbsp;if (wc.status !=
IBV_WC_SUCCESS)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;continue;<BR>+&nbsp;&nbsp;&nbsp;rcnt++;<BR>+<BR>+&nbsp;&nbsp;&nbsp;imm_data
= ntohl(wc.imm_data);<BR>+&nbsp;&nbsp;&nbsp;switch (rs_msg_op(imm_data))
{<BR>+&nbsp;&nbsp;&nbsp;case
RS_OP_SGL:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;sseq_comp = (uint16_t)
rs_msg_data(imm_data);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
RS_OP_CTRL:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if (rs_msg_data(imm_data) ==
RS_CTRL_DISCONNECT) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_disconnected;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return
0;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;} else if (rs_msg_data(imm_data) ==
RS_CTRL_SHUTDOWN) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;state &amp;=
~rs_connect_rd;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rmsg[rs-&gt;rmsg_tail].op
=
rs_msg_op(imm_data);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rmsg[rs-&gt;rmsg_tail].data
= rs_msg_data(imm_data);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if (++rs-&gt;rmsg_tail ==
rs-&gt;rq_size + 1)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rmsg_tail =
0;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}
else {<BR>+&nbsp;&nbsp;&nbsp;switch&nbsp; (rs_msg_op((uint32_t) wc.wr_id))
{<BR>+&nbsp;&nbsp;&nbsp;case
RS_OP_SGL:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ctrl_avail++;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
RS_OP_CTRL:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ctrl_avail++;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if
(rs_msg_data((uint32_t) wc.wr_id) ==
RS_CTRL_DISCONNECT)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_disconnected;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;sqe_avail++;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;sbuf_bytes_avail
+= rs_msg_data((uint32_t)
wc.wr_id);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;&nbsp;if
(wc.status != IBV_WC_SUCCESS &amp;&amp; (rs-&gt;state &amp; rs_connected))
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_error;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;err =
EIO;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(rs-&gt;state &amp; rs_connected) {<BR>+&nbsp;&nbsp;while (!ret &amp;&amp;
rcnt--)<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_post_recv(rs);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;<BR>+&nbsp;&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state =
rs_error;<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;err =
errno;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+static
int rs_get_cq_event(struct rsocket *rs)<BR>+{<BR>+&nbsp;struct ibv_cq
*cq;<BR>+&nbsp;void *context;<BR>+&nbsp;int ret;<BR>+<BR>+&nbsp;if
(!rs-&gt;cq_armed)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;return
0;<BR>+&nbsp;}<BR>+&nbsp;ret =
ibv_get_cq_event(rs-&gt;cm_id-&gt;recv_cq_channel, &amp;cq,
&amp;context);<BR>+&nbsp;if (!ret)
{<BR>+&nbsp;&nbsp;ibv_ack_cq_events(rs-&gt;cm_id-&gt;recv_cq,
1);<BR>+&nbsp;&nbsp;rs-&gt;cq_armed = 0;<BR>+&nbsp;} else if (errno != EAGAIN)
{<BR>+&nbsp;&nbsp;rs-&gt;state = rs_error;<BR>+&nbsp;}<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+/*<BR>+ * Although we serialize rsend and rrecv calls with
respect to themselves,<BR>+ * both calls may run simultaneously and need to poll
the CQ for completions.<BR>+ * We need to serialize access to the CQ, but rsend
and rrecv need to<BR>+ * allow each other to make forward progress.<BR>+ *<BR>+
* For example, rsend may need to wait for credits from the remote side,<BR>+ *
which could be stalled until the remote process calls rrecv.&nbsp; This
should<BR>+ * not block rrecv from receiving data from the remote side
however.<BR>+ *<BR>+ * We handle this by using two locks.&nbsp; The cq_lock
protects against polling<BR>+ * the CQ and processing completions.&nbsp; The
cq_wait_lock serializes access to<BR>+ * waiting on the CQ.<BR>+ */<BR>+static
int rs_process_cq(struct rsocket *rs, int nonblock, int (*test)(struct rsocket
*rs))<BR>+{<BR>+&nbsp;int
ret;<BR>+<BR>+&nbsp;fastlock_acquire(&amp;rs-&gt;cq_lock);<BR>+&nbsp;do
{<BR>+&nbsp;&nbsp;rs_update_credits(rs);<BR>+&nbsp;&nbsp;ret =
rs_poll_cq(rs);<BR>+&nbsp;&nbsp;if (test(rs)) {<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;} else if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;} else if (nonblock)
{<BR>+&nbsp;&nbsp;&nbsp;ret = ERR(EWOULDBLOCK);<BR>+&nbsp;&nbsp;} else if
(!rs-&gt;cq_armed)
{<BR>+&nbsp;&nbsp;&nbsp;ibv_req_notify_cq(rs-&gt;cm_id-&gt;recv_cq,
0);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;cq_armed = 1;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rs_update_credits(rs);<BR>+&nbsp;&nbsp;&nbsp;fastlock_acquire(&amp;rs-&gt;cq_wait_lock);<BR>+&nbsp;&nbsp;&nbsp;fastlock_release(&amp;rs-&gt;cq_lock);<BR>+&nbsp;&nbsp;&nbsp;ret
=
rs_get_cq_event(rs);<BR>+&nbsp;&nbsp;&nbsp;fastlock_release(&amp;rs-&gt;cq_wait_lock);<BR>+&nbsp;&nbsp;&nbsp;fastlock_acquire(&amp;rs-&gt;cq_lock);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}
while
(!ret);<BR>+<BR>+&nbsp;rs_update_credits(rs);<BR>+&nbsp;fastlock_release(&amp;rs-&gt;cq_lock);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static int rs_get_comp(struct rsocket *rs, int nonblock, int
(*test)(struct rsocket *rs))<BR>+{<BR>+&nbsp;struct timeval s,
e;<BR>+&nbsp;uint32_t poll_time = 0;<BR>+&nbsp;int ret;<BR>+&nbsp;do
{<BR>+&nbsp;&nbsp;ret = rs_process_cq(rs, 1, test);<BR>+&nbsp;&nbsp;if (!ret ||
nonblock || errno != EWOULDBLOCK) {<BR>+&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if
(!poll_time)<BR>+&nbsp;&nbsp;&nbsp;gettimeofday(&amp;s,
NULL);<BR>+<BR>+&nbsp;&nbsp;gettimeofday(&amp;e,
NULL);<BR>+&nbsp;&nbsp;poll_time = (e.tv_sec - s.tv_sec) * 1000000
+<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (e.tv_usec - s.tv_usec) +
1;<BR>+&nbsp;} while (poll_time &lt;= polling_time);<BR>+&nbsp;ret =
rs_process_cq(rs, 0, test);<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+static int
rs_nonblocking(struct rsocket *rs)<BR>+{<BR>+&nbsp;return (rs-&gt;fd_flags &amp;
O_NONBLOCK);<BR>+}<BR>+<BR>+static int rs_is_cq_armed(struct rsocket
*rs)<BR>+{<BR>+&nbsp;return rs-&gt;cq_armed;<BR>+}<BR>+<BR>+static int
rs_poll_all(struct rsocket *rs)<BR>+{<BR>+&nbsp;return 1;<BR>+}<BR>+<BR>+/*<BR>+
* We use hardware flow control to prevent over running the remote<BR>+ * receive
queue.&nbsp; However, data transfers still require space in<BR>+ * the remote
rmsg queue, or we risk losing notification that data<BR>+ * has been
transfered.<BR>+ *<BR>+ * Be careful with race conditions in the check
below.&nbsp; The target SGL<BR>+ * may be updated by a remote RDMA write.<BR>+
*/<BR>+static int rs_can_send(struct rsocket *rs)<BR>+{<BR>+&nbsp;return
rs-&gt;sqe_avail &amp;&amp; rs-&gt;sbuf_bytes_avail
&amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (rs-&gt;sseq_no !=
rs-&gt;sseq_comp) &amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(rs-&gt;target_sgl[rs-&gt;target_sge].length != 0);<BR>+}<BR>+<BR>+static int
rs_conn_can_send(struct rsocket *rs)<BR>+{<BR>+&nbsp;return rs_can_send(rs) ||
!(rs-&gt;state &amp; rs_connect_wr);<BR>+}<BR>+<BR>+static int
rs_conn_can_send_ctrl(struct rsocket *rs)<BR>+{<BR>+&nbsp;return
rs-&gt;ctrl_avail || !(rs-&gt;state &amp; rs_connected);<BR>+}<BR>+<BR>+static
int rs_have_rdata(struct rsocket *rs)<BR>+{<BR>+&nbsp;return (rs-&gt;rmsg_head
!= rs-&gt;rmsg_tail);<BR>+}<BR>+<BR>+static int rs_conn_have_rdata(struct
rsocket *rs)<BR>+{<BR>+&nbsp;return rs_have_rdata(rs) || !(rs-&gt;state &amp;
rs_connect_rd);<BR>+}<BR>+<BR>+static int rs_conn_all_sends_done(struct rsocket
*rs)<BR>+{<BR>+&nbsp;return ((rs-&gt;sqe_avail + rs-&gt;ctrl_avail) ==
rs-&gt;sq_size) ||<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; !(rs-&gt;state
&amp; rs_connected);<BR>+}<BR>+<BR>+static ssize_t rs_peek(struct rsocket *rs,
void *buf, size_t len)<BR>+{<BR>+&nbsp;size_t left = len;<BR>+&nbsp;uint32_t
end_size, rsize;<BR>+&nbsp;int rmsg_head, rbuf_offset;<BR>+&nbsp;uint8_t *bufb =
(uint8_t *)buf;<BR>+<BR>+&nbsp;rmsg_head =
rs-&gt;rmsg_head;<BR>+&nbsp;rbuf_offset = rs-&gt;rbuf_offset;<BR>+<BR>+&nbsp;for
(; left &amp;&amp; (rmsg_head != rs-&gt;rmsg_tail); left -= rsize)
{<BR>+&nbsp;&nbsp;if (left &lt; rs-&gt;rmsg[rmsg_head].data)
{<BR>+&nbsp;&nbsp;&nbsp;rsize = left;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rsize =
rs-&gt;rmsg[rmsg_head].data;<BR>+&nbsp;&nbsp;&nbsp;if (++rmsg_head ==
rs-&gt;rq_size + 1)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rmsg_head =
0;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;end_size = rs-&gt;rbuf_size -
rbuf_offset;<BR>+&nbsp;&nbsp;if (rsize &gt; end_size)
{<BR>+&nbsp;&nbsp;&nbsp;memcpy(bufb, &amp;rs-&gt;rbuf[rbuf_offset],
end_size);<BR>+&nbsp;&nbsp;&nbsp;rbuf_offset = 0;<BR>+&nbsp;&nbsp;&nbsp;bufb +=
end_size;<BR>+&nbsp;&nbsp;&nbsp;rsize -= end_size;<BR>+&nbsp;&nbsp;&nbsp;left -=
end_size;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;memcpy(bufb,
&amp;rs-&gt;rbuf[rbuf_offset], rsize);<BR>+&nbsp;&nbsp;rbuf_offset +=
rsize;<BR>+&nbsp;&nbsp;bufb += rsize;<BR>+&nbsp;}<BR>+<BR>+&nbsp;return len -
left;<BR>+}<BR>+<BR>+/*<BR>+ * Continue to receive any queued data even if the
remote side has disconnected.<BR>+ */<BR>+ __declspec(dllexport)<BR>+ssize_t
rrecv(int socket, void *buf, size_t len, int flags)<BR>+{<BR>+&nbsp;struct
rsocket *rs;<BR>+&nbsp;size_t left = len;<BR>+&nbsp;uint32_t end_size,
rsize;<BR>+&nbsp;int ret;<BR>+&nbsp;uint8_t *bufb = (uint8_t
*)buf;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;if (rs-&gt;state &amp; rs_opening)
{<BR>+&nbsp;&nbsp;ret = rs_do_connect(rs);<BR>+&nbsp;&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;if (errno ==
EINPROGRESS)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;errno =
EAGAIN;<BR>+&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;fastlock_acquire(&amp;rs-&gt;rlock);<BR>+&nbsp;do
{<BR>+&nbsp;&nbsp;if (!rs_have_rdata(rs)) {<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_get_comp(rs,
rs_nonblocking(rs),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs_conn_have_rdata);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;ret
= 0;<BR>+&nbsp;&nbsp;if (flags &amp; MSG_PEEK) {<BR>+&nbsp;&nbsp;&nbsp;left =
len - rs_peek(rs, buf,
left);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;for
(; left &amp;&amp; rs_have_rdata(rs); left -= rsize) {<BR>+&nbsp;&nbsp;&nbsp;if
(left &lt; rs-&gt;rmsg[rs-&gt;rmsg_head].data)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rsize =
left;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rmsg[rs-&gt;rmsg_head].data -=
left;<BR>+&nbsp;&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rseq_no++;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rsize
= rs-&gt;rmsg[rs-&gt;rmsg_head].data;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;if
(++rs-&gt;rmsg_head == rs-&gt;rq_size +
1)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rmsg_head =
0;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;&nbsp;end_size =
rs-&gt;rbuf_size - rs-&gt;rbuf_offset;<BR>+&nbsp;&nbsp;&nbsp;if (rsize &gt;
end_size) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;memcpy(bufb,
&amp;rs-&gt;rbuf[rs-&gt;rbuf_offset],
end_size);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_offset =
0;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;bufb +=
end_size;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rsize -=
end_size;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;left -=
end_size;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_bytes_avail +=
end_size;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;memcpy(bufb,
&amp;rs-&gt;rbuf[rs-&gt;rbuf_offset],
rsize);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_offset +=
rsize;<BR>+&nbsp;&nbsp;&nbsp;bufb +=
rsize;<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_bytes_avail +=
rsize;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;} while (left &amp;&amp; (flags &amp;
MSG_WAITALL) &amp;&amp; (rs-&gt;state &amp;
rs_connect_rd));<BR>+&nbsp;<BR>+&nbsp;fastlock_release(&amp;rs-&gt;rlock);<BR>+<BR>+out:<BR>+&nbsp;if
(ret)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+&nbsp;else<BR>+&nbsp;{<BR>+&nbsp;&nbsp;return len -
left;<BR>+&nbsp;}<BR>+}<BR>+<BR>+ssize_t rrecvfrom(int socket, void *buf, size_t
len, int flags,<BR>+&nbsp;&nbsp;&nbsp; struct sockaddr *src_addr, socklen_t
*addrlen)<BR>+{<BR>+&nbsp;ssize_t ret;<BR>+<BR>+&nbsp;ret = rrecv(socket, buf,
len, flags);<BR>+&nbsp;if (ret &gt; 0 &amp;&amp;
src_addr)<BR>+&nbsp;&nbsp;rgetpeername(socket, src_addr,
addrlen);<BR>+<BR>+&nbsp;return ret;<BR>+}<BR>+<BR>+/*<BR>+ * Simple,
straightforward implementation for now that only tries to fill<BR>+ * in the
first vector.<BR>+ */<BR>+static ssize_t rrecvv(int socket, const struct iovec
*iov, int iovcnt, int flags)<BR>+{<BR>+&nbsp;return rrecv(socket,
iov[0].iov_base, iov[0].iov_len, flags);<BR>+}<BR>+<BR>+ssize_t rrecvmsg(int
socket, struct msghdr *msg, int flags)<BR>+{<BR>+&nbsp;if (msg-&gt;msg_control
&amp;&amp; msg-&gt;msg_controllen)<BR>+&nbsp;&nbsp;return
ERR(ENOTSUP);<BR>+<BR>+&nbsp;return rrecvv(socket, msg-&gt;msg_iov, (int)
msg-&gt;msg_iovlen, msg-&gt;msg_flags);<BR>+}<BR>+<BR>+ssize_t rread(int socket,
void *buf, size_t count)<BR>+{<BR>+&nbsp;return rrecv(socket, buf, count,
0);<BR>+}<BR>+<BR>+ssize_t rreadv(int socket, const struct iovec *iov, int
iovcnt)<BR>+{<BR>+&nbsp;return rrecvv(socket, iov, iovcnt,
0);<BR>+}<BR>+<BR>+/*<BR>+ * We overlap sending the data, by posting a small
work request immediately,<BR>+ * then increasing the size of the send on each
iteration.<BR>+ */<BR>+ssize_t rsend(int socket, const void *buf, size_t len,
int flags)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;struct ibv_sge
sge;<BR>+&nbsp;size_t left = len;<BR>+&nbsp;uint32_t xfer_size, olen =
RS_OLAP_START_SIZE;<BR>+&nbsp;int ret = 0;<BR>+&nbsp;uint8_t *bufb = (uint8_t
*)buf;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;if (rs-&gt;state &amp; rs_opening)
{<BR>+&nbsp;&nbsp;ret = rs_do_connect(rs);<BR>+&nbsp;&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;if (errno ==
EINPROGRESS)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;errno =
EAGAIN;<BR>+&nbsp;&nbsp;&nbsp;goto
out;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;fastlock_acquire(&amp;rs-&gt;slock);<BR>+&nbsp;for
(; left; left -= xfer_size, bufb += xfer_size) {<BR>+&nbsp;&nbsp;if
(!rs_can_send(rs)) {<BR>+&nbsp;&nbsp;&nbsp;ret = rs_get_comp(rs,
rs_nonblocking(rs),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs_conn_can_send);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;if
(!(rs-&gt;state &amp; rs_connect_wr)) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;ret =
ERR(ECONNRESET);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if
(olen &lt; left) {<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
olen;<BR>+&nbsp;&nbsp;&nbsp;if (olen &lt;
RS_MAX_TRANSFER)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;olen &lt;&lt;= 1;<BR>+&nbsp;&nbsp;}
else {<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
left;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if (xfer_size &gt;
(uint32_t)rs-&gt;sbuf_bytes_avail)<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
rs-&gt;sbuf_bytes_avail;<BR>+&nbsp;&nbsp;if (xfer_size &gt;
rs-&gt;target_sgl[rs-&gt;target_sge].length)<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
rs-&gt;target_sgl[rs-&gt;target_sge].length;<BR>+<BR>+&nbsp;&nbsp;if (xfer_size
&lt;= rs-&gt;sq_inline) {<BR>+&nbsp;&nbsp;&nbsp;sge.addr =
(uintptr_t)bufb;<BR>+&nbsp;&nbsp;&nbsp;sge.length =
xfer_size;<BR>+&nbsp;&nbsp;&nbsp;sge.lkey = 0;<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_write_data(rs, &amp;sge, 1, xfer_size, IBV_SEND_INLINE);<BR>+&nbsp;&nbsp;}
else if (xfer_size &lt;= rs_sbuf_left(rs)) {<BR>+&nbsp;&nbsp;&nbsp;memcpy((void
*) (uintptr_t) rs-&gt;ssgl[0].addr, bufb,
xfer_size);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].length =
xfer_size;<BR>+&nbsp;&nbsp;&nbsp;ret = rs_write_data(rs, rs-&gt;ssgl, 1,
xfer_size, 0);<BR>+&nbsp;&nbsp;&nbsp;if (xfer_size &lt;
rs_sbuf_left(rs))<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr +=
xfer_size;<BR>+&nbsp;&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr
= (uintptr_t) rs-&gt;sbuf;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].length =
rs_sbuf_left(rs);<BR>+&nbsp;&nbsp;&nbsp;memcpy((void *) (uintptr_t)
rs-&gt;ssgl[0].addr,
bufb,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].length);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[1].length
= xfer_size - rs-&gt;ssgl[0].length;<BR>+&nbsp;&nbsp;&nbsp;memcpy(rs-&gt;sbuf,
bufb + rs-&gt;ssgl[0].length, rs-&gt;ssgl[1].length);<BR>+&nbsp;&nbsp;&nbsp;ret
= rs_write_data(rs, rs-&gt;ssgl, 2, xfer_size,
0);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr = (uintptr_t) rs-&gt;sbuf +
rs-&gt;ssgl[1].length;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+&nbsp;fastlock_release(&amp;rs-&gt;slock);<BR>+<BR>+out:<BR>+&nbsp;if
(ret &amp;&amp; left ==
len)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;&nbsp;return
ret;<BR>+&nbsp;}<BR>+&nbsp;else<BR>+&nbsp;{<BR>+&nbsp;&nbsp;return len -
left;<BR>+&nbsp;}<BR>+}<BR>+<BR>+ssize_t rsendto(int socket, const void *buf,
size_t len, int flags,<BR>+&nbsp;&nbsp;const struct sockaddr *dest_addr,
socklen_t addrlen)<BR>+{<BR>+/*<BR>+ * In Windows on a connection-oriented
socket,<BR>+ * the dest_addr and addrlen parameters are just ignored,<BR>+ *
making sendto() equivalent to send().<BR>+ */<BR>+&nbsp;return rsend(socket,
buf, len, flags);<BR>+}<BR>+<BR>+static void rs_copy_iov(void *dst, const struct
iovec **iov, size_t *offset, size_t len)<BR>+{<BR>+&nbsp;size_t
size;<BR>+&nbsp;uint8_t *dstb = (uint8_t *)dst;<BR>+<BR>+&nbsp;while (len)
{<BR>+&nbsp;&nbsp;size = (*iov)-&gt;iov_len - *offset;<BR>+&nbsp;&nbsp;if (size
&gt; len) {<BR>+&nbsp;&nbsp;&nbsp;memcpy (dstb, (*iov)-&gt;iov_base + *offset,
len);<BR>+&nbsp;&nbsp;&nbsp;*offset +=
len;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;memcpy(dstb,
(*iov)-&gt;iov_base + *offset, size);<BR>+&nbsp;&nbsp;len -=
size;<BR>+&nbsp;&nbsp;dstb +=
size;<BR>+&nbsp;&nbsp;(*iov)++;<BR>+&nbsp;&nbsp;*offset =
0;<BR>+&nbsp;}<BR>+}<BR>+<BR>+static ssize_t rsendv(int socket, const struct
iovec *iov, int iovcnt, int flags)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;const struct iovec *cur_iov;<BR>+&nbsp;size_t left, len, offset =
0;<BR>+&nbsp;uint32_t xfer_size, olen = RS_OLAP_START_SIZE;<BR>+&nbsp;int i, ret
= 0;<BR>+<BR>+&nbsp;rs = (struct rsocket *)idm_at(&amp;idm,
socket);<BR>+&nbsp;if (rs-&gt;state &amp; rs_opening) {<BR>+&nbsp;&nbsp;ret =
rs_do_connect(rs);<BR>+&nbsp;&nbsp;if (ret) {<BR>+&nbsp;&nbsp;&nbsp;if (errno ==
EINPROGRESS)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;errno =
EAGAIN;<BR>+&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;cur_iov = iov;<BR>+&nbsp;len =
iov[0].iov_len;<BR>+&nbsp;for (i = 1; i &lt; iovcnt; i++)<BR>+&nbsp;&nbsp;len +=
iov[i].iov_len;<BR>+<BR>+&nbsp;fastlock_acquire(&amp;rs-&gt;slock);<BR>+&nbsp;for
(left = len; left; left -= xfer_size) {<BR>+&nbsp;&nbsp;if (!rs_can_send(rs))
{<BR>+&nbsp;&nbsp;&nbsp;ret = rs_get_comp(rs,
rs_nonblocking(rs),<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs_conn_can_send);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;if
(!(rs-&gt;state &amp; rs_connect_wr)) {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;ret =
ERR(ECONNRESET);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if
(olen &lt; left) {<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
olen;<BR>+&nbsp;&nbsp;&nbsp;if (olen &lt;
RS_MAX_TRANSFER)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;olen &lt;&lt;= 1;<BR>+&nbsp;&nbsp;}
else {<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
left;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if (xfer_size &gt;
(uint32_t)rs-&gt;sbuf_bytes_avail)<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
rs-&gt;sbuf_bytes_avail;<BR>+&nbsp;&nbsp;if (xfer_size &gt;
rs-&gt;target_sgl[rs-&gt;target_sge].length)<BR>+&nbsp;&nbsp;&nbsp;xfer_size =
rs-&gt;target_sgl[rs-&gt;target_sge].length;<BR>+<BR>+&nbsp;&nbsp;if (xfer_size
&lt;= rs_sbuf_left(rs)) {<BR>+&nbsp;&nbsp;&nbsp;rs_copy_iov((void *) (uintptr_t)
rs-&gt;ssgl[0].addr,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&amp;cur_iov, &amp;offset,
xfer_size);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].length =
xfer_size;<BR>+&nbsp;&nbsp;&nbsp;ret = rs_write_data(rs, rs-&gt;ssgl, 1,
xfer_size,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xfer_size &lt;=
rs-&gt;sq_inline ? IBV_SEND_INLINE : 0);<BR>+&nbsp;&nbsp;&nbsp;if (xfer_size
&lt; rs_sbuf_left(rs))<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr +=
xfer_size;<BR>+&nbsp;&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr
= (uintptr_t) rs-&gt;sbuf;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].length =
rs_sbuf_left(rs);<BR>+&nbsp;&nbsp;&nbsp;rs_copy_iov((void *) (uintptr_t)
rs-&gt;ssgl[0].addr,
&amp;cur_iov,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;offset,
rs-&gt;ssgl[0].length);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[1].length = xfer_size
- rs-&gt;ssgl[0].length;<BR>+&nbsp;&nbsp;&nbsp;rs_copy_iov(rs-&gt;sbuf,
&amp;cur_iov, &amp;offset, rs-&gt;ssgl[1].length);<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_write_data(rs, rs-&gt;ssgl, 2,
xfer_size,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xfer_size &lt;=
rs-&gt;sq_inline ? IBV_SEND_INLINE :
0);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ssgl[0].addr = (uintptr_t) rs-&gt;sbuf +
rs-&gt;ssgl[1].length;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+&nbsp;fastlock_release(&amp;rs-&gt;slock);<BR>+<BR>+&nbsp;return
(ret &amp;&amp; left == len) ? ret : len -
left;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+ssize_t rsendmsg(int socket,
const struct msghdr *msg, int
flags)<BR>+{<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;if (msg-&gt;msg_control
&amp;&amp; msg-&gt;msg_controllen)<BR>+&nbsp;&nbsp;return
ERR(ENOTSUP);<BR>+<BR>+&nbsp;return rsendv(socket, msg-&gt;msg_iov, (int)
msg-&gt;msg_iovlen,
msg-&gt;msg_flags);<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+ssize_t rwrite(int
socket, const void *buf, size_t count)<BR>+{<BR>+&nbsp;return rsend(socket, buf,
count, 0);<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+ssize_t rwritev(int socket,
const struct iovec *iov, int iovcnt)<BR>+{<BR>+&nbsp;return rsendv(socket, iov,
iovcnt, 0);<BR>+}<BR>+<BR>+static struct pollfd *rs_fds_alloc(nfds_t
nfds)<BR>+{<BR>+&nbsp;static __thread struct pollfd *rfds;<BR>+&nbsp;static
__thread nfds_t rnfds;<BR>+<BR>+&nbsp;if (nfds &gt; rnfds) {<BR>+&nbsp;&nbsp;if
(rfds)<BR>+&nbsp;&nbsp;&nbsp;free(rfds);<BR>+<BR>+&nbsp;&nbsp;rfds = (struct
pollfd *)malloc(sizeof *rfds * nfds);<BR>+&nbsp;&nbsp;rnfds = rfds ? nfds :
0;<BR>+&nbsp;}<BR>+<BR>+&nbsp;return rfds;<BR>+}<BR>+<BR>+static int
rs_poll_rs(struct rsocket *rs, int
events,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nonblock, int
(*test)(struct rsocket *rs))<BR>+{<BR>+&nbsp;COMP_SET fds;<BR>+&nbsp;short
revents;<BR>+&nbsp;int ret;<BR>+<BR>+check_cq:<BR>+&nbsp;if ((rs-&gt;state &amp;
rs_connected) || (rs-&gt;state == rs_disconnected)
||<BR>+&nbsp;&nbsp;&nbsp;&nbsp; (rs-&gt;state &amp; rs_error))
{<BR>+&nbsp;&nbsp;rs_process_cq(rs, nonblock,
test);<BR>+<BR>+&nbsp;&nbsp;revents = 0;<BR>+&nbsp;&nbsp;if ((events &amp;
POLLIN) &amp;&amp; rs_conn_have_rdata(rs))<BR>+&nbsp;&nbsp;&nbsp;revents |=
POLLIN;<BR>+&nbsp;&nbsp;if ((events &amp; POLLOUT) &amp;&amp;
rs_can_send(rs))<BR>+&nbsp;&nbsp;&nbsp;revents |= POLLOUT;<BR>+&nbsp;&nbsp;if
(!(rs-&gt;state &amp; rs_connected)) {<BR>+&nbsp;&nbsp;&nbsp;if (rs-&gt;state ==
rs_disconnected)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;revents |=
POLLHUP;<BR>+&nbsp;&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;&nbsp;revents |=
POLLERR;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;return
revents;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (rs-&gt;state == rs_listening)
{<BR>+&nbsp;&nbsp;if (CompSetInit(&amp;fds))<BR>+&nbsp;&nbsp;&nbsp;return
0;<BR>+<BR>+&nbsp;&nbsp;CompSetZero(&amp;fds);<BR>+&nbsp;&nbsp;CompSetAdd(&amp;rs-&gt;cm_id-&gt;channel-&gt;channel,
&amp;fds);<BR>+&nbsp;&nbsp;return CompSetPoll(&amp;fds,
0);<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (rs-&gt;state &amp; rs_opening)
{<BR>+&nbsp;&nbsp;ret = rs_do_connect(rs);<BR>+&nbsp;&nbsp;if (ret)
{<BR>+&nbsp;&nbsp;&nbsp;if (errno == EINPROGRESS)
{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;errno = 0;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
0;<BR>+&nbsp;&nbsp;&nbsp;} else {<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
POLLOUT;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;goto
check_cq;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (rs-&gt;state ==
rs_connect_error)<BR>+&nbsp;&nbsp;return (rs-&gt;err &amp;&amp; events &amp;
POLLOUT) ? POLLOUT : 0;<BR>+<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+static int
rs_poll_check(struct pollfd *fds, nfds_t nfds)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;int i, cnt = 0;<BR>+<BR>+&nbsp;for (i = 0; i &lt; (int)nfds; i++)
{<BR>+&nbsp;&nbsp;rs = (struct rsocket *)idm_lookup(&amp;idm,
(int)fds[i].fd);<BR>+&nbsp;&nbsp;if (rs)<BR>+&nbsp;&nbsp;&nbsp;fds[i].revents =
(SHORT)rs_poll_rs(rs, fds[i].events, 1,
rs_poll_all);<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;;//WSAPoll(&amp;fds[i],
1, 0);<BR>+<BR>+&nbsp;&nbsp;if
(fds[i].revents)<BR>+&nbsp;&nbsp;&nbsp;cnt++;<BR>+&nbsp;}<BR>+&nbsp;return
cnt;<BR>+}<BR>+<BR>+static int rs_poll_arm(struct pollfd *rfds, struct pollfd
*fds, nfds_t nfds)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int
i;<BR>+<BR>+&nbsp;for (i = 0; i &lt; (int)nfds; i++) {<BR>+&nbsp;&nbsp;rs =
(struct rsocket *)idm_lookup(&amp;idm, (int)fds[i].fd);<BR>+&nbsp;&nbsp;if (rs)
{<BR>+&nbsp;&nbsp;&nbsp;fds[i].revents = (SHORT)rs_poll_rs(rs, fds[i].events, 0,
rs_is_cq_armed);<BR>+&nbsp;&nbsp;&nbsp;if
(fds[i].revents)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
1;<BR>+<BR>+&nbsp;&nbsp;&nbsp;if (rs-&gt;state &gt;=
rs_connected)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rfds[i].fd =
((short)rs-&gt;cm_id-&gt;recv_cq_channel-&gt;comp_channel.Event &gt;&gt;
2);<BR>+&nbsp;&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rfds[i].fd =
((short)rs-&gt;cm_id-&gt;channel-&gt;channel.Event &gt;&gt;
2);<BR>+<BR>+&nbsp;&nbsp;&nbsp;rfds[i].events = POLLIN;<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;rfds[i].fd =
fds[i].fd;<BR>+&nbsp;&nbsp;&nbsp;rfds[i].events =
fds[i].events;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;rfds[i].revents =
0;<BR>+&nbsp;}<BR>+&nbsp;return 0;<BR>+}<BR>+<BR>+static int
rs_poll_events(struct pollfd *rfds, struct pollfd *fds, nfds_t
nfds)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int i, cnt =
0;<BR>+<BR>+&nbsp;for (i = 0; i &lt; (int)nfds; i++) {<BR>+&nbsp;&nbsp;if
(!rfds[i].revents)<BR>+&nbsp;&nbsp;&nbsp;continue;<BR>+<BR>+&nbsp;&nbsp;rs =
(struct rsocket *)idm_lookup(&amp;idm, (int)fds[i].fd);<BR>+&nbsp;&nbsp;if (rs)
{<BR>+&nbsp;&nbsp;&nbsp;rs_get_cq_event(rs);<BR>+&nbsp;&nbsp;&nbsp;fds[i].revents
= (SHORT)rs_poll_rs(rs, fds[i].events, 1, rs_poll_all);<BR>+&nbsp;&nbsp;} else
{<BR>+&nbsp;&nbsp;&nbsp;fds[i].revents =
rfds[i].revents;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;if
(fds[i].revents)<BR>+&nbsp;&nbsp;&nbsp;cnt++;<BR>+&nbsp;}<BR>+&nbsp;return
cnt;<BR>+}<BR>+<BR>+/*<BR>+ * We need to poll *all* fd's that the user specifies
at least once.<BR>+ * Note that we may receive events on an rsocket that may not
be reported<BR>+ * to the user (e.g. connection events or credit updates).&nbsp;
Process those<BR>+ * events, then return to polling until we find ones of
interest.<BR>+ */<BR>+__declspec(dllexport)<BR>+int rpoll(struct pollfd *fds,
nfds_t nfds, int timeout)<BR>+{<BR>+&nbsp;struct timeval s, e;<BR>+&nbsp;struct
pollfd *rfds;<BR>+&nbsp;uint32_t poll_time = 0;<BR>+&nbsp;int
ret;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;do
{<BR>+&nbsp;&nbsp;ret = rs_poll_check(fds, nfds);<BR>+&nbsp;&nbsp;if (ret ||
!timeout)<BR>+&nbsp;&nbsp;&nbsp;return ret;<BR>+<BR>+&nbsp;&nbsp;if
(!poll_time)<BR>+&nbsp;&nbsp;&nbsp;gettimeofday(&amp;s,
NULL);<BR>+<BR>+&nbsp;&nbsp;gettimeofday(&amp;e,
NULL);<BR>+&nbsp;&nbsp;poll_time = (e.tv_sec - s.tv_sec) * 1000000
+<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (e.tv_usec - s.tv_usec) +
1;<BR>+&nbsp;} while (poll_time &lt;= polling_time);<BR>+<BR>+&nbsp;rfds =
rs_fds_alloc(nfds);<BR>+&nbsp;if (!rfds)<BR>+&nbsp;&nbsp;return
ERR(ENOMEM);<BR>+<BR>+&nbsp;do {<BR>+&nbsp;&nbsp;ret = rs_poll_arm(rfds, fds,
nfds);<BR>+&nbsp;&nbsp;if (ret)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+#if
0<BR>+&nbsp;&nbsp;ret = WSAPoll(rfds, nfds, timeout);<BR>+&nbsp;&nbsp;if (ret
&lt;= 0)<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+#endif<BR>+&nbsp;&nbsp;ret =
rs_poll_events(rfds, fds, nfds);<BR>+&nbsp;} while (!ret);<BR>+<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+static struct pollfd *<BR>+rs_select_to_poll(int *nfds,
fd_set *readfds, fd_set *writefds, fd_set *exceptfds)<BR>+{<BR>+&nbsp;struct
pollfd *fds;<BR>+&nbsp;int fd, i = 0;<BR>+<BR>+&nbsp;fds = (struct pollfd
*)calloc(*nfds, sizeof *fds);<BR>+&nbsp;if (!fds)<BR>+&nbsp;&nbsp;return
NULL;<BR>+<BR>+&nbsp;for (fd = 0; fd &lt; *nfds; fd++) {<BR>+&nbsp;&nbsp;if
(readfds &amp;&amp; FD_ISSET(fd, readfds)) {<BR>+&nbsp;&nbsp;&nbsp;fds[i].fd =
fd;<BR>+&nbsp;&nbsp;&nbsp;fds[i].events =
POLLIN;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if (writefds &amp;&amp;
FD_ISSET(fd, writefds)) {<BR>+&nbsp;&nbsp;&nbsp;fds[i].fd =
fd;<BR>+&nbsp;&nbsp;&nbsp;fds[i].events |=
POLLOUT;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if (exceptfds &amp;&amp;
FD_ISSET(fd, exceptfds))<BR>+&nbsp;&nbsp;&nbsp;fds[i].fd =
fd;<BR>+<BR>+&nbsp;&nbsp;if
(fds[i].fd)<BR>+&nbsp;&nbsp;&nbsp;i++;<BR>+&nbsp;}<BR>+<BR>+&nbsp;*nfds =
i;<BR>+&nbsp;return fds;<BR>+}<BR>+<BR>+static int<BR>+rs_poll_to_select(int
nfds, struct pollfd *fds, fd_set *readfds,<BR>+&nbsp;&nbsp;&nbsp; fd_set
*writefds, fd_set *exceptfds)<BR>+{<BR>+&nbsp;int i, cnt = 0;<BR>+<BR>+&nbsp;for
(i = 0; i &lt; nfds; i++) {<BR>+&nbsp;&nbsp;if (readfds &amp;&amp;
(fds[i].revents &amp; (POLLIN | POLLHUP)))
{<BR>+&nbsp;&nbsp;&nbsp;FD_SET(fds[i].fd,
readfds);<BR>+&nbsp;&nbsp;&nbsp;cnt++;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if
(writefds &amp;&amp; (fds[i].revents &amp; POLLOUT))
{<BR>+&nbsp;&nbsp;&nbsp;FD_SET(fds[i].fd,
writefds);<BR>+&nbsp;&nbsp;&nbsp;cnt++;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;if
(exceptfds &amp;&amp; (fds[i].revents &amp; ~(POLLIN | POLLOUT)))
{<BR>+&nbsp;&nbsp;&nbsp;FD_SET(fds[i].fd,
exceptfds);<BR>+&nbsp;&nbsp;&nbsp;cnt++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;return
cnt;<BR>+}<BR>+<BR>+static int rs_convert_timeout(struct timeval
*timeout)<BR>+{<BR>+&nbsp;return !timeout ? -1
:<BR>+&nbsp;&nbsp;timeout-&gt;tv_sec * 1000 + timeout-&gt;tv_usec /
1000;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rselect(int nfds, fd_set
*readfds, fd_set *writefds,<BR>+&nbsp;&nbsp;&nbsp;&nbsp; fd_set *exceptfds,
struct timeval *timeout)<BR>+{<BR>+&nbsp;struct pollfd *fds;<BR>+&nbsp;int
ret;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;fds =
rs_select_to_poll(&amp;nfds, readfds, writefds, exceptfds);<BR>+&nbsp;if
(!fds)<BR>+&nbsp;&nbsp;return ERR(ENOMEM);<BR>+<BR>+&nbsp;ret = rpoll(fds, nfds,
rs_convert_timeout(timeout));<BR>+<BR>+&nbsp;if
(readfds)<BR>+&nbsp;&nbsp;FD_ZERO(readfds);<BR>+&nbsp;if
(writefds)<BR>+&nbsp;&nbsp;FD_ZERO(writefds);<BR>+&nbsp;if
(exceptfds)<BR>+&nbsp;&nbsp;FD_ZERO(exceptfds);<BR>+<BR>+&nbsp;if (ret &gt;
0)<BR>+&nbsp;&nbsp;ret = rs_poll_to_select(nfds, fds, readfds, writefds,
exceptfds);<BR>+<BR>+&nbsp;free(fds);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+/*<BR>+ * For graceful disconnect, notify the remote side
that we're<BR>+ * disconnecting and wait until all outstanding sends
complete.<BR>+ */<BR>+__declspec(dllexport)<BR>+int rshutdown(int socket, int
how)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int ctrl, ret =
0;<BR>+<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;if (how == SHUT_RD)
{<BR>+&nbsp;&nbsp;rs-&gt;state &amp;= ~rs_connect_rd;<BR>+&nbsp;&nbsp;return
0;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (rs-&gt;fd_flags &amp;
O_NONBLOCK)<BR>+&nbsp;&nbsp;rs_set_nonblocking(rs, 0);<BR>+<BR>+&nbsp;if
(rs-&gt;state &amp; rs_connected) {<BR>+&nbsp;&nbsp;if (how == SHUT_RDWR)
{<BR>+&nbsp;&nbsp;&nbsp;ctrl =
RS_CTRL_DISCONNECT;<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state &amp;= ~(rs_connect_rd |
rs_connect_wr);<BR>+&nbsp;&nbsp;} else {<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;state
&amp;= ~rs_connect_wr;<BR>+&nbsp;&nbsp;&nbsp;ctrl = (rs-&gt;state &amp;
rs_connect_rd) ?<BR>+&nbsp;&nbsp;&nbsp;&nbsp;RS_CTRL_SHUTDOWN :
RS_CTRL_DISCONNECT;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;if (!rs-&gt;ctrl_avail)
{<BR>+&nbsp;&nbsp;&nbsp;ret = rs_process_cq(rs, 0,
rs_conn_can_send_ctrl);<BR>+&nbsp;&nbsp;&nbsp;if
(ret)<BR>+&nbsp;&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;&nbsp;wsa_setlasterror(errno);<BR>+&nbsp;&nbsp;&nbsp;&nbsp;return
ret;<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;if ((rs-&gt;state
&amp; rs_connected) &amp;&amp; rs-&gt;ctrl_avail)
{<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;ctrl_avail--;<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_post_write(rs, NULL, 0,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
rs_msg_set(RS_OP_CTRL, ctrl), 0, 0,
0);<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;if (rs-&gt;state &amp;
rs_connected)<BR>+&nbsp;&nbsp;rs_process_cq(rs, 0,
rs_conn_all_sends_done);<BR>+<BR>+&nbsp;if ((rs-&gt;fd_flags &amp; O_NONBLOCK)
&amp;&amp; (rs-&gt;state &amp;
rs_connected))<BR>+&nbsp;&nbsp;rs_set_nonblocking(rs, 1);<BR>+<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rclose(int
socket)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;if (rs-&gt;state &amp;
rs_connected)<BR>+&nbsp;&nbsp;rshutdown(socket,
SHUT_RDWR);<BR>+<BR>+&nbsp;rs_free(rs);<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+static void rs_copy_addr(struct sockaddr *dst, struct sockaddr
*src, socklen_t *len)<BR>+{<BR>+&nbsp;socklen_t size;<BR>+<BR>+&nbsp;if
(src-&gt;sa_family == AF_INET) {<BR>+&nbsp;&nbsp;size = min(*len, sizeof(struct
sockaddr_in));<BR>+&nbsp;&nbsp;*len = sizeof(struct sockaddr_in);<BR>+&nbsp;}
else {<BR>+&nbsp;&nbsp;size = min(*len, sizeof(struct
sockaddr_in6));<BR>+&nbsp;&nbsp;*len = sizeof(struct
sockaddr_in6);<BR>+&nbsp;}<BR>+&nbsp;memcpy(dst, src,
size);<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rgetpeername(int socket,
struct sockaddr *addr, socklen_t *addrlen)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;rs_copy_addr(addr,
rdma_get_peer_addr(rs-&gt;cm_id), addrlen);<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rgetsockname(int socket, struct
sockaddr *addr, socklen_t *addrlen)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;rs_copy_addr(addr,
rdma_get_local_addr(rs-&gt;cm_id), addrlen);<BR>+&nbsp;return
0;<BR>+}<BR>+<BR>+/*<BR>+ * Nonblocking is usually not inherited between
sockets, but we need to<BR>+ * inherit it here to establish the connection
only.&nbsp; This is needed to<BR>+ * prevent rdma_accept from blocking until the
remote side finishes<BR>+ * establishing the connection.&nbsp; If we were to
allow rdma_accept to block,<BR>+ * then a single thread cannot establish a
connection with itself, or<BR>+ * two threads which try to connect to each other
can deadlock trying to<BR>+ * form a connection.<BR>+ *<BR>+ * Data transfers on
the new socket remain blocking unless the user<BR>+ * specifies otherwise
through rfcntl.<BR>+ */<BR>+__declspec(dllexport)<BR>+int raccept(int socket,
struct sockaddr *addr, socklen_t *addrlen)<BR>+{<BR>+&nbsp;struct rsocket *rs,
*new_rs;<BR>+&nbsp;struct rdma_conn_param param;<BR>+&nbsp;struct rs_conn_data
*creq, cresp;<BR>+&nbsp;int
ret;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;new_rs = rs_alloc(rs);<BR>+&nbsp;if
(!new_rs)<BR>+&nbsp;&nbsp;return ERR(ENOMEM);<BR>+<BR>+&nbsp;ret =
rdma_get_request(rs-&gt;cm_id, &amp;new_rs-&gt;cm_id);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;ret =
rs_insert(new_rs);<BR>+&nbsp;if (ret &lt; 0)<BR>+&nbsp;&nbsp;goto
err;<BR>+<BR>+&nbsp;creq = (struct rs_conn_data *)
new_rs-&gt;cm_id-&gt;event-&gt;param.conn.private_data;<BR>+&nbsp;if
(creq-&gt;version != 1) {<BR>+&nbsp;&nbsp;ret =
ERR(ENOTSUP);<BR>+&nbsp;&nbsp;goto err;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(rs-&gt;fd_flags &amp; O_NONBLOCK)<BR>+&nbsp;&nbsp;rs_set_nonblocking(new_rs,
O_NONBLOCK);<BR>+<BR>+&nbsp;ret = rs_create_ep(new_rs);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;rs_save_conn_data(new_rs,
creq);<BR>+&nbsp;param =
new_rs-&gt;cm_id-&gt;event-&gt;param.conn;<BR>+&nbsp;rs_set_conn_data(new_rs,
&amp;param, &amp;cresp);<BR>+&nbsp;ret = rdma_accept(new_rs-&gt;cm_id,
&amp;param);<BR>+&nbsp;if (!ret)<BR>+&nbsp;&nbsp;new_rs-&gt;state =
rs_connect_rdwr;<BR>+&nbsp;else if (errno == EAGAIN || errno ==
EWOULDBLOCK)<BR>+&nbsp;&nbsp;new_rs-&gt;state =
rs_accepting;<BR>+&nbsp;else<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;if (addr
&amp;&amp; addrlen)<BR>+&nbsp;&nbsp;rgetpeername(new_rs-&gt;index, addr,
addrlen);<BR>+&nbsp;return
new_rs-&gt;index;<BR>+<BR>+err:<BR>+&nbsp;rs_free(new_rs);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+/*<BR>+ * Socket provider's variant:<BR>+ */<BR>+SOCKET
WSPAPI WSPAccept(<BR>+&nbsp;&nbsp;SOCKET&nbsp;&nbsp;&nbsp;
socket,<BR>+&nbsp;&nbsp;struct
sockaddr&nbsp;*addr,<BR>+&nbsp;&nbsp;LPINT&nbsp;&nbsp;&nbsp;
addrlen,<BR>+&nbsp;&nbsp;LPCONDITIONPROC&nbsp;
lpfnCondition,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
DWORD_PTR&nbsp;&nbsp;
dwCallbackData,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
LPINT&nbsp;&nbsp;&nbsp; lpErrno<BR>+&nbsp;)<BR>+{<BR>+&nbsp;struct rsocket *rs,
*new_rs;<BR>+&nbsp;struct rdma_conn_param param;<BR>+&nbsp;struct rs_conn_data
*creq, cresp;<BR>+&nbsp;SOCKET new_socket =
INVALID_SOCKET;<BR>+&nbsp;DWORD_PTR&nbsp;rsock =
INVALID_SOCKET;<BR>+&nbsp;int&nbsp;&nbsp;&nbsp;ret =
gMainUpCallTable.lpWPUQuerySocketHandleContext(<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(PDWORD_PTR)&amp;rsock,&nbsp;//
__out PDWORD_PTR
lpContext<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);<BR>+&nbsp;if
(SOCKET_ERROR == ret)<BR>+&nbsp;&nbsp;return
INVALID_SOCKET;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct
rsocket *)idm_at(&amp;idm, (int)rsock);<BR>+&nbsp;new_rs =
rs_alloc(rs);<BR>+&nbsp;if (!new_rs)<BR>+&nbsp;&nbsp;return
ERR(ENOMEM);<BR>+<BR>+&nbsp;ret = rdma_get_request(rs-&gt;cm_id,
&amp;new_rs-&gt;cm_id);<BR>+&nbsp;if (ret)<BR>+&nbsp;&nbsp;goto
err;<BR>+<BR>+&nbsp;ret = rs_insert(new_rs);<BR>+&nbsp;if (ret &lt;
0)<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;creq = (struct rs_conn_data *)
new_rs-&gt;cm_id-&gt;event-&gt;param.conn.private_data;<BR>+&nbsp;if
(creq-&gt;version != 1) {<BR>+&nbsp;&nbsp;ret =
ERR(ENOTSUP);<BR>+&nbsp;&nbsp;goto err;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(rs-&gt;fd_flags &amp; O_NONBLOCK)<BR>+&nbsp;&nbsp;rs_set_nonblocking(new_rs,
O_NONBLOCK);<BR>+<BR>+&nbsp;ret = rs_create_ep(new_rs);<BR>+&nbsp;if
(ret)<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;rs_save_conn_data(new_rs,
creq);<BR>+&nbsp;param =
new_rs-&gt;cm_id-&gt;event-&gt;param.conn;<BR>+&nbsp;rs_set_conn_data(new_rs,
&amp;param, &amp;cresp);<BR>+<BR>+&nbsp;if (addr &amp;&amp;
addrlen)<BR>+&nbsp;&nbsp;rgetpeername(new_rs-&gt;index, addr,
addrlen);<BR>+<BR>+&nbsp;if (lpfnCondition) {<BR>+&nbsp;&nbsp;struct sockaddr
local_addr;<BR>+&nbsp;&nbsp;socklen_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
local_addrlen = sizeof(local_addr);<BR>+&nbsp;&nbsp;WSABUF
caller_id;<BR>+&nbsp;&nbsp;WSABUF callee_id;<BR>+&nbsp;&nbsp;WSABUF
callee_data;<BR>+<BR>+&nbsp;&nbsp;/* Set the caller and callee data buffer
*/<BR>+&nbsp;&nbsp;caller_id.buf = (char *)addr;<BR>+&nbsp;&nbsp;caller_id.len =
sizeof(*addr);<BR>+<BR>+&nbsp;&nbsp;rs_copy_addr(&amp;local_addr,
rdma_get_local_addr(new_rs-&gt;cm_id),
&amp;local_addrlen);<BR>+<BR>+&nbsp;&nbsp;callee_id.buf = (char
*)&amp;local_addr;<BR>+&nbsp;&nbsp;callee_id.len =
local_addrlen;<BR>+&nbsp;&nbsp;<BR>+&nbsp;&nbsp;callee_data.buf =
NULL;<BR>+&nbsp;&nbsp;callee_data.len =
0;<BR>+<BR>+&nbsp;&nbsp;switch(lpfnCondition(&amp;caller_id, NULL, NULL, NULL,
&amp;callee_id, &amp;callee_data, NULL, dwCallbackData))
{<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;/* Should never happen
*/<BR>+&nbsp;&nbsp;&nbsp;/* Fall through. */<BR>+&nbsp;&nbsp;case
CF_REJECT:<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSAECONNREFUSED;<BR>+&nbsp;&nbsp;&nbsp;ret =
(int)INVALID_SOCKET;<BR>+&nbsp;&nbsp;&nbsp;goto err;<BR>+&nbsp;&nbsp;case
CF_DEFER:<BR>+&nbsp;&nbsp;&nbsp;*lpErrno =
WSATRY_AGAIN;<BR>+&nbsp;&nbsp;&nbsp;ret =
(int)INVALID_SOCKET;<BR>+&nbsp;&nbsp;&nbsp;goto err;<BR>+&nbsp;&nbsp;case
CF_ACCEPT:<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+&nbsp;new_socket
=
gMainUpCallTable.lpWPUCreateSocketHandle(<BR>+&nbsp;&nbsp;&nbsp;gProtocolInfo.dwCatalogEntryId,<BR>+&nbsp;&nbsp;&nbsp;new_rs-&gt;index,&nbsp;//
__in&nbsp; DWORD_PTR
dwContext<BR>+&nbsp;&nbsp;&nbsp;lpErrno<BR>+&nbsp;);<BR>+&nbsp;if
(INVALID_SOCKET == new_socket) {<BR>+&nbsp;&nbsp;//??? *lpErrno =
WSATRY_AGAIN;<BR>+&nbsp;&nbsp;goto err;<BR>+&nbsp;}<BR>+&nbsp;ret =
rdma_accept(new_rs-&gt;cm_id, &amp;param);<BR>+&nbsp;if
(!ret)<BR>+&nbsp;&nbsp;new_rs-&gt;state = rs_connect_rdwr;<BR>+&nbsp;else if
(errno == EAGAIN || errno == EWOULDBLOCK)<BR>+&nbsp;&nbsp;new_rs-&gt;state =
rs_accepting;<BR>+&nbsp;else<BR>+&nbsp;&nbsp;goto err;<BR>+<BR>+&nbsp;return
new_socket;<BR>+<BR>+err:<BR>+&nbsp;rs_free(new_rs);<BR>+&nbsp;if (new_socket !=
INVALID_SOCKET)<BR>+&nbsp;&nbsp;gMainUpCallTable.lpWPUCloseSocketHandle(new_socket,
lpErrno);<BR>+<BR>+&nbsp;return
INVALID_SOCKET;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rsetsockopt(int
socket, int level, int optname,<BR>+&nbsp;&nbsp;const void *optval, socklen_t
optlen)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int ret, opt_on =
0;<BR>+&nbsp;uint64_t *opts = NULL;<BR>+&nbsp;<BR>+&nbsp;ret =
ERR(ENOTSUP);<BR>+&nbsp;rs = (struct rsocket *)idm_at(&amp;idm,
socket);<BR>+&nbsp;switch (level) {<BR>+&nbsp;case
SOL_SOCKET:<BR>+&nbsp;&nbsp;opts = &amp;rs-&gt;so_opts;<BR>+&nbsp;&nbsp;switch
(optname) {<BR>+&nbsp;&nbsp;case SO_REUSEADDR:<BR>+&nbsp;&nbsp;&nbsp;ret =
rdma_set_option(rs-&gt;cm_id,
RDMA_OPTION_ID,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
RDMA_OPTION_ID_REUSEADDR,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(void *) optval, optlen);<BR>+&nbsp;&nbsp;&nbsp;if (ret &amp;&amp; ((errno ==
ENOSYS) || ((rs-&gt;state != rs_init)
&amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rs-&gt;cm_id-&gt;context
&amp;&amp;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(rs-&gt;cm_id-&gt;verbs-&gt;device-&gt;transport_type ==
IBV_TRANSPORT_IB))))<BR>+&nbsp;&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;opt_on = *(int *)
optval;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_RCVBUF:<BR>+&nbsp;&nbsp;&nbsp;if
(!rs-&gt;rbuf)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;rbuf_size = (*(uint32_t *)
optval) &lt;&lt; 1;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_SNDBUF:<BR>+&nbsp;&nbsp;&nbsp;if
(!rs-&gt;sbuf)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;sbuf_size = (*(uint32_t *)
optval) &lt;&lt; 1;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_LINGER:<BR>+&nbsp;&nbsp;&nbsp;/* Invert value so default so_opt = 0 is on
*/<BR>+&nbsp;&nbsp;&nbsp;opt_on =&nbsp; !((struct linger *)
optval)-&gt;l_onoff;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_KEEPALIVE:<BR>+&nbsp;&nbsp;&nbsp;opt_on = *(int *)
optval;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_OOBINLINE:<BR>+&nbsp;&nbsp;&nbsp;opt_on = *(int *)
optval;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
IPPROTO_TCP:<BR>+&nbsp;&nbsp;opts = &amp;rs-&gt;tcp_opts;<BR>+&nbsp;&nbsp;switch
(optname) {<BR>+&nbsp;&nbsp;case TCP_NODELAY:<BR>+&nbsp;&nbsp;&nbsp;opt_on =
*(int *) optval;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
TCP_MAXSEG:<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
IPPROTO_IPV6:<BR>+&nbsp;&nbsp;opts =
&amp;rs-&gt;ipv6_opts;<BR>+&nbsp;&nbsp;switch (optname) {<BR>+&nbsp;&nbsp;case
IPV6_V6ONLY:<BR>+&nbsp;&nbsp;&nbsp;ret = rdma_set_option(rs-&gt;cm_id,
RDMA_OPTION_ID,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
RDMA_OPTION_ID_AFONLY,<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
(void *) optval, optlen);<BR>+&nbsp;&nbsp;&nbsp;opt_on = *(int *)
optval;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;case
SOL_RDMA:<BR>+&nbsp;&nbsp;if (rs-&gt;state &gt;= rs_opening)
{<BR>+&nbsp;&nbsp;&nbsp;ret =
ERR(EINVAL);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+<BR>+&nbsp;&nbsp;switch
(optname) {<BR>+&nbsp;&nbsp;case
RDMA_SQSIZE:<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;sq_size = min((*(uint32_t *) optval),
RS_QP_MAX_SIZE);<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
RDMA_RQSIZE:<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;rq_size = min((*(uint32_t *) optval),
RS_QP_MAX_SIZE);<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
RDMA_INLINE:<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;sq_inline = min(*(uint32_t *) optval,
RS_QP_MAX_SIZE);<BR>+&nbsp;&nbsp;&nbsp;if (rs-&gt;sq_inline &lt;
RS_MIN_INLINE)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;sq_inline =
RS_MIN_INLINE;<BR>+&nbsp;&nbsp;&nbsp;ret =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+<BR>+&nbsp;if
(!ret &amp;&amp; opts) {<BR>+&nbsp;&nbsp;if (opt_on)<BR>+&nbsp;&nbsp;&nbsp;*opts
|= (uint64_t)(1 &lt;&lt;
optname);<BR>+&nbsp;&nbsp;else<BR>+&nbsp;&nbsp;&nbsp;*opts &amp;= ~(1 &lt;&lt;
optname);<BR>+&nbsp;}<BR>+<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rgetsockopt(int socket, int
level, int optname,<BR>+&nbsp;&nbsp;void *optval, socklen_t
*optlen)<BR>+{<BR>+&nbsp;struct rsocket *rs;<BR>+&nbsp;int ret =
0;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;switch (level) {<BR>+&nbsp;case
SOL_SOCKET:<BR>+&nbsp;&nbsp;switch (optname) {<BR>+&nbsp;&nbsp;case
SO_REUSEADDR:<BR>+&nbsp;&nbsp;case SO_KEEPALIVE:<BR>+&nbsp;&nbsp;case
SO_OOBINLINE:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) = !!(rs-&gt;so_opts &amp;
(uint64_t)(1 &lt;&lt; optname));<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_RCVBUF:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;rbuf_size;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_SNDBUF:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;sbuf_size;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_LINGER:<BR>+&nbsp;&nbsp;&nbsp;/* Value is inverted so default so_opt = 0 is
on */<BR>+&nbsp;&nbsp;&nbsp;((struct linger *) optval)-&gt;l_onoff
=<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!(rs-&gt;so_opts &amp; (uint64_t)(1 &lt;&lt;
optname));<BR>+&nbsp;&nbsp;&nbsp;((struct linger *) optval)-&gt;l_linger =
0;<BR>+&nbsp;&nbsp;&nbsp;*optlen = sizeof(struct
linger);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
SO_ERROR:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;err;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;err =
0;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;ret
=
ENOTSUP;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
IPPROTO_TCP:<BR>+&nbsp;&nbsp;switch (optname) {<BR>+&nbsp;&nbsp;case
TCP_NODELAY:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) = !!(rs-&gt;tcp_opts &amp;
(uint64_t)(1 &lt;&lt; optname));<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
TCP_MAXSEG:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) = (rs-&gt;cm_id &amp;&amp;
rs-&gt;cm_id-&gt;route.num_paths)
?<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 &lt;&lt; (7 +
rs-&gt;cm_id-&gt;route.path_rec-&gt;mtu)
:<BR>+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
2048;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;ret
=
ENOTSUP;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
IPPROTO_IPV6:<BR>+&nbsp;&nbsp;switch (optname) {<BR>+&nbsp;&nbsp;case
IPV6_V6ONLY:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) = !!(rs-&gt;ipv6_opts &amp;
(uint64_t)(1 &lt;&lt; optname));<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;ret
=
ENOTSUP;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;case
SOL_RDMA:<BR>+&nbsp;&nbsp;switch (optname) {<BR>+&nbsp;&nbsp;case
RDMA_SQSIZE:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;sq_size;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
RDMA_RQSIZE:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;rq_size;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;case
RDMA_INLINE:<BR>+&nbsp;&nbsp;&nbsp;*((int *) optval) =
rs-&gt;sq_inline;<BR>+&nbsp;&nbsp;&nbsp;*optlen =
sizeof(int);<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;ret
=
ENOTSUP;<BR>+&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;ret
= ENOTSUP;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;}<BR>+<BR>+&nbsp;return
ERR/*rdma_seterrno*/(ret);<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int
rfcntl(int socket, int cmd, ... /* arg */ )<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;va_list args;<BR>+&nbsp;long param;<BR>+&nbsp;int ret =
0;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;va_start(args, cmd);<BR>+&nbsp;switch
(cmd) {<BR>+&nbsp;case F_GETFL:<BR>+&nbsp;&nbsp;return (int)
rs-&gt;fd_flags;<BR>+&nbsp;case F_SETFL:<BR>+&nbsp;&nbsp;param = va_arg(args,
long);<BR>+&nbsp;&nbsp;if (param &amp; O_NONBLOCK)<BR>+&nbsp;&nbsp;&nbsp;ret =
rs_set_nonblocking(rs, O_NONBLOCK);<BR>+<BR>+&nbsp;&nbsp;if
(!ret)<BR>+&nbsp;&nbsp;&nbsp;rs-&gt;fd_flags |=
param;<BR>+&nbsp;&nbsp;break;<BR>+&nbsp;default:<BR>+&nbsp;&nbsp;ret =
ERR(ENOTSUP);<BR>+&nbsp;}<BR>+&nbsp;va_end(args);<BR>+&nbsp;return
ret;<BR>+}<BR>+<BR>+__declspec(dllexport)<BR>+int rioctlsocket(int socket, long
cmd, u_long* argp)<BR>+{<BR>+&nbsp;struct rsocket
*rs;<BR>+&nbsp;<BR>+&nbsp;wsa_setlasterror(0);<BR>+&nbsp;rs = (struct rsocket
*)idm_at(&amp;idm, socket);<BR>+&nbsp;switch (cmd) {<BR>+&nbsp;&nbsp;case
FIONBIO:<BR>+&nbsp;&nbsp;&nbsp;if
(*argp)<BR>+&nbsp;&nbsp;&nbsp;&nbsp;rs-&gt;fd_flags |=
O_NONBLOCK;<BR>+&nbsp;&nbsp;&nbsp;return rs_set_nonblocking(rs, *argp ?
O_NONBLOCK : 0);<BR>+&nbsp;&nbsp;case FIONREAD:<BR>+&nbsp;&nbsp;case
SIOCATMARK:<BR>+&nbsp;&nbsp;&nbsp;return
ERR(ENOTSUP);<BR>+&nbsp;&nbsp;default:<BR>+&nbsp;&nbsp;&nbsp;return
ERR(ENOTSUP);<BR>+&nbsp;}<BR>+}<BR>+<BR>+/**<BR>+ *
\brief&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get current RSockets status information for
the calling process<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(by calling
librdmacm.dll directly).<BR>+ *<BR>+ * \param lppStatusBuffer&nbsp;Pointer to a
buffer with an array of RS_STATUS information entries<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to be allocated and returned. The
caller is responsible for<BR>+
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;deallocating that buffer via free()
when it is no longer needed.<BR>+ *<BR>+ *
\return&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The number of RS_STATUS entries contained
in the status buffer<BR>+ *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;returned by
*lppStatusBuffer.<BR>+ */<BR>+int rsGetStatus ( __out LPRS_STATUS
*lppStatusBuffer )<BR>+{<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;i,
e;<BR>+&nbsp;DWORD&nbsp;&nbsp;&nbsp;dwNumEntries = 0;<BR>+&nbsp;struct
rsocket&nbsp;*rs;<BR>+&nbsp;char&nbsp;&nbsp;&nbsp;*pst = "";<BR>+<BR>+&nbsp;for
(i = 0; i &lt; IDX_MAX_INDEX; i++)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;if
(idm_lookup(&amp;idm,
i))<BR>+&nbsp;&nbsp;&nbsp;dwNumEntries++;<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;if
(&nbsp;&nbsp; 0 == dwNumEntries ||<BR>+&nbsp;&nbsp;&nbsp;&nbsp; NULL ==
(*lppStatusBuffer = (LPRS_STATUS)malloc(dwNumEntries *
sizeof(**lppStatusBuffer)))<BR>+&nbsp;&nbsp;&nbsp;
)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;return 0;<BR>+&nbsp;}<BR>+&nbsp;<BR>+&nbsp;for
(<BR>+&nbsp;&nbsp;&nbsp;i = 0, e = 0;<BR>+&nbsp;&nbsp;&nbsp;i &lt; IDX_MAX_INDEX
&amp;&amp; e &lt;
dwNumEntries;<BR>+&nbsp;&nbsp;&nbsp;i++<BR>+&nbsp;&nbsp;)<BR>+&nbsp;{<BR>+&nbsp;&nbsp;if
(rs = (struct rsocket *)idm_lookup(&amp;idm,
i))<BR>+&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;lppStatusBuffer[e]-&gt;src_addr =
rs-&gt;cm_id-&gt;route.addr.src_addr;<BR>+&nbsp;&nbsp;&nbsp;lppStatusBuffer[e]-&gt;dst_addr
= rs-&gt;cm_id-&gt;route.addr.dst_addr;<BR>+&nbsp;&nbsp;&nbsp;switch
(rs-&gt;state)<BR>+&nbsp;&nbsp;&nbsp;{<BR>+&nbsp;&nbsp;&nbsp;case
rs_init:&nbsp;&nbsp;&nbsp;pst =
"INIT";&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_bound:&nbsp;&nbsp;&nbsp;pst =
"BOUND";&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_listening:&nbsp;&nbsp;pst =
"LISTENING";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_opening:&nbsp;&nbsp;pst =
"OPENING";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_resolving_addr:&nbsp;pst =
"RESOLVING_ADDR";&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case rs_resolving_route:pst
= "RESOLVING_ROUTE";break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connecting:&nbsp;&nbsp;pst =
"CONNECTING";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_accepting:&nbsp;&nbsp;pst =
"ACCEPTING";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connected:&nbsp;&nbsp;pst =
"CONNECTED";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connect_wr:&nbsp;&nbsp;pst =
"CONNECT_WR";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connect_rd:&nbsp;&nbsp;pst =
"CONNECT_RD";&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connect_rdwr:&nbsp;pst =
"CONNECT_RDWR";&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_connect_error:&nbsp;pst =
"CONNECT_ERROR";&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_disconnected:&nbsp;pst =
"DISCONNECTED";&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;case
rs_error:&nbsp;&nbsp;&nbsp;pst =
"ERROR";&nbsp;&nbsp;&nbsp;break;<BR>+&nbsp;&nbsp;&nbsp;default:&nbsp;&nbsp;&nbsp;&nbsp;pst
=
"UNKNOWN";<BR>+&nbsp;&nbsp;&nbsp;}<BR>+&nbsp;&nbsp;&nbsp;strncpy(lppStatusBuffer[e]-&gt;state,
pst, sizeof(lppStatusBuffer[e]-&gt;state) -
1);<BR>+&nbsp;&nbsp;&nbsp;lppStatusBuffer[e]-&gt;state[sizeof(lppStatusBuffer[e]-&gt;state)]
=
'\0';<BR>+&nbsp;&nbsp;&nbsp;e++;<BR>+&nbsp;&nbsp;}<BR>+&nbsp;}<BR>+<BR>+&nbsp;return
e;<BR>+}<BR>Index:
ulp/librdmacm/src/Sources<BR>===================================================================<BR>---
ulp/librdmacm/src/Sources&nbsp;(revision 3419)<BR>+++
ulp/librdmacm/src/Sources&nbsp;(working copy)<BR>@@ -12,10 +12,12
@@<BR>&nbsp;&nbsp;cma.rc&nbsp;&nbsp;&nbsp;\<BR>&nbsp;&nbsp;cma_main.cpp&nbsp;\<BR>&nbsp;&nbsp;cma.cpp&nbsp;&nbsp;&nbsp;\<BR>-&nbsp;addrinfo.cpp<BR>+&nbsp;addrinfo.cpp&nbsp;\<BR>+&nbsp;rsocket.cpp&nbsp;&nbsp;\<BR>+&nbsp;indexer.cpp<BR>&nbsp;<BR>&nbsp;INCLUDES
=
..\include;..\..\..\inc;..\..\..\inc\user;..\..\libibverbs\include;\<BR>-&nbsp;&nbsp;&nbsp;&nbsp;
..\..\..\inc\user\linux;<BR>+&nbsp;&nbsp;&nbsp;&nbsp;
..\..\..\inc\user\linux<BR>&nbsp;<BR>&nbsp;USER_C_FLAGS = $(USER_C_FLAGS)
-DEXPORT_CMA_SYMBOLS<BR>&nbsp;<BR>@@ -26,4 +28,5
@@<BR>&nbsp;&nbsp;$(SDK_LIB_PATH)\iphlpapi.lib&nbsp;\<BR>&nbsp;&nbsp;$(TARGETPATH)\*\ibat.lib&nbsp;&nbsp;\<BR>&nbsp;&nbsp;$(TARGETPATH)\*\libibverbs.lib&nbsp;\<BR>-&nbsp;$(TARGETPATH)\*\winverbs.lib<BR>+&nbsp;$(TARGETPATH)\*\winverbs.lib&nbsp;&nbsp;&nbsp;
\<BR>+&nbsp;$(TARGETPATH)\*\complib.lib<BR></DIV></SPAN></FONT></DIV><br clear=all> This message and attachment(s) are intended solely for use by the addressee and may contain information that is privileged, confidential or otherwise exempt from disclosure under applicable law.

If you are not the intended recipient or agent thereof responsible for delivering this message to the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited.

If you have received this communication in error, please notify the sender immediately by telephone and with a 'reply' message.

Thank you for your co-operation.
</BODY></HTML>


------_=_NextPart_002_01CDEF18.1141EC2A--

------_=_NextPart_001_01CDEF18.1141EC2A
Content-Type: application/x-zip-compressed; name="RSocket.zip"
Content-Transfer-Encoding: base64
Content-Description: RSocket.zip
Content-Disposition: attachment; filename="RSocket.zip"

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
AAAARKYAAAAA


------_=_NextPart_001_01CDEF18.1141EC2A--

Loading...