diff --git a/examples/01-connection/client.c b/examples/01-connection/client.c index 3930e946ff..ee974660b9 100644 --- a/examples/01-connection/client.c +++ b/examples/01-connection/client.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2021, Intel Corporation */ /* * client.c -- a client of the connection example @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -16,6 +17,16 @@ #define main client_main #endif +#define MAX_RETRY 10 +#define RETRY_DELAY 5 + +static inline void +conn_drop_and_delete(struct rpma_conn **conn_ptr) +{ + (void) rpma_conn_disconnect(*conn_ptr); + (void) rpma_conn_delete(conn_ptr); +} + int main(int argc, char *argv[]) { @@ -52,30 +63,58 @@ main(int argc, char *argv[]) if (ret) return ret; - /* create a connection request */ - ret = rpma_conn_req_new(peer, addr, port, NULL, &req); - if (ret) - goto err_peer_delete; - - /* connect the connection request and obtain the connection object */ + /* prepare a connection's private data */ const char *msg = "Hello server!"; struct rpma_conn_private_data pdata; pdata.ptr = (void *)msg; pdata.len = (strlen(msg) + 1) * sizeof(char); - ret = rpma_conn_req_connect(&req, &pdata, &conn); - if (ret) - goto err_req_delete; - /* wait for the connection to establish */ - ret = rpma_conn_next_event(conn, &conn_event); - if (ret) { - goto err_conn_delete; - } else if (conn_event != RPMA_CONN_ESTABLISHED) { - fprintf(stderr, - "rpma_conn_next_event returned an unexpected event\n"); - goto err_conn_delete; + for (int retry = 0; retry < MAX_RETRY; retry++) { + /* create a connection request */ + ret = rpma_conn_req_new(peer, addr, port, NULL, &req); + if (ret) { + conn_drop_and_delete(&conn); + break; + } + + ret = rpma_conn_req_connect(&req, &pdata, &conn); + if (ret) { + conn_drop_and_delete(&conn); + if (req) + (void) rpma_conn_req_delete(&req); + break; + } + + /* wait for the connection to establish */ + ret = rpma_conn_next_event(conn, &conn_event); + if (ret) { + conn_drop_and_delete(&conn); + break; + } else if (conn_event == RPMA_CONN_ESTABLISHED) { + break; + } else if (conn_event == RPMA_CONN_REJECTED) { + conn_drop_and_delete(&conn); + if (retry < MAX_RETRY - 1) { + /* Wait for the server */ + fprintf(stderr, "Retrying...\n"); + sleep(RETRY_DELAY); + } else { + fprintf(stderr, + "The retry number exceeded. Closing.\n"); + break; + } + } else { + fprintf(stderr, + "rpma_conn_next_event returned an unexpected event: %s\n", + rpma_utils_conn_event_2str(conn_event)); + conn_drop_and_delete(&conn); + break; + } } + if (conn == NULL) + goto err_peer_delete; + /* here you can use the newly established connection */ (void) rpma_conn_get_private_data(conn, &pdata); if (pdata.ptr) { @@ -116,7 +155,6 @@ main(int argc, char *argv[]) (void) rpma_conn_disconnect(conn); err_conn_delete: (void) rpma_conn_delete(&conn); -err_req_delete: if (req) (void) rpma_conn_req_delete(&req); err_peer_delete: diff --git a/src/conn.c b/src/conn.c index 1405bef234..61898f75c2 100644 --- a/src/conn.c +++ b/src/conn.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2021, Intel Corporation */ /* * conn.c -- librpma connection-related implementations @@ -173,6 +173,9 @@ rpma_conn_next_event(struct rpma_conn *conn, enum rpma_conn_event *event) case RDMA_CM_EVENT_TIMEWAIT_EXIT: *event = RPMA_CONN_CLOSED; break; + case RDMA_CM_EVENT_REJECTED: + *event = RPMA_CONN_REJECTED; + break; default: RPMA_LOG_WARNING("%s: %s", rpma_utils_conn_event_2str(*event), diff --git a/src/include/librpma.h b/src/include/librpma.h index 8bd35a9385..c04ab15a31 100644 --- a/src/include/librpma.h +++ b/src/include/librpma.h @@ -1430,7 +1430,8 @@ enum rpma_conn_event { RPMA_CONN_UNDEFINED = -1, /* Undefined connection event */ RPMA_CONN_ESTABLISHED, /* Connection established */ RPMA_CONN_CLOSED, /* Connection closed */ - RPMA_CONN_LOST /* Connection lost */ + RPMA_CONN_LOST, /* Connection lost */ + RPMA_CONN_REJECTED /* Connection rejected */ }; /** 3 @@ -1446,6 +1447,7 @@ enum rpma_conn_event { * RPMA_CONN_ESTABLISHED, * RPMA_CONN_CLOSED, * RPMA_CONN_LOST, + * RPMA_CONN_REJECTED, * }; * * int rpma_conn_next_event(struct rpma_conn *conn, @@ -1458,6 +1460,7 @@ enum rpma_conn_event { * - RPMA_CONN_ESTABLISHED - connection established * - RPMA_CONN_CLOSED - connection closed * - RPMA_CONN_LOST - connection lost + * - RPMA_CONN_REJECTED - connection rejected * * RETURN VALUE * The rpma_conn_next_event() function returns 0 on success or a negative diff --git a/src/rpma.c b/src/rpma.c index 54e65fc95c..1d1063db23 100644 --- a/src/rpma.c +++ b/src/rpma.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2021, Intel Corporation */ /* * rpma.c -- entry points for librpma @@ -127,6 +127,8 @@ rpma_utils_conn_event_2str(enum rpma_conn_event conn_event) return "Connection closed"; case RPMA_CONN_LOST: return "Connection lost"; + case RPMA_CONN_REJECTED: + return "Connection rejected"; default: return "Unsupported connection event"; } diff --git a/tests/unit/conn/conn-next_event.c b/tests/unit/conn/conn-next_event.c index 477c752fad..31f09da06d 100644 --- a/tests/unit/conn/conn-next_event.c +++ b/tests/unit/conn/conn-next_event.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2021, Intel Corporation */ /* * conn-next-event.c -- the connection next_event unit tests @@ -99,17 +99,17 @@ next_event__get_cm_event_ENODATA(void **cstate_ptr) } /* - * next_event__event_REJECTED - - * RDMA_CM_EVENT_REJECTED is unexpected + * next_event__event_UNREACHABLE - + * RDMA_CM_EVENT_UNREACHABLE is unexpected */ static void -next_event__event_REJECTED(void **cstate_ptr) +next_event__event_UNREACHABLE(void **cstate_ptr) { struct conn_test_state *cstate = *cstate_ptr; expect_value(rdma_get_cm_event, channel, MOCK_EVCH); struct rdma_cm_event event; - event.event = RDMA_CM_EVENT_REJECTED; + event.event = RDMA_CM_EVENT_UNREACHABLE; will_return(rdma_get_cm_event, &event); expect_value(rdma_ack_cm_event, event, &event); @@ -125,18 +125,18 @@ next_event__event_REJECTED(void **cstate_ptr) } /* - * next_event__event_REJECTED_ack_EINVAL - + * next_event__event_UNREACHABLE_ack_EINVAL - * rdma_ack_cm_event() fails with EINVAL after obtaining - * an RDMA_CM_EVENT_REJECTED event + * an RDMA_CM_EVENT_UNREACHABLE event */ static void -next_event__event_REJECTED_ack_EINVAL(void **cstate_ptr) +next_event__event_UNREACHABLE_ack_EINVAL(void **cstate_ptr) { struct conn_test_state *cstate = *cstate_ptr; expect_value(rdma_get_cm_event, channel, MOCK_EVCH); struct rdma_cm_event event; - event.event = RDMA_CM_EVENT_REJECTED; + event.event = RDMA_CM_EVENT_UNREACHABLE; will_return(rdma_get_cm_event, &event); expect_value(rdma_ack_cm_event, event, &event); @@ -504,6 +504,31 @@ next_event__success_TIMEWAIT_EXIT(void **cstate_ptr) assert_int_equal(c_event, RPMA_CONN_CLOSED); } +/* + * next_event__success_REJECTED - happy day scenario + */ +static void +next_event__success_REJECTED(void **cstate_ptr) +{ + struct conn_test_state *cstate = *cstate_ptr; + + expect_value(rdma_get_cm_event, channel, MOCK_EVCH); + struct rdma_cm_event event; + event.event = RDMA_CM_EVENT_REJECTED; + will_return(rdma_get_cm_event, &event); + + expect_value(rdma_ack_cm_event, event, &event); + will_return(rdma_ack_cm_event, MOCK_OK); + + /* run test */ + enum rpma_conn_event c_event = RPMA_CONN_UNDEFINED; + int ret = rpma_conn_next_event(cstate->conn, &c_event); + + /* verify the results */ + assert_int_equal(ret, MOCK_OK); + assert_int_equal(c_event, RPMA_CONN_REJECTED); +} + static const struct CMUnitTest tests_next_event[] = { /* rpma_conn_next_event() unit tests */ cmocka_unit_test(next_event__conn_NULL), @@ -518,10 +543,10 @@ static const struct CMUnitTest tests_next_event[] = { next_event__get_cm_event_ENODATA, setup__conn_new, teardown__conn_delete), cmocka_unit_test_setup_teardown( - next_event__event_REJECTED, + next_event__event_UNREACHABLE, setup__conn_new, teardown__conn_delete), cmocka_unit_test_setup_teardown( - next_event__event_REJECTED_ack_EINVAL, + next_event__event_UNREACHABLE_ack_EINVAL, setup__conn_new, teardown__conn_delete), cmocka_unit_test_setup_teardown( next_event__data_store_ENOMEM, @@ -550,6 +575,9 @@ static const struct CMUnitTest tests_next_event[] = { cmocka_unit_test_setup_teardown( next_event__success_TIMEWAIT_EXIT, setup__conn_new, teardown__conn_delete), + cmocka_unit_test_setup_teardown( + next_event__success_REJECTED, + setup__conn_new, teardown__conn_delete), cmocka_unit_test(NULL) }; diff --git a/tests/unit/utils/utils-conn_event_2str.c b/tests/unit/utils/utils-conn_event_2str.c index 9a7bac355d..42007fbc8e 100644 --- a/tests/unit/utils/utils-conn_event_2str.c +++ b/tests/unit/utils/utils-conn_event_2str.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: BSD-3-Clause -/* Copyright 2020, Intel Corporation */ +/* Copyright 2020-2021, Intel Corporation */ /* * utils-conn_event_2str.c -- a unit test for rpma_utils_conn_event_2str() @@ -52,6 +52,17 @@ conn_event_2str__CONN_LOST(void **unused) "Connection lost"); } +/* + * conn_event_2str__CONN_REJECTED - sanity test for + * rpma_utils_conn_event_2str() + */ +static void +conn_event_2str__CONN_REJECTED(void **unused) +{ + assert_string_equal(rpma_utils_conn_event_2str(RPMA_CONN_REJECTED), + "Connection rejected"); +} + /* * conn_event_2str__CONN_UNSUPPORTED - sanity test for * rpma_utils_conn_event_2str() @@ -72,6 +83,7 @@ main(int argc, char *argv[]) cmocka_unit_test(conn_event_2str__CONN_ESTABLISHED), cmocka_unit_test(conn_event_2str__CONN_CLOSED), cmocka_unit_test(conn_event_2str__CONN_LOST), + cmocka_unit_test(conn_event_2str__CONN_REJECTED), cmocka_unit_test(conn_event_2str__CONN_UNSUPPORTED), };