aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYishai Hadas <yishaih@mellanox.com>2013-08-21 15:48:57 +0300
committerRoland Dreier <roland@purestorage.com>2013-12-16 11:14:01 -0800
commit850da777643eba60774cb4fb9183974594ec7fd3 (patch)
tree82f6a74c0cca2214be7b221256f6c0046f647379
parentbc5556c0ce997a449c0d9839615d121db47b0fa4 (diff)
downloadlibibverbs-850da777643eba60774cb4fb9183974594ec7fd3.tar.gz
Fix XRC sample application (ibv_xsrq_pingpong) issues
Fix sync issue when clients go down. This prevents a case where the client misses a response from the daemon and then waits forever. Also fix a typo in error message. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
-rw-r--r--examples/xsrq_pingpong.c96
1 files changed, 90 insertions, 6 deletions
diff --git a/examples/xsrq_pingpong.c b/examples/xsrq_pingpong.c
index 984740d..74205ec 100644
--- a/examples/xsrq_pingpong.c
+++ b/examples/xsrq_pingpong.c
@@ -57,6 +57,9 @@
#define MSG_SSCAN "%x:%x:%x:%x:%x"
#define ADDR_FORMAT \
"%8s: LID %04x, QPN RECV %06x SEND %06x, PSN %06x, SRQN %04x\n"
+#define TERMINATION_FORMAT "%s"
+#define TERMINATION_MSG_SIZE 4
+#define TERMINATION_MSG "END"
static int page_size;
struct pingpong_dest {
@@ -67,6 +70,7 @@ struct pingpong_dest {
int send_psn;
int srqn;
int pp_cnt;
+ int sockfd;
};
struct pingpong_context {
@@ -303,6 +307,74 @@ static int pp_init_ctx(char *ib_devname)
return 0;
}
+static int recv_termination_ack(int index)
+{
+ char msg[TERMINATION_MSG_SIZE];
+ int n = 0, r;
+ int sockfd = ctx.rem_dest[index].sockfd;
+
+ while (n < TERMINATION_MSG_SIZE) {
+ r = read(sockfd, msg + n, TERMINATION_MSG_SIZE - n);
+ if (r < 0) {
+ perror("client read");
+ fprintf(stderr,
+ "%d/%d: Couldn't read remote termination ack\n",
+ n, TERMINATION_MSG_SIZE);
+ return 1;
+ }
+ n += r;
+ }
+
+ if (strcmp(msg, TERMINATION_MSG)) {
+ fprintf(stderr, "Invalid termination ack was accepted\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int send_termination_ack(int index)
+{
+ char msg[TERMINATION_MSG_SIZE];
+ int sockfd = ctx.rem_dest[index].sockfd;
+
+ sprintf(msg, TERMINATION_FORMAT, TERMINATION_MSG);
+
+ if (write(sockfd, msg, TERMINATION_MSG_SIZE) != TERMINATION_MSG_SIZE) {
+ fprintf(stderr, "Couldn't send termination ack\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+static int pp_client_termination()
+{
+ if (send_termination_ack(0))
+ return 1;
+ if (recv_termination_ack(0))
+ return 1;
+
+ return 0;
+}
+
+static int pp_server_termination()
+{
+ int i;
+
+ for (i = 0; i < ctx.num_clients; i++) {
+ if (recv_termination_ack(i))
+ return 1;
+ }
+
+ for (i = 0; i < ctx.num_clients; i++) {
+ if (send_termination_ack(i))
+ return 1;
+ }
+
+ return 0;
+}
+
static int send_local_dest(int sockfd, int index)
{
char msg[MSG_SIZE];
@@ -355,6 +427,7 @@ static int recv_remote_dest(int sockfd, int index)
printf(ADDR_FORMAT, "remote", rem_dest->lid, rem_dest->recv_qpn,
rem_dest->send_qpn, rem_dest->send_psn, rem_dest->srqn);
+ rem_dest->sockfd = sockfd;
return 0;
}
@@ -376,7 +449,7 @@ static int connect_qps(int index)
IBV_QP_STATE | IBV_QP_AV | IBV_QP_PATH_MTU |
IBV_QP_DEST_QPN | IBV_QP_RQ_PSN |
IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER)) {
- fprintf(stderr, "Failed to modify send QP[%d] to RTR\n", index);
+ fprintf(stderr, "Failed to modify recv QP[%d] to RTR\n", index);
return 1;
}
@@ -472,8 +545,6 @@ static int pp_client_connect(const char *servername, int port)
if (connect_qps(0))
return 1;
- shutdown(sockfd, SHUT_RDWR);
- close(sockfd);
return 0;
}
@@ -536,9 +607,6 @@ static int pp_server_connect(int port)
if (connect_qps(i))
return 1;
-
- shutdown(connfd, SHUT_RDWR);
- close(connfd);
}
close(sockfd);
@@ -561,6 +629,9 @@ static int pp_close_ctx(void)
fprintf(stderr, "Couldn't destroy TGT QP[%d]\n", i);
return 1;
}
+
+ if (ctx.rem_dest[i].sockfd)
+ close(ctx.rem_dest[i].sockfd);
}
if (ibv_destroy_srq(ctx.srq)) {
@@ -884,6 +955,19 @@ int main(int argc, char *argv[])
if (ctx.use_event)
ibv_ack_cq_events(ctx.recv_cq, num_cq_events);
+ /* Process should get an ack from the daemon to close its resources to
+ * make sure latest daemon's response sent via its target QP destined
+ * to an XSRQ created by another client won't be lost.
+ * Failure to do so may cause the other client to wait for that sent
+ * message forever. See comment on pp_post_send.
+ */
+ if (servername) {
+ if (pp_client_termination())
+ return 1;
+ } else if (pp_server_termination()) {
+ return 1;
+ }
+
if (pp_close_ctx())
return 1;