client/
client.rs

1//! This demo shows how to establish a connection between server and client
2//! and send msg to the other end.
3//!
4//! You can try this example by running:
5//!
6//!     cargo run --example server
7//!
8//! And then start client in another terminal by running:
9//!
10//!     cargo run --example client <server_ip> <port>
11//!
12//! The default port is 7471.
13
14use 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    // Check to see if we got inline data allowed or not
43    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}