RDMA连接的建立
rdma_resolve_addr用于将给定的目标 IP 地址映射到可用的 RDMA 地址
/* struct sockaddr_in *s_addr 代表ip地址 */
static struct rdma_event_channel *cm_event_channel = NULL;
static struct rdma_cm_id *cm_client_id = NULL;
/* 打开用于报告通信事件的事件通道。通过事件通道向用户报告异步事件 */
cm_event_channel = rdma_create_event_channel();
/* rdma_cm_ids 在概念上等同于 RDMA 通信的套接字。不同之处在于 RDMA 通信需
要在通信发生之前明确绑定到指定的 RDMA 设备,并且大多数操作本质上是异步的。*/
rdma_create_id(cm_event_channel, &cm_client_id,
NULL,
RDMA_PS_TCP);
rdma_resolve_addr(cm_client_id, NULL, (struct sockaddr*) s_addr, 2000);
rdma_resolve_route用于将rdma地址解析为路由
struct rdma_cm_event *cm_event = NULL;
/* 等待channel上发生事件: RDMA_CM_EVENT_ADDR_RESOLVED */
process_rdma_cm_event(cm_event_channel,
RDMA_CM_EVENT_ADDR_RESOLVED,
&cm_event);
/* 接受事件(在接受事件之前应该通过process_rdma_cn_event返回的结果判断此事件是否确实发生了) */
rdma_ack_cm_event(cm_event);
/* 将目标RDMA地址解析为路由 */
rdma_resolve_route(cm_client_id, 2000);
/* 等待事件: RDMA_CM_EVENT_ROUTE_RESOLVED */
process_rdma_cm_event(cm_event_channel,
RDMA_CM_EVENT_ROUTE_RESOLVED,
&cm_event);
rdma_ack_cm_event(cm_event);
在建立连接之前还需要初始化其他资源
/* All resources are tied to a particular PD.
* And accessing recourses across PD will result in a protection fault. */
pd = ibv_alloc_pd(cm_client_id->verbs);
/* Now we need a completion channel, were the I/O completion
* notifications are sent. Remember, this is different from connection
* management (CM) event notifications.
* A completion channel is also tied to an RDMA device, hence we will
* use cm_client_id->verbs. */
io_completion_channel = ibv_create_comp_channel(cm_client_id->verbs);
/* Now we create a completion queue (CQ) where actual I/O
* completion metadata is placed. The metadata is packed into a structure
* called struct ibv_wc (wc = work completion). ibv_wc has detailed
* information about the work completion. An I/O request in RDMA world
* is called "work" ;)
*/
client_cq = ibv_create_cq(cm_client_id->verbs /* which device*/,
CQ_CAPACITY /* maximum capacity*/,
NULL /* user context, not used here */,
io_completion_channel /* which IO completion channel */,
0 /* signaling vector, not used here*/);
/* 为cq提供通知机制 */
ibv_req_notify_cq(client_cq, 0);
/* create a qp with initial args qp_init_attr*/
rdma_create_qp(cm_client_id /* which connection id */,
pd /* which protection domain*/,
&qp_init_attr /* Initial attributes */);
client_qp = cm_client_id.qp;