库函数、全局变量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <getopt.h>
#include <rdma/rdma_cma.h>
#include <rdma/rdma_verbs.h>
static const char *server = "127.0.0.1"; // ip地址
static const char *port = "7471"; // 端口信息(这个端口是标准的soft-core)
static struct rdma_cm_id *id; // cm管理器描述符
static struct ibv_mr *mr, *send_mr; // 注册的mr信息
static int send_flags; // 发送的标识符
static uint8_t send_msg[16]; // 发送消息的大小
static uint8_t recv_msg[16]; // 接收消息的大小
main函数
首先分析相关的命令参数,开始运行run函数。
int main(int argc, char **argv)
{
int op, ret;
while ((op = getopt(argc, argv, "s:p:")) != -1) {
switch (op) {
case 's':
server = optarg;
break;
case 'p':
port = optarg;
break;
default:
printf("usage: %s\n", argv[0]);
printf("\t[-s server_address]\n");
printf("\t[-p port_number]\n");
exit(1);
}
}
printf("rdma_client: start\n");
ret = run();
printf("rdma_client: end %d\n", ret);
return ret;
}
run函数
static int run(void)
{
struct rdma_addrinfo hints, *res; // rdma地址信息存储
struct ibv_qp_init_attr attr; // qp的属性,里面存储了qp的信息,以及上下文嘻嘻等
struct ibv_wc wc; // wc表示的是完成事件
int ret;
memset(&hints, 0, sizeof hints);
hints.ai_port_space = RDMA_PS_TCP; // 使用TCP的方式建立连接
ret = rdma_getaddrinfo(server, port, &hints, &res); // 验证服务器地址和端口的有效性
if (ret) {
printf("rdma_getaddrinfo: %s\n", gai_strerror(ret));
goto out;
}
// 表示配置qp信息
memset(&attr, 0, sizeof attr);
attr.cap.max_send_wr = attr.cap.max_recv_wr = 1;
attr.cap.max_send_sge = attr.cap.max_recv_sge = 1;
attr.cap.max_inline_data = 16;
attr.qp_context = id;
attr.sq_sig_all = 1;
ret = rdma_create_ep(&id, res, NULL, &attr); // 创建一个终端节点,这个终端节点里面包含了所有的信息。
// Check to see if we got inline data allowed or not
if (attr.cap.max_inline_data >= 16) // 这个表示我们当前支持IBV_SEND_INLINE
send_flags = IBV_SEND_INLINE;
else
printf("rdma_client: device doesn't support IBV_SEND_INLINE, "
"using sge sends\n");
if (ret) {
perror("rdma_create_ep");
goto out_free_addrinfo;
}
mr = rdma_reg_msgs(id, recv_msg, 16); // 创建mr信息,并且把相关的recv_msg和相关的信息存储在mr里面。
if (!mr) {
perror("rdma_reg_msgs for recv_msg");
ret = -1;
goto out_destroy_ep;
}
if ((send_flags & IBV_SEND_INLINE) == 0) {
send_mr = rdma_reg_msgs(id, send_msg, 16); // 创建一个send_mr用于发送数据。
if (!send_mr) {
perror("rdma_reg_msgs for send_msg");
ret = -1;
goto out_dereg_recv;
}
}
ret = rdma_post_recv(id, NULL, recv_msg, 16, mr); // 发送一个WR到RQ队列中,把数据的接收存放到mr里面。
if (ret) {
perror("rdma_post_recv");
goto out_dereg_send;
}
ret = rdma_connect(id, NULL); // 发起连接的建立
if (ret) {
perror("rdma_connect");
goto out_dereg_send;
}
// 同理一样,这个用于发送,从send_mr发送数据出去
ret = rdma_post_send(id, NULL, send_msg, 16, send_mr, send_flags);
if (ret) {
perror("rdma_post_send");
goto out_disconnect;
}
// 检查是否发送成功
while ((ret = rdma_get_send_comp(id, &wc)) == 0);
if (ret < 0) {
perror("rdma_get_send_comp");
goto out_disconnect;
}
// 检查是否接收成
while ((ret = rdma_get_recv_comp(id, &wc)) == 0);
if (ret < 0)
perror("rdma_get_recv_comp");
else
ret = 0;
out_disconnect:
rdma_disconnect(id);
out_dereg_send:
if ((send_flags & IBV_SEND_INLINE) == 0)
rdma_dereg_mr(send_mr);
out_dereg_recv:
rdma_dereg_mr(mr);
out_destroy_ep:
rdma_destroy_ep(id);
out_free_addrinfo:
rdma_freeaddrinfo(res);
out:
return ret;
}
总结:描述了客户端想服务器发送和接收的一个过程。
标签:core,ret,client,rdma,send,mr,recv,out From: https://blog.51cto.com/u_14834110/6879818