enum rdma_port_space\r
{\r
RDMA_PS_IPOIB = 0x0002,\r
+ RDMA_PS_IB = 0x0003,\r
RDMA_PS_TCP = 0x0106,\r
RDMA_PS_UDP = 0x0111,\r
};\r
\r
+#define RDMA_IB_IP_PS_MASK 0xFFFFFFFFFFFF0000ULL\r
+#define RDMA_IB_IP_PORT_MASK 0x000000000000FFFFULL\r
+#define RDMA_IB_IP_PS_TCP 0x0000000001060000ULL\r
+#define RDMA_IB_IP_PS_UDP 0x0000000001110000ULL\r
+\r
/*\r
* Global qkey value for UDP QPs and multicast groups created via the \r
* RDMA CM.\r
*/\r
#define RDMA_UDP_QKEY 0x01234567\r
\r
-struct ib_addr\r
+struct rdma_ib_addr\r
{\r
union ibv_gid sgid;\r
union ibv_gid dgid;\r
sizeof(struct sockaddr)];\r
union\r
{\r
- struct ib_addr ibaddr;\r
+ struct rdma_ib_addr ibaddr;\r
} addr;\r
};\r
\r
IWVConnectEndpoint *connect;\r
IWVDatagramEndpoint *datagram;\r
} ep;\r
+\r
+ struct rdma_cm_event *event;\r
+ struct ibv_comp_channel *send_cq_channel;\r
+ struct ibv_cq *send_cq;\r
+ struct ibv_comp_channel *recv_cq_channel;\r
+ struct ibv_cq *recv_cq;\r
+};\r
+\r
+enum {\r
+ RDMA_MAX_RESP_RES = 0xFF,\r
+ RDMA_MAX_INIT_DEPTH = 0xFF\r
};\r
\r
struct rdma_conn_param\r
} param;\r
};\r
\r
+#define RAI_PASSIVE 0x00000001\r
+\r
+struct rdma_addrinfo {\r
+ int ai_flags;\r
+ int ai_family;\r
+ int ai_qp_type;\r
+ int ai_port_space;\r
+ socklen_t ai_src_len;\r
+ socklen_t ai_dst_len;\r
+ struct sockaddr *ai_src_addr;\r
+ struct sockaddr *ai_dst_addr;\r
+ char *ai_src_canonname;\r
+ char *ai_dst_canonname;\r
+ size_t ai_route_len;\r
+ void *ai_route;\r
+ size_t ai_connect_len;\r
+ void *ai_connect;\r
+ struct rdma_addrinfo *ai_next;\r
+};\r
+\r
/**\r
* rdma_create_event_channel - Open a channel used to report communication events.\r
* Description:\r
struct rdma_cm_id **id, void *context,\r
enum rdma_port_space ps);\r
\r
+/**\r
+ * rdma_create_ep - Allocate a communication identifier and qp.\r
+ * @id: A reference where the allocated communication identifier will be\r
+ * returned.\r
+ * @res: Result from rdma_getaddrinfo, which specifies the source and\r
+ * destination addresses, plus optional routing and connection information.\r
+ * @pd: Optional protection domain. This parameter is ignored if qp_init_attr\r
+ * is NULL.\r
+ * @qp_init_attr: Optional attributes for a QP created on the rdma_cm_id.\r
+ * Description:\r
+ * Create an identifier and option QP used for communication.\r
+ * Notes:\r
+ * If qp_init_attr is provided, then a queue pair will be allocated and\r
+ * associated with the rdma_cm_id. If a pd is provided, the QP will be\r
+ * created on that PD. Otherwise, the QP will be allocated on a default\r
+ * PD.\r
+ * The rdma_cm_id will be set to use synchronous operations (connect,\r
+ * listen, and get_request). To convert to asynchronous operation, the\r
+ * rdma_cm_id should be migrated to a user allocated event channel.\r
+ * See also:\r
+ * rdma_create_id, rdma_create_qp, rdma_migrate_id, rdma_connect,\r
+ * rdma_listen\r
+ */\r
+int rdma_create_ep(struct rdma_cm_id **id, struct rdma_addrinfo *res,\r
+ struct ibv_pd *pd, struct ibv_qp_init_attr *qp_init_attr);\r
+\r
+/**\r
+ * rdma_destroy_ep - Deallocates a communication identifier and qp.\r
+ * @id: The communication identifer to destroy.\r
+ * Description:\r
+ * Destroys the specified rdma_cm_id and any associated QP created\r
+ * on that id.\r
+ * See also:\r
+ * rdma_create_ep\r
+ */\r
+void rdma_destroy_ep(struct rdma_cm_id *id);\r
+\r
/**\r
* rdma_destroy_id - Release a communication identifier.\r
* @id: The communication identifier to destroy.\r
#include <iphlpapi.h>\r
\r
#include <rdma/rdma_cma.h>\r
+#include <rdma/rdma_verbs.h>\r
#include <infiniband/verbs.h>\r
#include <_errno.h>\r
#include <comp_channel.h>\r
struct rdma_cm_id id;\r
enum cma_state state;\r
struct cma_device *cma_dev;\r
+ int sync;\r
int backlog;\r
int index;\r
volatile LONG refcnt;\r
struct cma_device\r
{\r
struct ibv_context *verbs;\r
+ struct ibv_pd *pd;\r
uint64_t guid;\r
int port_cnt;\r
uint8_t max_initiator_depth;\r
RtlZeroMemory(id_priv, sizeof(struct cma_id_private));\r
id_priv->refcnt = 1;\r
id_priv->id.context = context;\r
- id_priv->id.channel = channel;\r
+\r
+ if (!channel) {\r
+ id_priv->id.channel = rdma_create_event_channel();\r
+ if (!id_priv->id.channel) {\r
+ goto err2;\r
+ }\r
+ id_priv->sync = 1;\r
+ } else {\r
+ id_priv->id.channel = channel;\r
+ }\r
id_priv->id.ps = ps;\r
- CompEntryInit(&channel->channel, &id_priv->id.comp_entry);\r
+ CompEntryInit(&id_priv->id.channel->channel, &id_priv->id.comp_entry);\r
\r
if (ps == RDMA_PS_TCP) {\r
hr = windata.prov->CreateConnectEndpoint(&id_priv->id.ep.connect);\r
id_priv->id.ep.datagram->Release();\r
}\r
\r
+ if (id->event) {\r
+ rdma_ack_cm_event(id->event);\r
+ }\r
InterlockedDecrement(&id_priv->refcnt);\r
while (id_priv->refcnt) {\r
Sleep(0);\r
}\r
+ if (id_priv->sync) {\r
+ rdma_destroy_event_channel(id->channel);\r
+ }\r
delete id_priv;\r
ucma_release();\r
return 0;\r
return ret;\r
}\r
\r
+static int ucma_complete(struct cma_id_private *id_priv)\r
+{\r
+ int ret;\r
+\r
+ if (!id_priv->sync) {\r
+ return 0;\r
+ }\r
+\r
+ if (id_priv->id.event) {\r
+ rdma_ack_cm_event(id_priv->id.event);\r
+ id_priv->id.event = NULL;\r
+ }\r
+\r
+ ret = rdma_get_cm_event(id_priv->id.channel, &id_priv->id.event);\r
+ if (ret) {\r
+ return ret;\r
+ }\r
+\r
+ return id_priv->id.event->status;\r
+}\r
+\r
__declspec(dllexport)\r
int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,\r
struct sockaddr *dst_addr, int timeout_ms)\r
\r
id_priv->refcnt++;\r
CompEntryPost(&id->comp_entry);\r
- return 0;\r
+ return ucma_complete(id_priv);\r
}\r
\r
__declspec(dllexport)\r
\r
id_priv->refcnt++;\r
CompEntryPost(&id->comp_entry);\r
- return 0;\r
+ return ucma_complete(id_priv);\r
}\r
\r
static int ucma_modify_qp_init(struct cma_id_private *id_priv, struct ibv_qp *qp)\r
return ibvw_wv_errno(hr);\r
}\r
\r
- return 0;\r
+ return ucma_complete(id_priv);\r
}\r
\r
static int ucma_get_request(struct cma_id_private *listen, int index)\r
return ibvw_wv_errno(hr);\r
}\r
\r
- return 0;\r
+ return ucma_complete(id_priv);\r
}\r
\r
__declspec(dllexport)\r
return ibvw_wv_errno(hr);\r
}\r
\r
- return 0;\r
+ return ucma_complete(id_priv);\r
}\r
\r
__declspec(dllexport)\r
\r
ucma_get_request(listen, id_priv->index);\r
\r
- if (!event->event.status) {\r
- event->event.status = ucma_query_connect(&id_priv->id,\r
- &event->event.param.conn);\r
+ if (event->event.status) {\r
+ goto err;\r
}\r
\r
- if (!event->event.status) {\r
- event->event.event = RDMA_CM_EVENT_CONNECT_REQUEST;\r
- id_priv->state = cma_passive_connect;\r
- event->event.listen_id = &listen->id;\r
- } else {\r
- InterlockedDecrement(&listen->refcnt);\r
- InterlockedDecrement(&id_priv->refcnt);\r
- rdma_destroy_id(&id_priv->id);\r
+ if (listen->sync) {\r
+ event->event.status = rdma_migrate_id(&id_priv->id, NULL);\r
+ if (event->event.status) {\r
+ goto err;\r
+ }\r
+ }\r
+\r
+ event->event.status = ucma_query_connect(&id_priv->id,\r
+ &event->event.param.conn);\r
+ if (event->event.status) {\r
+ goto err;\r
}\r
\r
+ event->event.event = RDMA_CM_EVENT_CONNECT_REQUEST;\r
+ id_priv->state = cma_passive_connect;\r
+ event->event.listen_id = &listen->id;\r
+\r
+ return 0;\r
+\r
+err:\r
+ InterlockedDecrement(&listen->refcnt);\r
+ InterlockedDecrement(&id_priv->refcnt);\r
+ rdma_destroy_id(&id_priv->id);\r
return event->event.status;\r
}\r
\r
int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,\r
void *context)\r
{\r
- _set_errno(ENOSYS);\r
- return -1;\r
+ return rdma_seterrno(ENOSYS);\r
}\r
\r
__declspec(dllexport)\r
int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)\r
{\r
- _set_errno(ENOSYS);\r
- return -1;\r
+ return rdma_seterrno(ENOSYS);\r
}\r
\r
__declspec(dllexport)\r
int rdma_set_option(struct rdma_cm_id *id, int level, int optname,\r
void *optval, size_t optlen)\r
{\r
- _set_errno(ENOSYS);\r
- return -1;\r
+ return rdma_seterrno(ENOSYS);\r
}\r
\r
__declspec(dllexport)\r
int rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel)\r
{\r
+ struct cma_id_private *id_priv;\r
+ int sync;\r
+\r
+ id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+ if (id_priv->sync && !channel) {\r
+ return rdma_seterror(EINVAL);\r
+ }\r
+\r
+ if (id->comp_entry.Busy) {\r
+ return rdma_seterrno(EBUSY);\r
+ }\r
+\r
+ if ((sync = (channel == NULL))) {\r
+ channel = rdma_create_event_channel();\r
+ if (!channel) {\r
+ return rdma_seterror(ENOMEM);\r
+ }\r
+ }\r
+\r
+ if (id_priv->sync) {\r
+ if (id->event) {\r
+ rdma_ack_cm_event(id->event);\r
+ id->event = NULL;\r
+ }\r
+ rdma_destroy_event_channel(id->channel);\r
+ }\r
+\r
+ id_priv->sync = sync;\r
id->channel = channel;\r
+ id->comp_entry.Channel = channel->channel;\r
return 0;\r
}\r
\r