有人使用 RDMA_CM 库进行过 RDMA 编程吗?
我很难找到即使是简单的例子来研究。librdmacm 中有一个 rdma_client 和 rdma_server 示例,但它不会在循环中运行(rping 会循环,但它是直接使用 IB 动词而不是 rdma_cm 函数编写的)。
我已经编写了一个简单的乒乓球程序,但它在 1-100 次反弹后锁定在任何地方。我发现在客户端内添加睡眠会使其在挂起之前工作更长时间,这表明存在竞争条件。
客户端卡在 rdma_get_send_comp() 中,服务器卡在 rdma_get_recv_comp() 中。
我有限的理解是,在每个 rdma_post_send() 之前,您需要发出一个 rdma_post_recv() 将在发送之后发出。同样在每次发送之前(第一个客户端发送除外),您需要等待一条消息(rdma_get_recv()),表明对方已准备好接收。
有什么问题?
Server(rdma_cm_id *id)
{
ibv_wc wc;
int ret;
uint8_t recvBuffer[MESSAGE_BUFFER_SIZE],
sendBuffer[MESSAGE_BUFFER_SIZE];
ibv_mr *recvMemRegion = rdma_reg_msgs(id, recvBuffer, MESSAGE_BUFFER_SIZE);
if (!recvMemRegion)
throw 0;
ibv_mr *sendMemRegion = rdma_reg_msgs(id, sendBuffer, MESSAGE_BUFFER_SIZE);
if (!sendMemRegion)
throw 0;
if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
throw 0;
if (ret = rdma_accept(id, NULL))
throw 0;
do
{
if ((ret = rdma_get_recv_comp(id, &wc)) <= 0)
throw 0;
if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
throw 0;
if (ret = rdma_post_send(id, NULL, sendBuffer, 1, sendMemRegion, 0))
throw 0;
printf(".");
fflush(stdout);
if ((ret = rdma_get_send_comp(id, &wc)) <= 0)
throw 0;
}
while (true);
}
Client() // sends the 1st message
{
// queue-pair parameters are:
attr.cap.max_send_wr = attr.cap.max_recv_wr = 4;
attr.cap.max_send_sge = attr.cap.max_recv_sge = 2;
attr.cap.max_inline_data = 16;
attr.qp_context = id;
attr.sq_sig_all = 1;
attr.qp_type = IBV_QPT_RC;
<create connection boiler plate>
uint8_t recvBuffer[MESSAGE_BUFFER_SIZE],
sendBuffer[MESSAGE_BUFFER_SIZE];
recvMemRegion = rdma_reg_msgs(id, recvBuffer, MESSAGE_BUFFER_SIZE);
if (!recvMemRegion)
throw 0;
sendMemRegion = rdma_reg_msgs(id, sendBuffer, MESSAGE_BUFFER_SIZE);
if (!sendMemRegion)
throw 0;
if (ret = rdma_connect(id, NULL))
throw 0;
do
{
if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
throw 0;
//usleep(5000);
if (ret = rdma_post_send(id, NULL, sendBuffer, 1, sendMemRegion, 0))
throw 0;
if ((ret = rdma_get_send_comp(id, &wc)) <= 0)
throw 0;
if ((ret = rdma_get_recv_comp(id, &wc)) <= 0)
throw 0;
printf(".");
fflush(stdout);
}
while (true);
}