diff --git a/include/spdk/sock.h b/include/spdk/sock.h index 282d224cb..0788c6e9e 100644 --- a/include/spdk/sock.h +++ b/include/spdk/sock.h @@ -195,6 +195,15 @@ bool spdk_sock_is_ipv6(struct spdk_sock *sock); */ bool spdk_sock_is_ipv4(struct spdk_sock *sock); +/** + * Check whether the socket is currently connected. + * + * \param sock Socket to check + * + * \return true if the socket is connected or false otherwise. + */ +bool spdk_sock_is_connected(struct spdk_sock *sock); + /** * Callback function for spdk_sock_group_add_sock(). * diff --git a/include/spdk_internal/sock.h b/include/spdk_internal/sock.h index 095eba803..1437991a4 100644 --- a/include/spdk_internal/sock.h +++ b/include/spdk_internal/sock.h @@ -86,6 +86,7 @@ struct spdk_net_impl { bool (*is_ipv6)(struct spdk_sock *sock); bool (*is_ipv4)(struct spdk_sock *sock); + bool (*is_connected)(struct spdk_sock *sock); int (*get_placement_id)(struct spdk_sock *sock, int *placement_id); struct spdk_sock_group_impl *(*group_impl_create)(void); diff --git a/lib/sock/sock.c b/lib/sock/sock.c index f82e3f521..b312a34ef 100644 --- a/lib/sock/sock.c +++ b/lib/sock/sock.c @@ -308,6 +308,12 @@ spdk_sock_is_ipv4(struct spdk_sock *sock) return sock->net_impl->is_ipv4(sock); } +bool +spdk_sock_is_connected(struct spdk_sock *sock) +{ + return sock->net_impl->is_connected(sock); +} + struct spdk_sock_group * spdk_sock_group_create(void *ctx) { diff --git a/module/sock/posix/posix.c b/module/sock/posix/posix.c index f6bb493cb..76598ad3d 100644 --- a/module/sock/posix/posix.c +++ b/module/sock/posix/posix.c @@ -529,6 +529,29 @@ spdk_posix_sock_is_ipv4(struct spdk_sock *_sock) return (sa.ss_family == AF_INET); } +static bool +spdk_posix_sock_is_connected(struct spdk_sock *_sock) +{ + struct spdk_posix_sock *sock = __posix_sock(_sock); + uint8_t byte; + int rc; + + rc = recv(sock->fd, &byte, 1, MSG_PEEK); + if (rc == 0) { + return false; + } + + if (rc < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) { + return true; + } + + return false; + } + + return true; +} + static int spdk_posix_sock_get_placement_id(struct spdk_sock *_sock, int *placement_id) { @@ -686,6 +709,7 @@ static struct spdk_net_impl g_posix_net_impl = { .set_priority = spdk_posix_sock_set_priority, .is_ipv6 = spdk_posix_sock_is_ipv6, .is_ipv4 = spdk_posix_sock_is_ipv4, + .is_connected = spdk_posix_sock_is_connected, .get_placement_id = spdk_posix_sock_get_placement_id, .group_impl_create = spdk_posix_sock_group_impl_create, .group_impl_add_sock = spdk_posix_sock_group_impl_add_sock, diff --git a/module/sock/vpp/vpp.c b/module/sock/vpp/vpp.c index 23ec19aa4..d12b57607 100644 --- a/module/sock/vpp/vpp.c +++ b/module/sock/vpp/vpp.c @@ -1006,6 +1006,14 @@ spdk_vpp_sock_is_ipv4(struct spdk_sock *_sock) return __vpp_session(_sock)->app_session.transport.is_ip4; } +static bool +spdk_vpp_sock_is_connected(struct spdk_sock *_sock) +{ + assert(g_svm.vpp_initialized); + + return (__vpp_session(_sock)->app_session.session_state == VPP_SESSION_STATE_READY); +} + static int spdk_vpp_sock_get_placement_id(struct spdk_sock *_sock, int *placement_id) { @@ -1440,6 +1448,7 @@ static struct spdk_net_impl g_vpp_net_impl = { .set_priority = spdk_vpp_sock_set_priority, .is_ipv6 = spdk_vpp_sock_is_ipv6, .is_ipv4 = spdk_vpp_sock_is_ipv4, + .is_connected = spdk_vpp_sock_is_connected, .get_placement_id = spdk_vpp_sock_get_placement_id, .group_impl_create = spdk_vpp_sock_group_impl_create, .group_impl_add_sock = spdk_vpp_sock_group_impl_add_sock, diff --git a/test/common/lib/test_sock.c b/test/common/lib/test_sock.c index b63e0d154..35255b1b3 100644 --- a/test/common/lib/test_sock.c +++ b/test/common/lib/test_sock.c @@ -50,6 +50,7 @@ DEFINE_STUB(spdk_sock_set_recvbuf, int, (struct spdk_sock *sock, int sz), 0); DEFINE_STUB(spdk_sock_set_sendbuf, int, (struct spdk_sock *sock, int sz), 0); DEFINE_STUB(spdk_sock_is_ipv6, bool, (struct spdk_sock *sock), false); DEFINE_STUB(spdk_sock_is_ipv4, bool, (struct spdk_sock *sock), true); +DEFINE_STUB(spdk_sock_is_connected, bool, (struct spdk_sock *sock), true); DEFINE_STUB(spdk_sock_group_create, struct spdk_sock_group *, (void *ctx), NULL); DEFINE_STUB(spdk_sock_group_add_sock, int, (struct spdk_sock_group *group, struct spdk_sock *sock, spdk_sock_cb cb_fn, void *cb_arg), 0); diff --git a/test/unit/lib/sock/sock.c/sock_ut.c b/test/unit/lib/sock/sock.c/sock_ut.c index 3cfa40cdc..366723a86 100644 --- a/test/unit/lib/sock/sock.c/sock_ut.c +++ b/test/unit/lib/sock/sock.c/sock_ut.c @@ -130,6 +130,7 @@ spdk_ut_sock_accept(struct spdk_sock *_sock) SPDK_CU_ASSERT_FATAL(g_ut_client_sock != NULL); g_ut_client_sock->peer = new_sock; + new_sock->peer = g_ut_client_sock; return &new_sock->base; } @@ -145,6 +146,11 @@ spdk_ut_sock_close(struct spdk_sock *_sock) if (sock == g_ut_client_sock) { g_ut_client_sock = NULL; } + + if (sock->peer != NULL) { + sock->peer->peer = NULL; + } + free(_sock); return 0; @@ -244,6 +250,14 @@ spdk_ut_sock_is_ipv4(struct spdk_sock *_sock) return true; } +static bool +spdk_ut_sock_is_connected(struct spdk_sock *_sock) +{ + struct spdk_ut_sock *sock = __ut_sock(_sock); + + return (sock->peer != NULL); +} + static int spdk_ut_sock_get_placement_id(struct spdk_sock *_sock, int *placement_id) { @@ -331,6 +345,7 @@ static struct spdk_net_impl g_ut_net_impl = { .set_priority = spdk_ut_sock_set_priority, .is_ipv6 = spdk_ut_sock_is_ipv6, .is_ipv4 = spdk_ut_sock_is_ipv4, + .is_connected = spdk_ut_sock_is_connected, .get_placement_id = spdk_ut_sock_get_placement_id, .group_impl_create = spdk_ut_sock_group_impl_create, .group_impl_add_sock = spdk_ut_sock_group_impl_add_sock, @@ -371,6 +386,8 @@ _sock(const char *ip, int port) server_sock = spdk_sock_accept(listen_sock); SPDK_CU_ASSERT_FATAL(server_sock != NULL); + CU_ASSERT(spdk_sock_is_connected(client_sock) == true); + CU_ASSERT(spdk_sock_is_connected(server_sock) == true); /* Test spdk_sock_recv */ iov.iov_base = test_string; @@ -418,6 +435,11 @@ _sock(const char *ip, int port) CU_ASSERT(client_sock == NULL); CU_ASSERT(rc == 0); + /* On FreeBSD, it takes a small amount of time for a close to propagate to the + * other side, even in loopback. Introduce a small sleep. */ + sleep(1); + CU_ASSERT(spdk_sock_is_connected(server_sock) == false); + rc = spdk_sock_close(&server_sock); CU_ASSERT(server_sock == NULL); CU_ASSERT(rc == 0);