]> git.openfabrics.org - ~shefty/librdmacm.git/commitdiff
refresh
authorSean Hefty <sean.hefty@intel.com>
Thu, 8 Aug 2013 23:21:50 +0000 (16:21 -0700)
committerSean Hefty <sean.hefty@intel.com>
Thu, 8 Aug 2013 23:21:50 +0000 (16:21 -0700)
meta
patches/refresh-temp [deleted file]
patches/time-ex

diff --git a/meta b/meta
index d9ac2c43019aa9960248656e3ddb89a28cc2172c..a2cb487e217c582014e8fc19270c3ad0c62c9348 100644 (file)
--- a/meta
+++ b/meta
@@ -1,9 +1,8 @@
 Version: 1
-Previous: 01822cc9d2c258e503b2650954ddcc7d46b8b010
-Head: b57defaebf2047961297de3112d1b891a95ac18f
+Previous: b308f5a2162f78207306ae61c8983815132017ff
+Head: 2949a92960546b75c647bcf14fec1f4369fd17fa
 Applied:
-  time-ex: a3a0245f9c372bc5fe47ae70c7d26807f05d8f18
-  refresh-temp: b57defaebf2047961297de3112d1b891a95ac18f
+  time-ex: 2949a92960546b75c647bcf14fec1f4369fd17fa
 Unapplied:
   old-af-ib: d71ebf70cf74111cfd5f0982d9abe6ec68fb38e3
   old-seterr: 47eb0c419687c2690292c1910acae83a46e5388c
diff --git a/patches/refresh-temp b/patches/refresh-temp
deleted file mode 100644 (file)
index 498342b..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-Bottom: a4acfa9cd78aabcf2e9936c67eda92310132be0c
-Top:    668ddd4271538fc243a888fad972f12f0e1bf29d
-Author: Sean Hefty <sean.hefty@intel.com>
-Date:   2013-08-08 16:21:50 -0700
-
-Refresh of time-ex
-
----
-
-diff --git a/examples/cmtime.c b/examples/cmtime.c
-new file mode 100644
-index 0000000..f97ab9e
---- /dev/null
-+++ b/examples/cmtime.c
-@@ -0,0 +1,498 @@
-+/*
-+ * Copyright (c) 2013 Intel Corporation.  All rights reserved.
-+ *
-+ * This software is available to you under the OpenIB.org BSD license
-+ * below:
-+ *
-+ *     Redistribution and use in source and binary forms, with or
-+ *     without modification, are permitted provided that the following
-+ *     conditions are met:
-+ *
-+ *      - Redistributions of source code must retain the above
-+ *        copyright notice, this list of conditions and the following
-+ *        disclaimer.
-+ *
-+ *      - Redistributions in binary form must reproduce the above
-+ *        copyright notice, this list of conditions and the following
-+ *        disclaimer in the documentation and/or other materials
-+ *        provided with the distribution.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
-+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
-+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-+ * SOFTWARE.
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <strings.h>
-+#include <errno.h>
-+#include <getopt.h>
-+#include <sys/types.h>
-+#include <sys/socket.h>
-+#include <sys/time.h>
-+#include <sys/wait.h>
-+#include <netdb.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+#include <netinet/in.h>
-+#include <netinet/tcp.h>
-+
-+#include <rdma/rdma_cma.h>
-+#include "common.h"
-+
-+static struct rdma_addrinfo hints, *rai;
-+static struct rdma_event_channel *channel;
-+static char *port = "7471";
-+static char *dst_addr;
-+static char *src_addr;
-+
-+enum step {
-+      STEP_CREATE_ID,
-+      STEP_RESOLVE_ADDR,
-+      STEP_RESOLVE_ROUTE,
-+      STEP_CREATE_QP,
-+      STEP_CONNECT,
-+      STEP_DISCONNECT,
-+      STEP_DESTROY,
-+      STEP_CNT
-+};
-+
-+static char *step_str[] = {
-+      "create id",
-+      "resolve addr",
-+      "resolve route",
-+      "create qp",
-+      "connect",
-+      "disconnect",
-+      "destroy"
-+};
-+
-+struct node {
-+      struct rdma_cm_id *id;
-+      struct timeval times[STEP_CNT][2];
-+      int error;
-+};
-+
-+static struct node *nodes;
-+static struct timeval times[STEP_CNT][2];
-+static int connections = 100;
-+static int left[STEP_CNT];
-+static struct ibv_qp_init_attr init_qp_attr;
-+static struct rdma_conn_param conn_param;
-+
-+#define start_perf(n, s)      gettimeofday(&((n)->times[s][0]), NULL)
-+#define end_perf(n, s)                gettimeofday(&((n)->times[s][1]), NULL)
-+#define start_time(s)         gettimeofday(&times[s][0], NULL)
-+#define end_time(s)           gettimeofday(&times[s][1], NULL)
-+
-+static int zero_time(struct timeval *t)
-+{
-+      return !(t->tv_sec || t->tv_usec);
-+}
-+
-+static float diff_us(struct timeval *end, struct timeval *start)
-+{
-+      return (end->tv_sec - start->tv_sec) * 1000000. + (end->tv_usec - start->tv_usec);
-+}
-+
-+static void show_perf(void)
-+{
-+      int c, i;
-+      float us, max[STEP_CNT], min[STEP_CNT];
-+
-+      for (i = 0; i < STEP_CNT; i++) {
-+              max[i] = 0;
-+              min[i] = 999999999.;
-+              for (c = 0; c < connections; c++) {
-+                      if (!zero_time(&nodes[c].times[i][0]) &&
-+                          !zero_time(&nodes[c].times[i][1])) {
-+                              us = diff_us(&nodes[c].times[i][1], &nodes[c].times[i][0]);
-+                              if (us > max[i])
-+                                      max[i] = us;
-+                              if (us < min[i])
-+                                      min[i] = us;
-+                      }
-+              }
-+      }
-+
-+      printf("step              total ms     max ms     min us  us / conn\n");
-+      for (i = 0; i < STEP_CNT; i++) {
-+              us = diff_us(&times[i][1], &times[i][0]);
-+              printf("%-13s: %11.2f%11.2f%11.2f%11.2f\n", step_str[i], us / 1000.,
-+                      max[i] / 1000., min[i], us / connections);
-+      }
-+}
-+
-+static void addr_handler(struct node *n)
-+{
-+      end_perf(n, STEP_RESOLVE_ADDR);
-+      left[STEP_RESOLVE_ADDR]--;
-+}
-+
-+static void route_handler(struct node *n)
-+{
-+      end_perf(n, STEP_RESOLVE_ROUTE);
-+      left[STEP_RESOLVE_ROUTE]--;
-+}
-+
-+static void conn_handler(struct node *n)
-+{
-+      end_perf(n, STEP_CONNECT);
-+      left[STEP_CONNECT]--;
-+}
-+
-+static void disc_handler(struct node *n)
-+{
-+      end_perf(n, STEP_DISCONNECT);
-+      left[STEP_DISCONNECT]--;
-+}
-+
-+static int req_handler(struct rdma_cm_id *id)
-+{
-+      int ret;
-+
-+      ret = rdma_create_qp(id, NULL, &init_qp_attr);
-+      if (ret) {
-+              perror("failure creating qp");
-+              goto err;
-+      }
-+
-+      ret = rdma_accept(id, NULL);
-+      if (ret) {
-+              perror("failure accepting");
-+              goto err;
-+      }
-+      return 0;
-+
-+err:
-+      printf("failing connection request\n");
-+      rdma_reject(id, NULL, 0);
-+      return ret;
-+}
-+
-+static void cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
-+{
-+      struct node *n = id->context;
-+
-+      switch (event->event) {
-+      case RDMA_CM_EVENT_ADDR_RESOLVED:
-+              addr_handler(n);
-+              break;
-+      case RDMA_CM_EVENT_ROUTE_RESOLVED:
-+              route_handler(n);
-+              break;
-+      case RDMA_CM_EVENT_CONNECT_REQUEST:
-+              if (req_handler(id)) {
-+                      rdma_ack_cm_event(event);
-+                      rdma_destroy_id(id);
-+                      return;
-+              }
-+              break;
-+      case RDMA_CM_EVENT_ESTABLISHED:
-+              if (n)
-+                      conn_handler(n);
-+              break;
-+      case RDMA_CM_EVENT_ADDR_ERROR:
-+              printf("RDMA_CM_EVENT_ADDR_ERROR, error: %d\n", event->status);
-+              addr_handler(n);
-+              n->error = 1;
-+              break;
-+      case RDMA_CM_EVENT_ROUTE_ERROR:
-+              printf("RDMA_CM_EVENT_ROUTE_ERROR, error: %d\n", event->status);
-+              route_handler(n);
-+              n->error = 1;
-+              break;
-+      case RDMA_CM_EVENT_CONNECT_ERROR:
-+      case RDMA_CM_EVENT_UNREACHABLE:
-+      case RDMA_CM_EVENT_REJECTED:
-+              printf("event: %s, error: %d\n",
-+                     rdma_event_str(event->event), event->status);
-+              conn_handler(n);
-+              n->error = 1;
-+              break;
-+      case RDMA_CM_EVENT_DISCONNECTED:
-+              if (!n) {
-+                      rdma_disconnect(id);
-+                      rdma_ack_cm_event(event);
-+                      rdma_destroy_id(id);
-+                      return;
-+              }
-+              disc_handler(n);
-+              break;
-+      case RDMA_CM_EVENT_DEVICE_REMOVAL:
-+              /* Cleanup will occur after test completes. */
-+              break;
-+      default:
-+              break;
-+      }
-+      rdma_ack_cm_event(event);
-+}
-+
-+static int alloc_nodes(void)
-+{
-+      int ret, i;
-+
-+      nodes = calloc(sizeof *nodes, connections);
-+      if (!nodes)
-+              return -ENOMEM;
-+
-+      printf("creating id\n");
-+      start_time(STEP_CREATE_ID);
-+      for (i = 0; i < connections; i++) {
-+              start_perf(&nodes[i], STEP_CREATE_ID);
-+              if (dst_addr) {
-+                      ret = rdma_create_id(channel, &nodes[i].id, &nodes[i],
-+                                           hints.ai_port_space);
-+                      if (ret)
-+                              goto err;
-+              }
-+              end_perf(&nodes[i], STEP_CREATE_ID);
-+      }
-+      end_time(STEP_CREATE_ID);
-+      return 0;
-+
-+err:
-+      while (--i >= 0)
-+              rdma_destroy_id(nodes[i].id);
-+      free(nodes);
-+      return ret;
-+}
-+
-+static void cleanup_nodes(void)
-+{
-+      int i;
-+
-+      printf("destroying id\n");
-+      start_time(STEP_DESTROY);
-+      for (i = 0; i < connections; i++) {
-+              start_perf(&nodes[i], STEP_DESTROY);
-+              if (nodes[i].id)
-+                      rdma_destroy_id(nodes[i].id);
-+              end_perf(&nodes[i], STEP_DESTROY);
-+      }
-+      end_time(STEP_DESTROY);
-+}
-+
-+static int process_events(int *left)
-+{
-+      struct rdma_cm_event *event;
-+      int ret = 0;
-+
-+      while ((!left || *left) && !ret) {
-+              ret = rdma_get_cm_event(channel, &event);
-+              if (!ret) {
-+                      cma_handler(event->id, event);
-+              } else {
-+                      perror("failure in rdma_get_cm_event in connect events");
-+                      ret = errno;
-+              }
-+      }
-+
-+      return ret;
-+}
-+
-+static int run_server(void)
-+{
-+      struct rdma_cm_id *listen_id;
-+      int ret;
-+
-+      ret = rdma_create_id(channel, &listen_id, NULL, hints.ai_port_space);
-+      if (ret) {
-+              perror("listen request failed");
-+              return ret;
-+      }
-+
-+      ret = get_rdma_addr(src_addr, dst_addr, port, &hints, &rai);
-+      if (ret) {
-+              perror("getrdmaaddr error");
-+              goto out;
-+      }
-+
-+      ret = rdma_bind_addr(listen_id, rai->ai_src_addr);
-+      if (ret) {
-+              perror("bind address failed");
-+              goto out;
-+      }
-+
-+      ret = rdma_listen(listen_id, 0);
-+      if (ret) {
-+              perror("failure trying to listen");
-+              goto out;
-+      }
-+
-+      process_events(NULL);
-+ out:
-+      rdma_destroy_id(listen_id);
-+      return ret;
-+}
-+
-+static int run_client(void)
-+{
-+      int i, ret;
-+
-+      ret = get_rdma_addr(src_addr, dst_addr, port, &hints, &rai);
-+      if (ret) {
-+              perror("getaddrinfo error");
-+              return ret;
-+      }
-+
-+      conn_param.responder_resources = 1;
-+      conn_param.initiator_depth = 1;
-+      conn_param.retry_count = 5;
-+      conn_param.private_data = rai->ai_connect;
-+      conn_param.private_data_len = rai->ai_connect_len;
-+
-+      printf("resolving address\n");
-+      start_time(STEP_RESOLVE_ADDR);
-+      for (i = 0; i < connections; i++) {
-+              start_perf(&nodes[i], STEP_RESOLVE_ADDR);
-+              ret = rdma_resolve_addr(nodes[i].id, rai->ai_src_addr,
-+                                      rai->ai_dst_addr, 2000);
-+              if (ret) {
-+                      perror("failure getting addr");
-+                      nodes[i].error = 1;
-+                      continue;
-+              }
-+              left[STEP_RESOLVE_ADDR]++;
-+      }
-+      ret = process_events(&left[STEP_RESOLVE_ADDR]);
-+      if (ret)
-+              return ret;
-+      end_time(STEP_RESOLVE_ADDR);
-+
-+      printf("resolving route\n");
-+      start_time(STEP_RESOLVE_ROUTE);
-+      for (i = 0; i < connections; i++) {
-+              if (nodes[i].error)
-+                      continue;
-+              start_perf(&nodes[i], STEP_RESOLVE_ROUTE);
-+              ret = rdma_resolve_route(nodes[i].id, 2000);
-+              if (ret) {
-+                      perror("failure resolving route");
-+                      nodes[i].error = 1;
-+                      continue;
-+              }
-+              left[STEP_RESOLVE_ROUTE]++;
-+      }
-+      ret = process_events(&left[STEP_RESOLVE_ROUTE]);
-+      if (ret)
-+              return ret;
-+      end_time(STEP_RESOLVE_ROUTE);
-+
-+      printf("creating qp\n");
-+      start_time(STEP_CREATE_QP);
-+      for (i = 0; i < connections; i++) {
-+              if (nodes[i].error)
-+                      continue;
-+              start_perf(&nodes[i], STEP_CREATE_QP);
-+              ret = rdma_create_qp(nodes[i].id, NULL, &init_qp_attr);
-+              if (ret) {
-+                      perror("failure creating qp");
-+                      nodes[i].error = 1;
-+                      continue;
-+              }
-+              end_perf(&nodes[i], STEP_CREATE_QP);
-+      }
-+      end_time(STEP_CREATE_QP);
-+
-+      printf("connecting\n");
-+      start_time(STEP_CONNECT);
-+      for (i = 0; i < connections; i++) {
-+              if (nodes[i].error)
-+                      continue;
-+              start_perf(&nodes[i], STEP_CONNECT);
-+              ret = rdma_connect(nodes[i].id, &conn_param);
-+              if (ret) {
-+                      perror("failure rconnecting");
-+                      nodes[i].error = 1;
-+                      continue;
-+              }
-+              left[STEP_CONNECT]++;
-+      }
-+      ret = process_events(&left[STEP_CONNECT]);
-+      if (ret)
-+              return ret;
-+      end_time(STEP_CONNECT);
-+
-+      printf("disconnecting\n");
-+      start_time(STEP_DISCONNECT);
-+      for (i = 0; i < connections; i++) {
-+              if (nodes[i].error)
-+                      continue;
-+              start_perf(&nodes[i], STEP_DISCONNECT);
-+              rdma_disconnect(nodes[i].id);
-+              left[STEP_DISCONNECT]++;
-+      }
-+      ret = process_events(&left[STEP_DISCONNECT]);
-+      if (ret)
-+              return ret;
-+      end_time(STEP_DISCONNECT);
-+
-+      return ret;
-+}
-+
-+int main(int argc, char **argv)
-+{
-+      int op, ret;
-+
-+      hints.ai_port_space = RDMA_PS_TCP;
-+      hints.ai_qp_type = IBV_QPT_RC;
-+      while ((op = getopt(argc, argv, "s:b:c:p:")) != -1) {
-+              switch (op) {
-+              case 's':
-+                      dst_addr = optarg;
-+                      break;
-+              case 'b':
-+                      src_addr = optarg;
-+                      break;
-+              case 'c':
-+                      connections = atoi(optarg);
-+                      break;
-+              case 'p':
-+                      port = optarg;
-+                      break;
-+              default:
-+                      printf("usage: %s\n", argv[0]);
-+                      printf("\t[-s server_address]\n");
-+                      printf("\t[-b bind_address]\n");
-+                      printf("\t[-c connections]\n");
-+                      printf("\t[-p port_number]\n");
-+                      exit(1);
-+              }
-+      }
-+
-+      init_qp_attr.cap.max_send_wr = 1;
-+      init_qp_attr.cap.max_recv_wr = 1;
-+      init_qp_attr.cap.max_send_sge = 1;
-+      init_qp_attr.cap.max_recv_sge = 1;
-+      init_qp_attr.qp_type = IBV_QPT_RC;
-+
-+      channel = rdma_create_event_channel();
-+      if (!channel) {
-+              printf("failed to create event channel\n");
-+              exit(1);
-+      }
-+
-+      if (dst_addr) {
-+              alloc_nodes();
-+              ret = run_client();
-+      } else {
-+              hints.ai_flags |= RAI_PASSIVE;
-+              ret = run_server();
-+      }
-+
-+      cleanup_nodes();
-+      rdma_destroy_event_channel(channel);
-+      if (rai)
-+              rdma_freeaddrinfo(rai);
-+
-+      show_perf();
-+      free(nodes);
-+      return ret;
-+}
index 740079af66e278d27a332dbefaae3a6f3f93fc46..5d92237d6d18e11a4bb3e89ad077bc881cadb8f9 100644 (file)
@@ -1,5 +1,5 @@
 Bottom: 2ab79436b858f0bf24ff91555665a0823faef381
-Top:    a4acfa9cd78aabcf2e9936c67eda92310132be0c
+Top:    668ddd4271538fc243a888fad972f12f0e1bf29d
 Author: Sean Hefty <sean.hefty@intel.com>
 Date:   2013-08-05 10:57:43 -0700
 
@@ -37,3 +37,507 @@ index e1be9f3..4e3dee7 100644
  
  librdmacmincludedir = $(includedir)/rdma
  infinibandincludedir = $(includedir)/infiniband
+diff --git a/examples/cmtime.c b/examples/cmtime.c
+new file mode 100644
+index 0000000..f97ab9e
+--- /dev/null
++++ b/examples/cmtime.c
+@@ -0,0 +1,498 @@
++/*
++ * Copyright (c) 2013 Intel Corporation.  All rights reserved.
++ *
++ * This software is available to you under the OpenIB.org BSD license
++ * below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <strings.h>
++#include <errno.h>
++#include <getopt.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/time.h>
++#include <sys/wait.h>
++#include <netdb.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <netinet/in.h>
++#include <netinet/tcp.h>
++
++#include <rdma/rdma_cma.h>
++#include "common.h"
++
++static struct rdma_addrinfo hints, *rai;
++static struct rdma_event_channel *channel;
++static char *port = "7471";
++static char *dst_addr;
++static char *src_addr;
++
++enum step {
++      STEP_CREATE_ID,
++      STEP_RESOLVE_ADDR,
++      STEP_RESOLVE_ROUTE,
++      STEP_CREATE_QP,
++      STEP_CONNECT,
++      STEP_DISCONNECT,
++      STEP_DESTROY,
++      STEP_CNT
++};
++
++static char *step_str[] = {
++      "create id",
++      "resolve addr",
++      "resolve route",
++      "create qp",
++      "connect",
++      "disconnect",
++      "destroy"
++};
++
++struct node {
++      struct rdma_cm_id *id;
++      struct timeval times[STEP_CNT][2];
++      int error;
++};
++
++static struct node *nodes;
++static struct timeval times[STEP_CNT][2];
++static int connections = 100;
++static int left[STEP_CNT];
++static struct ibv_qp_init_attr init_qp_attr;
++static struct rdma_conn_param conn_param;
++
++#define start_perf(n, s)      gettimeofday(&((n)->times[s][0]), NULL)
++#define end_perf(n, s)                gettimeofday(&((n)->times[s][1]), NULL)
++#define start_time(s)         gettimeofday(&times[s][0], NULL)
++#define end_time(s)           gettimeofday(&times[s][1], NULL)
++
++static int zero_time(struct timeval *t)
++{
++      return !(t->tv_sec || t->tv_usec);
++}
++
++static float diff_us(struct timeval *end, struct timeval *start)
++{
++      return (end->tv_sec - start->tv_sec) * 1000000. + (end->tv_usec - start->tv_usec);
++}
++
++static void show_perf(void)
++{
++      int c, i;
++      float us, max[STEP_CNT], min[STEP_CNT];
++
++      for (i = 0; i < STEP_CNT; i++) {
++              max[i] = 0;
++              min[i] = 999999999.;
++              for (c = 0; c < connections; c++) {
++                      if (!zero_time(&nodes[c].times[i][0]) &&
++                          !zero_time(&nodes[c].times[i][1])) {
++                              us = diff_us(&nodes[c].times[i][1], &nodes[c].times[i][0]);
++                              if (us > max[i])
++                                      max[i] = us;
++                              if (us < min[i])
++                                      min[i] = us;
++                      }
++              }
++      }
++
++      printf("step              total ms     max ms     min us  us / conn\n");
++      for (i = 0; i < STEP_CNT; i++) {
++              us = diff_us(&times[i][1], &times[i][0]);
++              printf("%-13s: %11.2f%11.2f%11.2f%11.2f\n", step_str[i], us / 1000.,
++                      max[i] / 1000., min[i], us / connections);
++      }
++}
++
++static void addr_handler(struct node *n)
++{
++      end_perf(n, STEP_RESOLVE_ADDR);
++      left[STEP_RESOLVE_ADDR]--;
++}
++
++static void route_handler(struct node *n)
++{
++      end_perf(n, STEP_RESOLVE_ROUTE);
++      left[STEP_RESOLVE_ROUTE]--;
++}
++
++static void conn_handler(struct node *n)
++{
++      end_perf(n, STEP_CONNECT);
++      left[STEP_CONNECT]--;
++}
++
++static void disc_handler(struct node *n)
++{
++      end_perf(n, STEP_DISCONNECT);
++      left[STEP_DISCONNECT]--;
++}
++
++static int req_handler(struct rdma_cm_id *id)
++{
++      int ret;
++
++      ret = rdma_create_qp(id, NULL, &init_qp_attr);
++      if (ret) {
++              perror("failure creating qp");
++              goto err;
++      }
++
++      ret = rdma_accept(id, NULL);
++      if (ret) {
++              perror("failure accepting");
++              goto err;
++      }
++      return 0;
++
++err:
++      printf("failing connection request\n");
++      rdma_reject(id, NULL, 0);
++      return ret;
++}
++
++static void cma_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
++{
++      struct node *n = id->context;
++
++      switch (event->event) {
++      case RDMA_CM_EVENT_ADDR_RESOLVED:
++              addr_handler(n);
++              break;
++      case RDMA_CM_EVENT_ROUTE_RESOLVED:
++              route_handler(n);
++              break;
++      case RDMA_CM_EVENT_CONNECT_REQUEST:
++              if (req_handler(id)) {
++                      rdma_ack_cm_event(event);
++                      rdma_destroy_id(id);
++                      return;
++              }
++              break;
++      case RDMA_CM_EVENT_ESTABLISHED:
++              if (n)
++                      conn_handler(n);
++              break;
++      case RDMA_CM_EVENT_ADDR_ERROR:
++              printf("RDMA_CM_EVENT_ADDR_ERROR, error: %d\n", event->status);
++              addr_handler(n);
++              n->error = 1;
++              break;
++      case RDMA_CM_EVENT_ROUTE_ERROR:
++              printf("RDMA_CM_EVENT_ROUTE_ERROR, error: %d\n", event->status);
++              route_handler(n);
++              n->error = 1;
++              break;
++      case RDMA_CM_EVENT_CONNECT_ERROR:
++      case RDMA_CM_EVENT_UNREACHABLE:
++      case RDMA_CM_EVENT_REJECTED:
++              printf("event: %s, error: %d\n",
++                     rdma_event_str(event->event), event->status);
++              conn_handler(n);
++              n->error = 1;
++              break;
++      case RDMA_CM_EVENT_DISCONNECTED:
++              if (!n) {
++                      rdma_disconnect(id);
++                      rdma_ack_cm_event(event);
++                      rdma_destroy_id(id);
++                      return;
++              }
++              disc_handler(n);
++              break;
++      case RDMA_CM_EVENT_DEVICE_REMOVAL:
++              /* Cleanup will occur after test completes. */
++              break;
++      default:
++              break;
++      }
++      rdma_ack_cm_event(event);
++}
++
++static int alloc_nodes(void)
++{
++      int ret, i;
++
++      nodes = calloc(sizeof *nodes, connections);
++      if (!nodes)
++              return -ENOMEM;
++
++      printf("creating id\n");
++      start_time(STEP_CREATE_ID);
++      for (i = 0; i < connections; i++) {
++              start_perf(&nodes[i], STEP_CREATE_ID);
++              if (dst_addr) {
++                      ret = rdma_create_id(channel, &nodes[i].id, &nodes[i],
++                                           hints.ai_port_space);
++                      if (ret)
++                              goto err;
++              }
++              end_perf(&nodes[i], STEP_CREATE_ID);
++      }
++      end_time(STEP_CREATE_ID);
++      return 0;
++
++err:
++      while (--i >= 0)
++              rdma_destroy_id(nodes[i].id);
++      free(nodes);
++      return ret;
++}
++
++static void cleanup_nodes(void)
++{
++      int i;
++
++      printf("destroying id\n");
++      start_time(STEP_DESTROY);
++      for (i = 0; i < connections; i++) {
++              start_perf(&nodes[i], STEP_DESTROY);
++              if (nodes[i].id)
++                      rdma_destroy_id(nodes[i].id);
++              end_perf(&nodes[i], STEP_DESTROY);
++      }
++      end_time(STEP_DESTROY);
++}
++
++static int process_events(int *left)
++{
++      struct rdma_cm_event *event;
++      int ret = 0;
++
++      while ((!left || *left) && !ret) {
++              ret = rdma_get_cm_event(channel, &event);
++              if (!ret) {
++                      cma_handler(event->id, event);
++              } else {
++                      perror("failure in rdma_get_cm_event in connect events");
++                      ret = errno;
++              }
++      }
++
++      return ret;
++}
++
++static int run_server(void)
++{
++      struct rdma_cm_id *listen_id;
++      int ret;
++
++      ret = rdma_create_id(channel, &listen_id, NULL, hints.ai_port_space);
++      if (ret) {
++              perror("listen request failed");
++              return ret;
++      }
++
++      ret = get_rdma_addr(src_addr, dst_addr, port, &hints, &rai);
++      if (ret) {
++              perror("getrdmaaddr error");
++              goto out;
++      }
++
++      ret = rdma_bind_addr(listen_id, rai->ai_src_addr);
++      if (ret) {
++              perror("bind address failed");
++              goto out;
++      }
++
++      ret = rdma_listen(listen_id, 0);
++      if (ret) {
++              perror("failure trying to listen");
++              goto out;
++      }
++
++      process_events(NULL);
++ out:
++      rdma_destroy_id(listen_id);
++      return ret;
++}
++
++static int run_client(void)
++{
++      int i, ret;
++
++      ret = get_rdma_addr(src_addr, dst_addr, port, &hints, &rai);
++      if (ret) {
++              perror("getaddrinfo error");
++              return ret;
++      }
++
++      conn_param.responder_resources = 1;
++      conn_param.initiator_depth = 1;
++      conn_param.retry_count = 5;
++      conn_param.private_data = rai->ai_connect;
++      conn_param.private_data_len = rai->ai_connect_len;
++
++      printf("resolving address\n");
++      start_time(STEP_RESOLVE_ADDR);
++      for (i = 0; i < connections; i++) {
++              start_perf(&nodes[i], STEP_RESOLVE_ADDR);
++              ret = rdma_resolve_addr(nodes[i].id, rai->ai_src_addr,
++                                      rai->ai_dst_addr, 2000);
++              if (ret) {
++                      perror("failure getting addr");
++                      nodes[i].error = 1;
++                      continue;
++              }
++              left[STEP_RESOLVE_ADDR]++;
++      }
++      ret = process_events(&left[STEP_RESOLVE_ADDR]);
++      if (ret)
++              return ret;
++      end_time(STEP_RESOLVE_ADDR);
++
++      printf("resolving route\n");
++      start_time(STEP_RESOLVE_ROUTE);
++      for (i = 0; i < connections; i++) {
++              if (nodes[i].error)
++                      continue;
++              start_perf(&nodes[i], STEP_RESOLVE_ROUTE);
++              ret = rdma_resolve_route(nodes[i].id, 2000);
++              if (ret) {
++                      perror("failure resolving route");
++                      nodes[i].error = 1;
++                      continue;
++              }
++              left[STEP_RESOLVE_ROUTE]++;
++      }
++      ret = process_events(&left[STEP_RESOLVE_ROUTE]);
++      if (ret)
++              return ret;
++      end_time(STEP_RESOLVE_ROUTE);
++
++      printf("creating qp\n");
++      start_time(STEP_CREATE_QP);
++      for (i = 0; i < connections; i++) {
++              if (nodes[i].error)
++                      continue;
++              start_perf(&nodes[i], STEP_CREATE_QP);
++              ret = rdma_create_qp(nodes[i].id, NULL, &init_qp_attr);
++              if (ret) {
++                      perror("failure creating qp");
++                      nodes[i].error = 1;
++                      continue;
++              }
++              end_perf(&nodes[i], STEP_CREATE_QP);
++      }
++      end_time(STEP_CREATE_QP);
++
++      printf("connecting\n");
++      start_time(STEP_CONNECT);
++      for (i = 0; i < connections; i++) {
++              if (nodes[i].error)
++                      continue;
++              start_perf(&nodes[i], STEP_CONNECT);
++              ret = rdma_connect(nodes[i].id, &conn_param);
++              if (ret) {
++                      perror("failure rconnecting");
++                      nodes[i].error = 1;
++                      continue;
++              }
++              left[STEP_CONNECT]++;
++      }
++      ret = process_events(&left[STEP_CONNECT]);
++      if (ret)
++              return ret;
++      end_time(STEP_CONNECT);
++
++      printf("disconnecting\n");
++      start_time(STEP_DISCONNECT);
++      for (i = 0; i < connections; i++) {
++              if (nodes[i].error)
++                      continue;
++              start_perf(&nodes[i], STEP_DISCONNECT);
++              rdma_disconnect(nodes[i].id);
++              left[STEP_DISCONNECT]++;
++      }
++      ret = process_events(&left[STEP_DISCONNECT]);
++      if (ret)
++              return ret;
++      end_time(STEP_DISCONNECT);
++
++      return ret;
++}
++
++int main(int argc, char **argv)
++{
++      int op, ret;
++
++      hints.ai_port_space = RDMA_PS_TCP;
++      hints.ai_qp_type = IBV_QPT_RC;
++      while ((op = getopt(argc, argv, "s:b:c:p:")) != -1) {
++              switch (op) {
++              case 's':
++                      dst_addr = optarg;
++                      break;
++              case 'b':
++                      src_addr = optarg;
++                      break;
++              case 'c':
++                      connections = atoi(optarg);
++                      break;
++              case 'p':
++                      port = optarg;
++                      break;
++              default:
++                      printf("usage: %s\n", argv[0]);
++                      printf("\t[-s server_address]\n");
++                      printf("\t[-b bind_address]\n");
++                      printf("\t[-c connections]\n");
++                      printf("\t[-p port_number]\n");
++                      exit(1);
++              }
++      }
++
++      init_qp_attr.cap.max_send_wr = 1;
++      init_qp_attr.cap.max_recv_wr = 1;
++      init_qp_attr.cap.max_send_sge = 1;
++      init_qp_attr.cap.max_recv_sge = 1;
++      init_qp_attr.qp_type = IBV_QPT_RC;
++
++      channel = rdma_create_event_channel();
++      if (!channel) {
++              printf("failed to create event channel\n");
++              exit(1);
++      }
++
++      if (dst_addr) {
++              alloc_nodes();
++              ret = run_client();
++      } else {
++              hints.ai_flags |= RAI_PASSIVE;
++              ret = run_server();
++      }
++
++      cleanup_nodes();
++      rdma_destroy_event_channel(channel);
++      if (rai)
++              rdma_freeaddrinfo(rai);
++
++      show_perf();
++      free(nodes);
++      return ret;
++}