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>
44 #include <semaphore.h>
45 #include <arpa/inet.h>
49 #include <rdma/rdma_cma.h>
50 #include <infiniband/arch.h>
53 #define DEBUG_LOG if (debug) printf
56 * rping "ping/pong" loop:
57 * client sends source rkey/addr/len
58 * server receives source rkey/add/len
59 * server rdma reads "ping" data from source
60 * server sends "go ahead" on rdma read completion
61 * client sends sink rkey/addr/len
62 * server receives sink rkey/addr/len
63 * server rdma writes "pong" data to sink
64 * server sends "go ahead" on rdma write completion
69 * These states are used to signal events between the completion handler
70 * and the main client or server thread.
72 * Once CONNECTED, they cycle through RDMA_READ_ADV, RDMA_WRITE_ADV,
73 * and RDMA_WRITE_COMPLETE for each ping.
88 struct rping_rdma_info {
95 * Default max buffer size for IO...
97 #define RPING_BUFSIZE 64*1024
98 #define RPING_SQ_DEPTH 16
100 /* Default string for print data and
101 * minimum buffer size
103 #define _stringify( _x ) # _x
104 #define stringify( _x ) _stringify( _x )
106 #define RPING_MSG_FMT "rdma-ping-%d: "
107 #define RPING_MIN_BUFSIZE sizeof(stringify(INT_MAX)) + sizeof(RPING_MSG_FMT)
110 * Control block struct.
113 int server; /* 0 iff client */
115 pthread_t persistent_server_thread;
116 struct ibv_comp_channel *channel;
121 struct ibv_recv_wr rq_wr; /* recv work request record */
122 struct ibv_sge recv_sgl; /* recv single SGE */
123 struct rping_rdma_info recv_buf;/* malloc'd buffer */
124 struct ibv_mr *recv_mr; /* MR associated with this buffer */
126 struct ibv_send_wr sq_wr; /* send work request record */
127 struct ibv_sge send_sgl;
128 struct rping_rdma_info send_buf;/* single send buf */
129 struct ibv_mr *send_mr;
131 struct ibv_send_wr rdma_sq_wr; /* rdma work request record */
132 struct ibv_sge rdma_sgl; /* rdma single SGE */
133 char *rdma_buf; /* used as rdma sink */
134 struct ibv_mr *rdma_mr;
136 uint32_t remote_rkey; /* remote guys RKEY */
137 uint64_t remote_addr; /* remote guys TO */
138 uint32_t remote_len; /* remote guys LEN */
140 char *start_buf; /* rdma read src */
141 struct ibv_mr *start_mr;
143 enum test_state state; /* used for cond/signalling */
146 struct sockaddr_storage sin;
147 uint16_t port; /* dst port in NBO */
148 int verbose; /* verbose logging */
149 int count; /* ping count */
150 int size; /* ping data size */
151 int validate; /* validate ping data */
155 struct rdma_event_channel *cm_channel;
156 struct rdma_cm_id *cm_id; /* connection on client side,*/
157 /* listener on service side. */
158 struct rdma_cm_id *child_cm_id; /* connection on server side */
161 static int rping_cma_event_handler(struct rdma_cm_id *cma_id,
162 struct rdma_cm_event *event)
165 struct rping_cb *cb = cma_id->context;
167 DEBUG_LOG("cma_event type %s cma_id %p (%s)\n",
168 rdma_event_str(event->event), cma_id,
169 (cma_id == cb->cm_id) ? "parent" : "child");
171 switch (event->event) {
172 case RDMA_CM_EVENT_ADDR_RESOLVED:
173 cb->state = ADDR_RESOLVED;
174 ret = rdma_resolve_route(cma_id, 2000);
177 perror("rdma_resolve_route");
182 case RDMA_CM_EVENT_ROUTE_RESOLVED:
183 cb->state = ROUTE_RESOLVED;
187 case RDMA_CM_EVENT_CONNECT_REQUEST:
188 cb->state = CONNECT_REQUEST;
189 cb->child_cm_id = cma_id;
190 DEBUG_LOG("child cma %p\n", cb->child_cm_id);
194 case RDMA_CM_EVENT_ESTABLISHED:
195 DEBUG_LOG("ESTABLISHED\n");
198 * Server will wake up when first RECV completes.
201 cb->state = CONNECTED;
206 case RDMA_CM_EVENT_ADDR_ERROR:
207 case RDMA_CM_EVENT_ROUTE_ERROR:
208 case RDMA_CM_EVENT_CONNECT_ERROR:
209 case RDMA_CM_EVENT_UNREACHABLE:
210 case RDMA_CM_EVENT_REJECTED:
211 fprintf(stderr, "cma event %s, error %d\n",
212 rdma_event_str(event->event), event->status);
217 case RDMA_CM_EVENT_DISCONNECTED:
218 fprintf(stderr, "%s DISCONNECT EVENT...\n",
219 cb->server ? "server" : "client");
223 case RDMA_CM_EVENT_DEVICE_REMOVAL:
224 fprintf(stderr, "cma detected device removal!!!!\n");
229 fprintf(stderr, "unhandled event: %s, ignoring\n",
230 rdma_event_str(event->event));
237 static int server_recv(struct rping_cb *cb, struct ibv_wc *wc)
239 if (wc->byte_len != sizeof(cb->recv_buf)) {
240 fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);
244 cb->remote_rkey = ntohl(cb->recv_buf.rkey);
245 cb->remote_addr = ntohll(cb->recv_buf.buf);
246 cb->remote_len = ntohl(cb->recv_buf.size);
247 DEBUG_LOG("Received rkey %x addr %" PRIx64 " len %d from peer\n",
248 cb->remote_rkey, cb->remote_addr, cb->remote_len);
250 if (cb->state <= CONNECTED || cb->state == RDMA_WRITE_COMPLETE)
251 cb->state = RDMA_READ_ADV;
253 cb->state = RDMA_WRITE_ADV;
258 static int client_recv(struct rping_cb *cb, struct ibv_wc *wc)
260 if (wc->byte_len != sizeof(cb->recv_buf)) {
261 fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);
265 if (cb->state == RDMA_READ_ADV)
266 cb->state = RDMA_WRITE_ADV;
268 cb->state = RDMA_WRITE_COMPLETE;
273 static int rping_cq_event_handler(struct rping_cb *cb)
276 struct ibv_recv_wr *bad_wr;
279 while ((ret = ibv_poll_cq(cb->cq, 1, &wc)) == 1) {
283 fprintf(stderr, "cq completion failed status %d\n",
285 if (wc.status != IBV_WC_WR_FLUSH_ERR)
292 DEBUG_LOG("send completion\n");
295 case IBV_WC_RDMA_WRITE:
296 DEBUG_LOG("rdma write completion\n");
297 cb->state = RDMA_WRITE_COMPLETE;
301 case IBV_WC_RDMA_READ:
302 DEBUG_LOG("rdma read completion\n");
303 cb->state = RDMA_READ_COMPLETE;
308 DEBUG_LOG("recv completion\n");
309 ret = cb->server ? server_recv(cb, &wc) :
310 client_recv(cb, &wc);
312 fprintf(stderr, "recv wc error: %d\n", ret);
316 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
318 fprintf(stderr, "post recv error: %d\n", ret);
325 DEBUG_LOG("unknown!!!!! completion\n");
331 fprintf(stderr, "poll error %d\n", ret);
342 static int rping_accept(struct rping_cb *cb)
344 struct rdma_conn_param conn_param;
347 DEBUG_LOG("accepting client connection request\n");
349 memset(&conn_param, 0, sizeof conn_param);
350 conn_param.responder_resources = 1;
351 conn_param.initiator_depth = 1;
353 ret = rdma_accept(cb->child_cm_id, &conn_param);
355 perror("rdma_accept");
360 if (cb->state == ERROR) {
361 fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);
367 static void rping_setup_wr(struct rping_cb *cb)
369 cb->recv_sgl.addr = (uint64_t) (unsigned long) &cb->recv_buf;
370 cb->recv_sgl.length = sizeof cb->recv_buf;
371 cb->recv_sgl.lkey = cb->recv_mr->lkey;
372 cb->rq_wr.sg_list = &cb->recv_sgl;
373 cb->rq_wr.num_sge = 1;
375 cb->send_sgl.addr = (uint64_t) (unsigned long) &cb->send_buf;
376 cb->send_sgl.length = sizeof cb->send_buf;
377 cb->send_sgl.lkey = cb->send_mr->lkey;
379 cb->sq_wr.opcode = IBV_WR_SEND;
380 cb->sq_wr.send_flags = IBV_SEND_SIGNALED;
381 cb->sq_wr.sg_list = &cb->send_sgl;
382 cb->sq_wr.num_sge = 1;
384 cb->rdma_sgl.addr = (uint64_t) (unsigned long) cb->rdma_buf;
385 cb->rdma_sgl.lkey = cb->rdma_mr->lkey;
386 cb->rdma_sq_wr.send_flags = IBV_SEND_SIGNALED;
387 cb->rdma_sq_wr.sg_list = &cb->rdma_sgl;
388 cb->rdma_sq_wr.num_sge = 1;
391 static int rping_setup_buffers(struct rping_cb *cb)
395 DEBUG_LOG("rping_setup_buffers called on cb %p\n", cb);
397 cb->recv_mr = ibv_reg_mr(cb->pd, &cb->recv_buf, sizeof cb->recv_buf,
398 IBV_ACCESS_LOCAL_WRITE);
400 fprintf(stderr, "recv_buf reg_mr failed\n");
404 cb->send_mr = ibv_reg_mr(cb->pd, &cb->send_buf, sizeof cb->send_buf, 0);
406 fprintf(stderr, "send_buf reg_mr failed\n");
411 cb->rdma_buf = malloc(cb->size);
413 fprintf(stderr, "rdma_buf malloc failed\n");
418 cb->rdma_mr = ibv_reg_mr(cb->pd, cb->rdma_buf, cb->size,
419 IBV_ACCESS_LOCAL_WRITE |
420 IBV_ACCESS_REMOTE_READ |
421 IBV_ACCESS_REMOTE_WRITE);
423 fprintf(stderr, "rdma_buf reg_mr failed\n");
429 cb->start_buf = malloc(cb->size);
430 if (!cb->start_buf) {
431 fprintf(stderr, "start_buf malloc failed\n");
436 cb->start_mr = ibv_reg_mr(cb->pd, cb->start_buf, cb->size,
437 IBV_ACCESS_LOCAL_WRITE |
438 IBV_ACCESS_REMOTE_READ |
439 IBV_ACCESS_REMOTE_WRITE);
441 fprintf(stderr, "start_buf reg_mr failed\n");
448 DEBUG_LOG("allocated & registered buffers...\n");
454 ibv_dereg_mr(cb->rdma_mr);
458 ibv_dereg_mr(cb->send_mr);
460 ibv_dereg_mr(cb->recv_mr);
464 static void rping_free_buffers(struct rping_cb *cb)
466 DEBUG_LOG("rping_free_buffers called on cb %p\n", cb);
467 ibv_dereg_mr(cb->recv_mr);
468 ibv_dereg_mr(cb->send_mr);
469 ibv_dereg_mr(cb->rdma_mr);
472 ibv_dereg_mr(cb->start_mr);
477 static int rping_create_qp(struct rping_cb *cb)
479 struct ibv_qp_init_attr init_attr;
482 memset(&init_attr, 0, sizeof(init_attr));
483 init_attr.cap.max_send_wr = RPING_SQ_DEPTH;
484 init_attr.cap.max_recv_wr = 2;
485 init_attr.cap.max_recv_sge = 1;
486 init_attr.cap.max_send_sge = 1;
487 init_attr.qp_type = IBV_QPT_RC;
488 init_attr.send_cq = cb->cq;
489 init_attr.recv_cq = cb->cq;
492 ret = rdma_create_qp(cb->child_cm_id, cb->pd, &init_attr);
494 cb->qp = cb->child_cm_id->qp;
496 ret = rdma_create_qp(cb->cm_id, cb->pd, &init_attr);
498 cb->qp = cb->cm_id->qp;
504 static void rping_free_qp(struct rping_cb *cb)
506 ibv_destroy_qp(cb->qp);
507 ibv_destroy_cq(cb->cq);
508 ibv_destroy_comp_channel(cb->channel);
509 ibv_dealloc_pd(cb->pd);
512 static int rping_setup_qp(struct rping_cb *cb, struct rdma_cm_id *cm_id)
516 cb->pd = ibv_alloc_pd(cm_id->verbs);
518 fprintf(stderr, "ibv_alloc_pd failed\n");
521 DEBUG_LOG("created pd %p\n", cb->pd);
523 cb->channel = ibv_create_comp_channel(cm_id->verbs);
525 fprintf(stderr, "ibv_create_comp_channel failed\n");
529 DEBUG_LOG("created channel %p\n", cb->channel);
531 cb->cq = ibv_create_cq(cm_id->verbs, RPING_SQ_DEPTH * 2, cb,
534 fprintf(stderr, "ibv_create_cq failed\n");
538 DEBUG_LOG("created cq %p\n", cb->cq);
540 ret = ibv_req_notify_cq(cb->cq, 0);
542 fprintf(stderr, "ibv_create_cq failed\n");
547 ret = rping_create_qp(cb);
549 perror("rdma_create_qp");
552 DEBUG_LOG("created qp %p\n", cb->qp);
556 ibv_destroy_cq(cb->cq);
558 ibv_destroy_comp_channel(cb->channel);
560 ibv_dealloc_pd(cb->pd);
564 static void *cm_thread(void *arg)
566 struct rping_cb *cb = arg;
567 struct rdma_cm_event *event;
571 ret = rdma_get_cm_event(cb->cm_channel, &event);
573 perror("rdma_get_cm_event");
576 ret = rping_cma_event_handler(event->id, event);
577 rdma_ack_cm_event(event);
583 static void *cq_thread(void *arg)
585 struct rping_cb *cb = arg;
586 struct ibv_cq *ev_cq;
590 DEBUG_LOG("cq_thread started.\n");
593 pthread_testcancel();
595 ret = ibv_get_cq_event(cb->channel, &ev_cq, &ev_ctx);
597 fprintf(stderr, "Failed to get cq event!\n");
600 if (ev_cq != cb->cq) {
601 fprintf(stderr, "Unknown CQ!\n");
604 ret = ibv_req_notify_cq(cb->cq, 0);
606 fprintf(stderr, "Failed to set notify!\n");
609 ret = rping_cq_event_handler(cb);
610 ibv_ack_cq_events(cb->cq, 1);
616 static void rping_format_send(struct rping_cb *cb, char *buf, struct ibv_mr *mr)
618 struct rping_rdma_info *info = &cb->send_buf;
620 info->buf = htonll((uint64_t) (unsigned long) buf);
621 info->rkey = htonl(mr->rkey);
622 info->size = htonl(cb->size);
624 DEBUG_LOG("RDMA addr %" PRIx64" rkey %x len %d\n",
625 ntohll(info->buf), ntohl(info->rkey), ntohl(info->size));
628 static int rping_test_server(struct rping_cb *cb)
630 struct ibv_send_wr *bad_wr;
634 /* Wait for client's Start STAG/TO/Len */
636 if (cb->state != RDMA_READ_ADV) {
637 fprintf(stderr, "wait for RDMA_READ_ADV state %d\n",
643 DEBUG_LOG("server received sink adv\n");
645 /* Issue RDMA Read. */
646 cb->rdma_sq_wr.opcode = IBV_WR_RDMA_READ;
647 cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;
648 cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;
649 cb->rdma_sq_wr.sg_list->length = cb->remote_len;
651 ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);
653 fprintf(stderr, "post send error %d\n", ret);
656 DEBUG_LOG("server posted rdma read req \n");
658 /* Wait for read completion */
660 if (cb->state != RDMA_READ_COMPLETE) {
661 fprintf(stderr, "wait for RDMA_READ_COMPLETE state %d\n",
666 DEBUG_LOG("server received read complete\n");
668 /* Display data in recv buf */
670 printf("server ping data: %s\n", cb->rdma_buf);
672 /* Tell client to continue */
673 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
675 fprintf(stderr, "post send error %d\n", ret);
678 DEBUG_LOG("server posted go ahead\n");
680 /* Wait for client's RDMA STAG/TO/Len */
682 if (cb->state != RDMA_WRITE_ADV) {
683 fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",
688 DEBUG_LOG("server received sink adv\n");
690 /* RDMA Write echo data */
691 cb->rdma_sq_wr.opcode = IBV_WR_RDMA_WRITE;
692 cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;
693 cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;
694 cb->rdma_sq_wr.sg_list->length = strlen(cb->rdma_buf) + 1;
695 DEBUG_LOG("rdma write from lkey %x laddr %" PRIx64 " len %d\n",
696 cb->rdma_sq_wr.sg_list->lkey,
697 cb->rdma_sq_wr.sg_list->addr,
698 cb->rdma_sq_wr.sg_list->length);
700 ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);
702 fprintf(stderr, "post send error %d\n", ret);
706 /* Wait for completion */
707 ret = sem_wait(&cb->sem);
708 if (cb->state != RDMA_WRITE_COMPLETE) {
709 fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",
714 DEBUG_LOG("server rdma write complete \n");
716 /* Tell client to begin again */
717 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
719 fprintf(stderr, "post send error %d\n", ret);
722 DEBUG_LOG("server posted go ahead\n");
728 static int rping_bind_server(struct rping_cb *cb)
732 if (cb->sin.ss_family == AF_INET)
733 ((struct sockaddr_in *) &cb->sin)->sin_port = cb->port;
735 ((struct sockaddr_in6 *) &cb->sin)->sin6_port = cb->port;
737 ret = rdma_bind_addr(cb->cm_id, (struct sockaddr *) &cb->sin);
739 perror("rdma_bind_addr");
742 DEBUG_LOG("rdma_bind_addr successful\n");
744 DEBUG_LOG("rdma_listen\n");
745 ret = rdma_listen(cb->cm_id, 3);
747 perror("rdma_listen");
754 static struct rping_cb *clone_cb(struct rping_cb *listening_cb)
756 struct rping_cb *cb = malloc(sizeof *cb);
760 cb->child_cm_id->context = cb;
764 static void free_cb(struct rping_cb *cb)
769 static void *rping_persistent_server_thread(void *arg)
771 struct rping_cb *cb = arg;
772 struct ibv_recv_wr *bad_wr;
775 ret = rping_setup_qp(cb, cb->child_cm_id);
777 fprintf(stderr, "setup_qp failed: %d\n", ret);
781 ret = rping_setup_buffers(cb);
783 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
787 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
789 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
793 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
795 ret = rping_accept(cb);
797 fprintf(stderr, "connect error %d\n", ret);
801 rping_test_server(cb);
802 rdma_disconnect(cb->child_cm_id);
803 rping_free_buffers(cb);
805 pthread_cancel(cb->cqthread);
806 pthread_join(cb->cqthread, NULL);
807 rdma_destroy_id(cb->child_cm_id);
811 pthread_cancel(cb->cqthread);
812 pthread_join(cb->cqthread, NULL);
814 rping_free_buffers(cb);
822 static int rping_run_persistent_server(struct rping_cb *listening_cb)
827 ret = rping_bind_server(listening_cb);
832 sem_wait(&listening_cb->sem);
833 if (listening_cb->state != CONNECT_REQUEST) {
834 fprintf(stderr, "wait for CONNECT_REQUEST state %d\n",
835 listening_cb->state);
839 cb = clone_cb(listening_cb);
842 pthread_create(&cb->persistent_server_thread, NULL, rping_persistent_server_thread, cb);
847 static int rping_run_server(struct rping_cb *cb)
849 struct ibv_recv_wr *bad_wr;
852 ret = rping_bind_server(cb);
857 if (cb->state != CONNECT_REQUEST) {
858 fprintf(stderr, "wait for CONNECT_REQUEST state %d\n",
863 ret = rping_setup_qp(cb, cb->child_cm_id);
865 fprintf(stderr, "setup_qp failed: %d\n", ret);
869 ret = rping_setup_buffers(cb);
871 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
875 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
877 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
881 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
883 ret = rping_accept(cb);
885 fprintf(stderr, "connect error %d\n", ret);
889 rping_test_server(cb);
890 rdma_disconnect(cb->child_cm_id);
891 rdma_destroy_id(cb->child_cm_id);
893 rping_free_buffers(cb);
900 static int rping_test_client(struct rping_cb *cb)
902 int ping, start, cc, i, ret = 0;
903 struct ibv_send_wr *bad_wr;
907 for (ping = 0; !cb->count || ping < cb->count; ping++) {
908 cb->state = RDMA_READ_ADV;
910 /* Put some ascii text in the buffer. */
911 cc = sprintf(cb->start_buf, RPING_MSG_FMT, ping);
912 for (i = cc, c = start; i < cb->size; i++) {
913 cb->start_buf[i] = c;
921 cb->start_buf[cb->size - 1] = 0;
923 rping_format_send(cb, cb->start_buf, cb->start_mr);
924 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
926 fprintf(stderr, "post send error %d\n", ret);
930 /* Wait for server to ACK */
932 if (cb->state != RDMA_WRITE_ADV) {
933 fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",
939 rping_format_send(cb, cb->rdma_buf, cb->rdma_mr);
940 ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);
942 fprintf(stderr, "post send error %d\n", ret);
946 /* Wait for the server to say the RDMA Write is complete. */
948 if (cb->state != RDMA_WRITE_COMPLETE) {
949 fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",
956 if (memcmp(cb->start_buf, cb->rdma_buf, cb->size)) {
957 fprintf(stderr, "data mismatch!\n");
963 printf("ping data: %s\n", cb->rdma_buf);
969 static int rping_connect_client(struct rping_cb *cb)
971 struct rdma_conn_param conn_param;
974 memset(&conn_param, 0, sizeof conn_param);
975 conn_param.responder_resources = 1;
976 conn_param.initiator_depth = 1;
977 conn_param.retry_count = 10;
979 ret = rdma_connect(cb->cm_id, &conn_param);
981 perror("rdma_connect");
986 if (cb->state != CONNECTED) {
987 fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);
991 DEBUG_LOG("rmda_connect successful\n");
995 static int rping_bind_client(struct rping_cb *cb)
999 if (cb->sin.ss_family == AF_INET)
1000 ((struct sockaddr_in *) &cb->sin)->sin_port = cb->port;
1002 ((struct sockaddr_in6 *) &cb->sin)->sin6_port = cb->port;
1004 ret = rdma_resolve_addr(cb->cm_id, NULL, (struct sockaddr *) &cb->sin, 2000);
1006 perror("rdma_resolve_addr");
1011 if (cb->state != ROUTE_RESOLVED) {
1012 fprintf(stderr, "waiting for addr/route resolution state %d\n",
1017 DEBUG_LOG("rdma_resolve_addr - rdma_resolve_route successful\n");
1021 static int rping_run_client(struct rping_cb *cb)
1023 struct ibv_recv_wr *bad_wr;
1026 ret = rping_bind_client(cb);
1030 ret = rping_setup_qp(cb, cb->cm_id);
1032 fprintf(stderr, "setup_qp failed: %d\n", ret);
1036 ret = rping_setup_buffers(cb);
1038 fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);
1042 ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);
1044 fprintf(stderr, "ibv_post_recv failed: %d\n", ret);
1048 pthread_create(&cb->cqthread, NULL, cq_thread, cb);
1050 ret = rping_connect_client(cb);
1052 fprintf(stderr, "connect error %d\n", ret);
1056 rping_test_client(cb);
1057 rdma_disconnect(cb->cm_id);
1059 rping_free_buffers(cb);
1066 static int get_addr(char *dst, struct sockaddr *addr)
1068 struct addrinfo *res;
1071 ret = getaddrinfo(dst, NULL, NULL, &res);
1073 printf("getaddrinfo failed - invalid hostname or IP address\n");
1077 if (res->ai_family == PF_INET)
1078 memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in));
1079 else if (res->ai_family == PF_INET6)
1080 memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in6));
1088 static void usage(char *name)
1090 printf("%s -s [-vVd] [-S size] [-C count] [-a addr] [-p port]\n",
1092 printf("%s -c [-vVd] [-S size] [-C count] -a addr [-p port]\n",
1094 printf("\t-c\t\tclient side\n");
1095 printf("\t-s\t\tserver side. To bind to any address with IPv6 use -a ::0\n");
1096 printf("\t-v\t\tdisplay ping data to stdout\n");
1097 printf("\t-V\t\tvalidate ping data\n");
1098 printf("\t-d\t\tdebug printfs\n");
1099 printf("\t-S size \tping data size\n");
1100 printf("\t-C count\tping count times\n");
1101 printf("\t-a addr\t\taddress\n");
1102 printf("\t-p port\t\tport\n");
1103 printf("\t-P\t\tpersistent server mode allowing multiple connections\n");
1106 int main(int argc, char *argv[])
1108 struct rping_cb *cb;
1111 int persistent_server = 0;
1113 cb = malloc(sizeof(*cb));
1117 memset(cb, 0, sizeof(*cb));
1121 cb->sin.ss_family = PF_INET;
1122 cb->port = htons(7174);
1123 sem_init(&cb->sem, 0, 0);
1126 while ((op=getopt(argc, argv, "a:Pp:C:S:t:scvVd")) != -1) {
1129 ret = get_addr(optarg, (struct sockaddr *) &cb->sin);
1132 persistent_server = 1;
1135 cb->port = htons(atoi(optarg));
1136 DEBUG_LOG("port %d\n", (int) atoi(optarg));
1140 DEBUG_LOG("server\n");
1144 DEBUG_LOG("client\n");
1147 cb->size = atoi(optarg);
1148 if ((cb->size < RPING_MIN_BUFSIZE) ||
1149 (cb->size > (RPING_BUFSIZE - 1))) {
1150 fprintf(stderr, "Invalid size %d "
1151 "(valid range is %Zd to %d)\n",
1152 cb->size, RPING_MIN_BUFSIZE, RPING_BUFSIZE);
1155 DEBUG_LOG("size %d\n", (int) atoi(optarg));
1158 cb->count = atoi(optarg);
1159 if (cb->count < 0) {
1160 fprintf(stderr, "Invalid count %d\n",
1164 DEBUG_LOG("count %d\n", (int) cb->count);
1168 DEBUG_LOG("verbose\n");
1172 DEBUG_LOG("validate data\n");
1186 if (cb->server == -1) {
1192 cb->cm_channel = rdma_create_event_channel();
1193 if (!cb->cm_channel) {
1194 perror("rdma_create_event_channel");
1198 ret = rdma_create_id(cb->cm_channel, &cb->cm_id, cb, RDMA_PS_TCP);
1200 perror("rdma_create_id");
1203 DEBUG_LOG("created cm_id %p\n", cb->cm_id);
1205 pthread_create(&cb->cmthread, NULL, cm_thread, cb);
1208 if (persistent_server)
1209 ret = rping_run_persistent_server(cb);
1211 ret = rping_run_server(cb);
1213 ret = rping_run_client(cb);
1215 DEBUG_LOG("destroy cm_id %p\n", cb->cm_id);
1216 rdma_destroy_id(cb->cm_id);
1218 rdma_destroy_event_channel(cb->cm_channel);