1use rdma_sys::*;
15use std::{env, process::exit, ptr::null_mut};
16
17fn run(ip: &str, port: &str) -> i32 {
18 let mut send_msg = vec![1_u8; 16];
19 let mut recv_msg = vec![0_u8; 16];
20 let mut hints = unsafe { std::mem::zeroed::<rdma_addrinfo>() };
21 let mut res: *mut rdma_addrinfo = null_mut();
22
23 hints.ai_port_space = rdma_port_space::RDMA_PS_TCP as i32;
24 let mut ret =
25 unsafe { rdma_getaddrinfo(ip.as_ptr().cast(), port.as_ptr().cast(), &hints, &mut res) };
26
27 if ret != 0 {
28 println!("rdma_getaddrinfo");
29 return ret;
30 }
31
32 let mut attr = unsafe { std::mem::zeroed::<ibv_qp_init_attr>() };
33 let mut id: *mut rdma_cm_id = null_mut();
34 attr.cap.max_send_wr = 1;
35 attr.cap.max_recv_wr = 1;
36 attr.cap.max_send_sge = 1;
37 attr.cap.max_recv_sge = 1;
38 attr.cap.max_inline_data = 16;
39 attr.qp_context = id.cast();
40 attr.sq_sig_all = 1;
41 ret = unsafe { rdma_create_ep(&mut id, res, null_mut(), &mut attr) };
42 let mut send_flags = 0_u32;
44 if attr.cap.max_inline_data >= 16 {
45 send_flags = ibv_send_flags::IBV_SEND_INLINE.0;
46 } else {
47 println!("rdma_client: device doesn't support IBV_SEND_INLINE, using sge sends");
48 }
49
50 if ret != 0 {
51 println!("rdma_create_ep");
52 unsafe {
53 rdma_freeaddrinfo(res);
54 }
55 return ret;
56 }
57
58 let mr = unsafe { rdma_reg_msgs(id, recv_msg.as_mut_ptr().cast(), 16) };
59 if mr.is_null() {
60 println!("rdma_reg_msgs for recv_msg");
61 unsafe {
62 rdma_destroy_ep(id);
63 }
64 return -1;
65 }
66
67 let mut send_mr = null_mut();
68 if (send_flags & ibv_send_flags::IBV_SEND_INLINE.0) as u32 == 0 {
69 println!("flags {:?}", send_flags);
70 send_mr = unsafe { rdma_reg_msgs(id, send_msg.as_mut_ptr().cast(), 16) };
71 if send_mr.is_null() {
72 println!("rdma_reg_msgs for send_msg");
73 unsafe {
74 rdma_dereg_mr(mr);
75 }
76 return -1;
77 }
78 }
79
80 ret = unsafe { rdma_post_recv(id, null_mut(), recv_msg.as_mut_ptr().cast(), 16, mr) };
81 if ret != 0 {
82 println!("rdma_post_recv");
83 if (send_flags & ibv_send_flags::IBV_SEND_INLINE.0) as u32 == 0 {
84 unsafe { rdma_dereg_mr(send_mr) };
85 }
86 return ret;
87 }
88
89 ret = unsafe { rdma_connect(id, null_mut()) };
90 if ret != 0 {
91 println!("rdma_connect");
92 unsafe {
93 rdma_disconnect(id);
94 }
95 return ret;
96 }
97
98 ret = unsafe {
99 rdma_post_send(
100 id,
101 null_mut(),
102 send_msg.as_mut_ptr().cast(),
103 16,
104 send_mr,
105 send_flags.try_into().unwrap(),
106 )
107 };
108 if ret != 0 {
109 println!("rdma_post_send");
110 unsafe {
111 rdma_disconnect(id);
112 }
113 return ret;
114 }
115
116 let mut wc = unsafe { std::mem::zeroed::<ibv_wc>() };
117 while ret == 0 {
118 ret = unsafe { rdma_get_send_comp(id, &mut wc) };
119 }
120 if ret < 0 {
121 println!("rdma_get_send_comp");
122 unsafe {
123 rdma_disconnect(id);
124 }
125 return ret;
126 }
127
128 ret = 0;
129 while ret == 0 {
130 ret = unsafe { rdma_get_recv_comp(id, &mut wc) };
131 }
132 println!("rdma_client: recv msg : {:?}", recv_msg);
133 if ret < 0 {
134 println!("rdma_get_recv_comp");
135 } else {
136 ret = 0;
137 }
138
139 ret
140}
141
142fn main() {
143 println!("rdma_client: start");
144 let args: Vec<String> = env::args().collect();
145 if args.len() != 3 {
146 println!("usage : cargo run --example client <server_ip> <port>");
147 println!("input : {:?}", args);
148 exit(-1);
149 }
150 let ip = args.get(1).unwrap().as_str();
151 let port = args.get(2).unwrap().as_str();
152
153 let ret = run(ip, port);
154
155 if ret != 0 {
156 println!(
157 "rdma_client: ret error {:?}",
158 std::io::Error::from_raw_os_error(-ret)
159 );
160 if ret == -1 {
161 println!(
162 "rdma_client: last os error {:?}",
163 std::io::Error::last_os_error()
164 );
165 }
166 }
167 println!("rdma_client: end");
168}