2 * Copyright (c) 2005 Ammasso, Inc. All rights reserved.
3 * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 #include <sys/types.h>
40 #include <netinet/in.h>
41 #include <sys/socket.h>
43 #include <semaphore.h>
44 #include <arpa/inet.h>
48 #include <rdma/rdma_cma.h>
49 #include <infiniband/arch.h>
52 #define DEBUG_LOG if (debug) printf
55 * rping "ping/pong" loop:
56 * client sends source rkey/addr/len
57 * server receives source rkey/add/len
58 * server rdma reads "ping" data from source
59 * server sends "go ahead" on rdma read completion
60 * client sends sink rkey/addr/len
61 * server receives sink rkey/addr/len
62 * server rdma writes "pong" data to sink
63 * server sends "go ahead" on rdma write completion
68 * These states are used to signal events between the completion handler
69 * and the main client or server thread.
71 * Once CONNECTED, they cycle through RDMA_READ_ADV, RDMA_WRITE_ADV,
72 * and RDMA_WRITE_COMPLETE for each ping.
87 struct rping_rdma_info {
94 * Default max buffer size for IO...
96 #define RPING_BUFSIZE 64*1024
97 #define RPING_SQ_DEPTH 16
99 /* Default string for print data and
100 * minimum buffer size
102 #define _stringify( _x ) # _x
103 #define stringify( _x ) _stringify( _x )
105 #define RPING_MSG_FMT "rdma-ping-%d: "
106 #define RPING_MIN_BUFSIZE sizeof(stringify(INT_MAX)) + sizeof(RPING_MSG_FMT)
109 * Control block struct.
112 int server; /* 0 iff client */
114 pthread_t persistent_server_thread;
115 struct ibv_comp_channel *channel;
120 struct ibv_recv_wr rq_wr; /* recv work request record */
121 struct ibv_sge recv_sgl; /* recv single SGE */
122 struct rping_rdma_info recv_buf;/* malloc'd buffer */
123 struct ibv_mr *recv_mr; /* MR associated with this buffer */
125 struct ibv_send_wr sq_wr; /* send work request record */
126 struct ibv_sge send_sgl;
127 struct rping_rdma_info send_buf;/* single send buf */
128 struct ibv_mr *send_mr;
130 struct ibv_send_wr rdma_sq_wr; /* rdma work request record */
131 struct ibv_sge rdma_sgl; /* rdma single SGE */
132 char *rdma_buf; /* used as rdma sink */
133 struct ibv_mr *rdma_mr;
135 uint32_t remote_rkey; /* remote guys RKEY */
136 uint64_t remote_addr; /* remote guys TO */
137 uint32_t remote_len; /* remote guys LEN */
139 char *start_buf; /* rdma read src */
140 struct ibv_mr *start_mr;
142 enum test_state state; /* used for cond/signalling */
145 struct sockaddr_storage sin;
146 uint16_t port; /* dst port in NBO */
147 int verbose; /* verbose logging */
148 int count; /* ping count */
149 int size; /* ping data size */
150 int validate; /* validate ping data */
154 struct rdma_event_channel *cm_channel;
155 struct rdma_cm_id *cm_id; /* connection on client side,*/
156 /* listener on service side. */
157 struct rdma_cm_id *child_cm_id; /* connection on server side */
160 static int rping_cma_event_handler(struct rdma_cm_id *cma_id,
161 struct rdma_cm_event *event)
164 struct rping_cb *cb = cma_id->context;
166 DEBUG_LOG("cma_event type %s cma_id %p (%s)\n",
167 rdma_event_str(event->event), cma_id,
168 (cma_id == cb->cm_id) ? "parent" : "child");
170 switch (event->event) {
171 case RDMA_CM_EVENT_ADDR_RESOLVED:
172 cb->state = ADDR_RESOLVED;
173 ret = rdma_resolve_route(cma_id, 2000);
176 perror("rdma_resolve_route");
181 case RDMA_CM_EVENT_ROUTE_RESOLVED:
182 cb->state = ROUTE_RESOLVED;
186 case RDMA_CM_EVENT_CONNECT_REQUEST:
187 cb->state = CONNECT_REQUEST;
188 cb->child_cm_id = cma_id;
189 DEBUG_LOG("child cma %p\n", cb->child_cm_id);
193 case RDMA_CM_EVENT_ESTABLISHED:
194 DEBUG_LOG("ESTABLISHED\n");
197 * Server will wake up when first RECV completes.
200 cb->state = CONNECTED;
205 case RDMA_CM_EVENT_ADDR_ERROR:
206 case RDMA_CM_EVENT_ROUTE_ERROR:
207 case RDMA_CM_EVENT_CONNECT_ERROR:
208 case RDMA_CM_EVENT_UNREACHABLE:
209 case RDMA_CM_EVENT_REJECTED:
210 fprintf(stderr, "cma event %s, error %d\n",
211 rdma_event_str(event->event), event->status);
216 case RDMA_CM_EVENT_DISCONNECTED:
217 fprintf(stderr, "%s DISCONNECT EVENT...\n",
218 cb->server ? "server" : "client");
222 case RDMA_CM_EVENT_DEVICE_REMOVAL:
223 fprintf(stderr, "cma detected device removal!!!!\n");
228 fprintf(stderr, "unhandled event: %s, ignoring\n",
229 rdma_event_str(event->event));
236 static int server_recv(struct rping_cb *cb, struct ibv_wc *wc)
238 if (wc->byte_len != sizeof(cb->recv_buf)) {
239 fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);
243 cb->remote_rkey = ntohl(cb->recv_buf.rkey);
244 cb->remote_addr = ntohll(cb->recv_buf.buf);
245 cb->remote_len = ntohl(cb->recv_buf.size);
246 DEBUG_LOG("Received rkey %x addr %" PRIx64 " len %d from peer\n",
247 cb->remote_rkey, cb->remote_addr, cb->remote_len);
249 if (cb->state <= CONNECTED || cb->state == RDMA_WRITE_COMPLETE)
250 cb->state = RDMA_READ_ADV;
252 cb->state = RDMA_WRITE_ADV;
257 static int client_recv(struct rping_cb *cb, struct ibv_wc *wc)
259 if (wc->byte_len != sizeof(cb->recv_buf)) {
260 fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);
264 if (cb->state == RDMA_READ_ADV)
265 cb->state = RDMA_WRITE_ADV;
267 cb->state = RDMA_WRITE_COMPLETE;
272 static int rping_cq_event_handler(struct rping_cb *cb)
275 struct ibv_recv_wr *bad_wr;
278 while ((ret = ibv_poll_cq(cb->cq, 1, &wc)) == 1) {
282 if (wc.status != IBV_WC_WR_FLUSH_ERR)
283 fprintf(stderr, "cq completion failed status %d\n",
291 DEBUG_LOG("send completion\n");
294 case IBV_WC_RDMA_WRITE:
295 DEBUG_LOG("rdma write completion\n");
296 cb->state = RDMA_WRITE_COMPLETE;
300 case IBV_WC_RDMA_READ:
301 DEBUG_LOG("rdma read completion\n");
302 cb->state = RDMA_READ_COMPLETE;
307 DEBUG_LOG("recv completion\n");
308 ret = cb->server ? server_recv(cb, &wc) :
309 client_recv(cb, &wc);
311 fprintf(stderr, "recv wc error: %d\n", ret);
315 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
317 fprintf(stderr, "post recv error: %d\n", ret);
324 DEBUG_LOG("unknown!!!!! completion\n");
330 fprintf(stderr, "poll error %d\n", ret);
341 static int rping_accept(struct rping_cb *cb)
343 struct rdma_conn_param conn_param;
346 DEBUG_LOG("accepting client connection request\n");
348 memset(&conn_param, 0, sizeof conn_param);
349 conn_param.responder_resources = 1;
350 conn_param.initiator_depth = 1;
352 ret = rdma_accept(cb->child_cm_id, &conn_param);
354 perror("rdma_accept");
359 if (cb->state == ERROR) {
360 fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);
366 static void rping_setup_wr(struct rping_cb *cb)
368 cb->recv_sgl.addr = (uint64_t) (unsigned long) &cb->recv_buf;
369 cb->recv_sgl.length = sizeof cb->recv_buf;
370 cb->recv_sgl.lkey = cb->recv_mr->lkey;
371 cb->rq_wr.sg_list = &cb->recv_sgl;
372 cb->rq_wr.num_sge = 1;
374 cb->send_sgl.addr = (uint64_t) (unsigned long) &cb->send_buf;
375 cb->send_sgl.length = sizeof cb->send_buf;
376 cb->send_sgl.lkey = cb->send_mr->lkey;
378 cb->sq_wr.opcode = IBV_WR_SEND;
379 cb->sq_wr.send_flags = IBV_SEND_SIGNALED;
380 cb->sq_wr.sg_list = &cb->send_sgl;
381 cb->sq_wr.num_sge = 1;
383 cb->rdma_sgl.addr = (uint64_t) (unsigned long) cb->rdma_buf;
384 cb->rdma_sgl.lkey = cb->rdma_mr->lkey;
385 cb->rdma_sq_wr.send_flags = IBV_SEND_SIGNALED;
386 cb->rdma_sq_wr.sg_list = &cb->rdma_sgl;
387 cb->rdma_sq_wr.num_sge = 1;
390 static int rping_setup_buffers(struct rping_cb *cb)
394 DEBUG_LOG("rping_setup_buffers called on cb %p\n", cb);
396 cb->recv_mr = ibv_reg_mr(cb->pd, &cb->recv_buf, sizeof cb->recv_buf,
397 IBV_ACCESS_LOCAL_WRITE);
399 fprintf(stderr, "recv_buf reg_mr failed\n");
403 cb->send_mr = ibv_reg_mr(cb->pd, &cb->send_buf, sizeof cb->send_buf, 0);
405 fprintf(stderr, "send_buf reg_mr failed\n");
410 cb->rdma_buf = malloc(cb->size);
412 fprintf(stderr, "rdma_buf malloc failed\n");
417 cb->rdma_mr = ibv_reg_mr(cb->pd, cb->rdma_buf, cb->size,
418 IBV_ACCESS_LOCAL_WRITE |
419 IBV_ACCESS_REMOTE_READ |
420 IBV_ACCESS_REMOTE_WRITE);
422 fprintf(stderr, "rdma_buf reg_mr failed\n");
428 cb->start_buf = malloc(cb->size);
429 if (!cb->start_buf) {
430 fprintf(stderr, "start_buf malloc failed\n");
435 cb->start_mr = ibv_reg_mr(cb->pd, cb->start_buf, cb->size,
436 IBV_ACCESS_LOCAL_WRITE |
437 IBV_ACCESS_REMOTE_READ |
438 IBV_ACCESS_REMOTE_WRITE);
440 fprintf(stderr, "start_buf reg_mr failed\n");
447 DEBUG_LOG("allocated & registered buffers...\n");
453 ibv_dereg_mr(cb->rdma_mr);
457 ibv_dereg_mr(cb->send_mr);
459 ibv_dereg_mr(cb->recv_mr);
463 static void rping_free_buffers(struct rping_cb *cb)
465 DEBUG_LOG("rping_free_buffers called on cb %p\n", cb);
466 ibv_dereg_mr(cb->recv_mr);
467 ibv_dereg_mr(cb->send_mr);
468 ibv_dereg_mr(cb->rdma_mr);
471 ibv_dereg_mr(cb->start_mr);
476 static int rping_create_qp(struct rping_cb *cb)
478 struct ibv_qp_init_attr init_attr;
481 memset(&init_attr, 0, sizeof(init_attr));
482 init_attr.cap.max_send_wr = RPING_SQ_DEPTH;
483 init_attr.cap.max_recv_wr = 2;
484 init_attr.cap.max_recv_sge = 1;
485 init_attr.cap.max_send_sge = 1;
486 init_attr.qp_type = IBV_QPT_RC;
487 init_attr.send_cq = cb->cq;
488 init_attr.recv_cq = cb->cq;
491 ret = rdma_create_qp(cb->child_cm_id, cb->pd, &init_attr);
493 cb->qp = cb->child_cm_id->qp;
495 ret = rdma_create_qp(cb->cm_id, cb->pd, &init_attr);
497 cb->qp = cb->cm_id->qp;
503 static void rping_free_qp(struct rping_cb *cb)
505 ibv_destroy_qp(cb->qp);
506 ibv_destroy_cq(cb->cq);
507 ibv_destroy_comp_channel(cb->channel);
508 ibv_dealloc_pd(cb->pd);
511 static int rping_setup_qp(struct rping_cb *cb, struct rdma_cm_id *cm_id)
515 cb->pd = ibv_alloc_pd(cm_id->verbs);
517 fprintf(stderr, "ibv_alloc_pd failed\n");
520 DEBUG_LOG("created pd %p\n", cb->pd);
522 cb->channel = ibv_create_comp_channel(cm_id->verbs);
524 fprintf(stderr, "ibv_create_comp_channel failed\n");
528 DEBUG_LOG("created channel %p\n", cb->channel);
530 cb->cq = ibv_create_cq(cm_id->verbs, RPING_SQ_DEPTH * 2, cb,
533 fprintf(stderr, "ibv_create_cq failed\n");
537 DEBUG_LOG("created cq %p\n", cb->cq);
539 ret = ibv_req_notify_cq(cb->cq, 0);
541 fprintf(stderr, "ibv_create_cq failed\n");
546 ret = rping_create_qp(cb);
548 perror("rdma_create_qp");
551 DEBUG_LOG("created qp %p\n", cb->qp);
555 ibv_destroy_cq(cb->cq);
557 ibv_destroy_comp_channel(cb->channel);
559 ibv_dealloc_pd(cb->pd);
563 static void *cm_thread(void *arg)
565 struct rping_cb *cb = arg;
566 struct rdma_cm_event *event;
570 ret = rdma_get_cm_event(cb->cm_channel, &event);
572 perror("rdma_get_cm_event");
575 ret = rping_cma_event_handler(event->id, event);
576 rdma_ack_cm_event(event);
582 static void *cq_thread(void *arg)
584 struct rping_cb *cb = arg;
585 struct ibv_cq *ev_cq;
589 DEBUG_LOG("cq_thread started.\n");
592 pthread_testcancel();
594 ret = ibv_get_cq_event(cb->channel, &ev_cq, &ev_ctx);
596 fprintf(stderr, "Failed to get cq event!\n");
599 if (ev_cq != cb->cq) {
600 fprintf(stderr, "Unknown CQ!\n");
603 ret = ibv_req_notify_cq(cb->cq, 0);
605 fprintf(stderr, "Failed to set notify!\n");
608 ret = rping_cq_event_handler(cb);
609 ibv_ack_cq_events(cb->cq, 1);
615 static void rping_format_send(struct rping_cb *cb, char *buf, struct ibv_mr *mr)
617 struct rping_rdma_info *info = &cb->send_buf;
619 info->buf = htonll((uint64_t) (unsigned long) buf);
620 info->rkey = htonl(mr->rkey);
621 info->size = htonl(cb->size);
623 DEBUG_LOG("RDMA addr %" PRIx64" rkey %x len %d\n",
624 ntohll(info->buf), ntohl(info->rkey), ntohl(info->size));
627 static int rping_test_server(struct rping_cb *cb)
629 struct ibv_send_wr *bad_wr;
633 /* Wait for client's Start STAG/TO/Len */
635 if (cb->state != RDMA_READ_ADV) {
636 fprintf(stderr, "wait for RDMA_READ_ADV state %d\n",
642 DEBUG_LOG("server received sink adv\n");
644 /* Issue RDMA Read. */
645 cb->rdma_sq_wr.opcode = IBV_WR_RDMA_READ;
646 cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;
647 cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;
648 cb->rdma_sq_wr.sg_list->length = cb->remote_len;
650 ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);
652 fprintf(stderr, "post send error %d\n", ret);
655 DEBUG_LOG("server posted rdma read req \n");
657 /* Wait for read completion */
659 if (cb->state != RDMA_READ_COMPLETE) {
660 fprintf(stderr, "wait for RDMA_READ_COMPLETE state %d\n",
665 DEBUG_LOG("server received read complete\n");
667 /* Display data in recv buf */
669 printf("server ping data: %s\n", cb->rdma_buf);
671 /* Tell client to continue */
672 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
674 fprintf(stderr, "post send error %d\n", ret);
677 DEBUG_LOG("server posted go ahead\n");
679 /* Wait for client's RDMA STAG/TO/Len */
681 if (cb->state != RDMA_WRITE_ADV) {
682 fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",
687 DEBUG_LOG("server received sink adv\n");
689 /* RDMA Write echo data */
690 cb->rdma_sq_wr.opcode = IBV_WR_RDMA_WRITE;
691 cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;
692 cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;
693 cb->rdma_sq_wr.sg_list->length = strlen(cb->rdma_buf) + 1;
694 DEBUG_LOG("rdma write from lkey %x laddr %" PRIx64 " len %d\n",
695 cb->rdma_sq_wr.sg_list->lkey,
696 cb->rdma_sq_wr.sg_list->addr,
697 cb->rdma_sq_wr.sg_list->length);
699 ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);
701 fprintf(stderr, "post send error %d\n", ret);
705 /* Wait for completion */
706 ret = sem_wait(&cb->sem);
707 if (cb->state != RDMA_WRITE_COMPLETE) {
708 fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",
713 DEBUG_LOG("server rdma write complete \n");
715 /* Tell client to begin again */
716 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
718 fprintf(stderr, "post send error %d\n", ret);
721 DEBUG_LOG("server posted go ahead\n");
727 static int rping_bind_server(struct rping_cb *cb)
731 if (cb->sin.ss_family == AF_INET)
732 ((struct sockaddr_in *) &cb->sin)->sin_port = cb->port;
734 ((struct sockaddr_in6 *) &cb->sin)->sin6_port = cb->port;
736 ret = rdma_bind_addr(cb->cm_id, (struct sockaddr *) &cb->sin);
738 perror("rdma_bind_addr");
741 DEBUG_LOG("rdma_bind_addr successful\n");
743 DEBUG_LOG("rdma_listen\n");
744 ret = rdma_listen(cb->cm_id, 3);
746 perror("rdma_listen");
753 static struct rping_cb *clone_cb(struct rping_cb *listening_cb)
755 struct rping_cb *cb = malloc(sizeof *cb);
759 cb->child_cm_id->context = cb;
763 static void free_cb(struct rping_cb *cb)
768 static void *rping_persistent_server_thread(void *arg)
770 struct rping_cb *cb = arg;
771 struct ibv_recv_wr *bad_wr;
774 ret = rping_setup_qp(cb, cb->child_cm_id);
776 fprintf(stderr, "setup_qp failed: %d\n", ret);
780 ret = rping_setup_buffers(cb);
782 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
786 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
788 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
792 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
794 ret = rping_accept(cb);
796 fprintf(stderr, "connect error %d\n", ret);
800 rping_test_server(cb);
801 rdma_disconnect(cb->child_cm_id);
802 pthread_join(cb->cqthread, NULL);
803 rping_free_buffers(cb);
805 rdma_destroy_id(cb->child_cm_id);
809 pthread_cancel(cb->cqthread);
810 pthread_join(cb->cqthread, NULL);
812 rping_free_buffers(cb);
820 static int rping_run_persistent_server(struct rping_cb *listening_cb)
825 ret = rping_bind_server(listening_cb);
830 sem_wait(&listening_cb->sem);
831 if (listening_cb->state != CONNECT_REQUEST) {
832 fprintf(stderr, "wait for CONNECT_REQUEST state %d\n",
833 listening_cb->state);
837 cb = clone_cb(listening_cb);
840 pthread_create(&cb->persistent_server_thread, NULL, rping_persistent_server_thread, cb);
845 static int rping_run_server(struct rping_cb *cb)
847 struct ibv_recv_wr *bad_wr;
850 ret = rping_bind_server(cb);
855 if (cb->state != CONNECT_REQUEST) {
856 fprintf(stderr, "wait for CONNECT_REQUEST state %d\n",
861 ret = rping_setup_qp(cb, cb->child_cm_id);
863 fprintf(stderr, "setup_qp failed: %d\n", ret);
867 ret = rping_setup_buffers(cb);
869 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
873 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
875 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
879 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
881 ret = rping_accept(cb);
883 fprintf(stderr, "connect error %d\n", ret);
887 rping_test_server(cb);
888 rdma_disconnect(cb->child_cm_id);
889 pthread_join(cb->cqthread, NULL);
890 rdma_destroy_id(cb->child_cm_id);
892 rping_free_buffers(cb);
899 static int rping_test_client(struct rping_cb *cb)
901 int ping, start, cc, i, ret = 0;
902 struct ibv_send_wr *bad_wr;
906 for (ping = 0; !cb->count || ping < cb->count; ping++) {
907 cb->state = RDMA_READ_ADV;
909 /* Put some ascii text in the buffer. */
910 cc = sprintf(cb->start_buf, RPING_MSG_FMT, ping);
911 for (i = cc, c = start; i < cb->size; i++) {
912 cb->start_buf[i] = c;
920 cb->start_buf[cb->size - 1] = 0;
922 rping_format_send(cb, cb->start_buf, cb->start_mr);
923 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
925 fprintf(stderr, "post send error %d\n", ret);
929 /* Wait for server to ACK */
931 if (cb->state != RDMA_WRITE_ADV) {
932 fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",
938 rping_format_send(cb, cb->rdma_buf, cb->rdma_mr);
939 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
941 fprintf(stderr, "post send error %d\n", ret);
945 /* Wait for the server to say the RDMA Write is complete. */
947 if (cb->state != RDMA_WRITE_COMPLETE) {
948 fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",
955 if (memcmp(cb->start_buf, cb->rdma_buf, cb->size)) {
956 fprintf(stderr, "data mismatch!\n");
962 printf("ping data: %s\n", cb->rdma_buf);
968 static int rping_connect_client(struct rping_cb *cb)
970 struct rdma_conn_param conn_param;
973 memset(&conn_param, 0, sizeof conn_param);
974 conn_param.responder_resources = 1;
975 conn_param.initiator_depth = 1;
976 conn_param.retry_count = 10;
978 ret = rdma_connect(cb->cm_id, &conn_param);
980 perror("rdma_connect");
985 if (cb->state != CONNECTED) {
986 fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);
990 DEBUG_LOG("rmda_connect successful\n");
994 static int rping_bind_client(struct rping_cb *cb)
998 if (cb->sin.ss_family == AF_INET)
999 ((struct sockaddr_in *) &cb->sin)->sin_port = cb->port;
1001 ((struct sockaddr_in6 *) &cb->sin)->sin6_port = cb->port;
1003 ret = rdma_resolve_addr(cb->cm_id, NULL, (struct sockaddr *) &cb->sin, 2000);
1005 perror("rdma_resolve_addr");
1010 if (cb->state != ROUTE_RESOLVED) {
1011 fprintf(stderr, "waiting for addr/route resolution state %d\n",
1016 DEBUG_LOG("rdma_resolve_addr - rdma_resolve_route successful\n");
1020 static int rping_run_client(struct rping_cb *cb)
1022 struct ibv_recv_wr *bad_wr;
1025 ret = rping_bind_client(cb);
1029 ret = rping_setup_qp(cb, cb->cm_id);
1031 fprintf(stderr, "setup_qp failed: %d\n", ret);
1035 ret = rping_setup_buffers(cb);
1037 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
1041 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
1043 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
1047 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
1049 ret = rping_connect_client(cb);
1051 fprintf(stderr, "connect error %d\n", ret);
1055 ret = rping_test_client(cb);
1057 fprintf(stderr, "rping client failed: %d\n", ret);
1062 rdma_disconnect(cb->cm_id);
1064 pthread_join(cb->cqthread, NULL);
1066 rping_free_buffers(cb);
1073 static int get_addr(char *dst, struct sockaddr *addr)
1075 struct addrinfo *res;
1078 ret = getaddrinfo(dst, NULL, NULL, &res);
1080 printf("getaddrinfo failed - invalid hostname or IP address\n");
1084 if (res->ai_family == PF_INET)
1085 memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in));
1086 else if (res->ai_family == PF_INET6)
1087 memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in6));
1095 static void usage(char *name)
1097 printf("%s -s [-vVd] [-S size] [-C count] [-a addr] [-p port]\n",
1099 printf("%s -c [-vVd] [-S size] [-C count] -a addr [-p port]\n",
1101 printf("\t-c\t\tclient side\n");
1102 printf("\t-s\t\tserver side. To bind to any address with IPv6 use -a ::0\n");
1103 printf("\t-v\t\tdisplay ping data to stdout\n");
1104 printf("\t-V\t\tvalidate ping data\n");
1105 printf("\t-d\t\tdebug printfs\n");
1106 printf("\t-S size \tping data size\n");
1107 printf("\t-C count\tping count times\n");
1108 printf("\t-a addr\t\taddress\n");
1109 printf("\t-p port\t\tport\n");
1110 printf("\t-P\t\tpersistent server mode allowing multiple connections\n");
1113 int main(int argc, char *argv[])
1115 struct rping_cb *cb;
1118 int persistent_server = 0;
1120 cb = malloc(sizeof(*cb));
1124 memset(cb, 0, sizeof(*cb));
1128 cb->sin.ss_family = PF_INET;
1129 cb->port = htons(7174);
1130 sem_init(&cb->sem, 0, 0);
1133 while ((op=getopt(argc, argv, "a:Pp:C:S:t:scvVd")) != -1) {
1136 ret = get_addr(optarg, (struct sockaddr *) &cb->sin);
1139 persistent_server = 1;
1142 cb->port = htons(atoi(optarg));
1143 DEBUG_LOG("port %d\n", (int) atoi(optarg));
1147 DEBUG_LOG("server\n");
1151 DEBUG_LOG("client\n");
1154 cb->size = atoi(optarg);
1155 if ((cb->size < RPING_MIN_BUFSIZE) ||
1156 (cb->size > (RPING_BUFSIZE - 1))) {
1157 fprintf(stderr, "Invalid size %d "
1158 "(valid range is %d to %d)\n",
1159 (int)cb->size, (int)(RPING_MIN_BUFSIZE),
1160 (int)(RPING_BUFSIZE));
1163 DEBUG_LOG("size %d\n", (int) atoi(optarg));
1166 cb->count = atoi(optarg);
1167 if (cb->count < 0) {
1168 fprintf(stderr, "Invalid count %d\n",
1172 DEBUG_LOG("count %d\n", (int) cb->count);
1176 DEBUG_LOG("verbose\n");
1180 DEBUG_LOG("validate data\n");
1194 if (cb->server == -1) {
1200 cb->cm_channel = rdma_create_event_channel();
1201 if (!cb->cm_channel) {
1202 perror("rdma_create_event_channel");
1206 ret = rdma_create_id(cb->cm_channel, &cb->cm_id, cb, RDMA_PS_TCP);
1208 perror("rdma_create_id");
1211 DEBUG_LOG("created cm_id %p\n", cb->cm_id);
1213 pthread_create(&cb->cmthread, NULL, cm_thread, cb);
1216 if (persistent_server)
1217 ret = rping_run_persistent_server(cb);
1219 ret = rping_run_server(cb);
1221 ret = rping_run_client(cb);
1223 DEBUG_LOG("destroy cm_id %p\n", cb->cm_id);
1224 rdma_destroy_id(cb->cm_id);
1226 rdma_destroy_event_channel(cb->cm_channel);