From 64ae44ccea5f1a4e4ca4ab5462345108555d8c85 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Wed, 9 Oct 2024 13:51:14 +0200 Subject: [PATCH] Add Z_FEATURE_TCP_NODELAY (#723) * refactor: recopy buffers instead of bytes in siphon * feat: activate TCP_NO_DELAY --- CMakeLists.txt | 1 + include/zenoh-pico/config.h | 1 + include/zenoh-pico/config.h.in | 1 + src/protocol/iobuf.c | 30 +++++++++++++++++++++------- src/system/arduino/esp32/network.cpp | 7 +++++++ src/system/espidf/network.c | 7 +++++++ src/system/unix/network.c | 8 +++++++- src/system/windows/network.c | 7 +++++++ src/system/zephyr/network.c | 9 +++++++++ src/transport/multicast/tx.c | 2 ++ src/transport/unicast/tx.c | 2 ++ 11 files changed, 67 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 508033628..7f5d01971 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,6 +203,7 @@ set(Z_FEATURE_LINK_UDP_UNICAST 1 CACHE STRING "Toggle UDP unicast links") set(Z_FEATURE_MULTICAST_TRANSPORT 1 CACHE STRING "Toggle multicast transport") set(Z_FEATURE_UNICAST_TRANSPORT 1 CACHE STRING "Toggle unicast transport") set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport") +set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index eda3441d5..b3c5d3ec1 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -41,6 +41,7 @@ #define Z_FEATURE_UNICAST_TRANSPORT 1 #define Z_FEATURE_FRAGMENTATION 1 #define Z_FEATURE_ENCODING_VALUES 1 +#define Z_FEATURE_TCP_NODELAY 1 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index dba1ab27d..40941d9fa 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -41,6 +41,7 @@ #define Z_FEATURE_UNICAST_TRANSPORT @Z_FEATURE_UNICAST_TRANSPORT@ #define Z_FEATURE_FRAGMENTATION @Z_FEATURE_FRAGMENTATION@ #define Z_FEATURE_ENCODING_VALUES @Z_FEATURE_ENCODING_VALUES@ +#define Z_FEATURE_TCP_NODELAY @Z_FEATURE_TCP_NODELAY@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index 609905f10..c398bc766 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -519,14 +519,30 @@ _z_zbuf_t _z_wbuf_to_zbuf(const _z_wbuf_t *wbf) { z_result_t _z_wbuf_siphon(_z_wbuf_t *dst, _z_wbuf_t *src, size_t length) { z_result_t ret = _Z_RES_OK; - - for (size_t i = 0; i < length; i++) { - ret = _z_wbuf_write(dst, _z_wbuf_read(src)); - if (ret != _Z_RES_OK) { - break; - } + size_t llength = length; + _z_iosli_t *wios = _z_wbuf_get_iosli(dst, dst->_w_idx); + size_t writable = _z_iosli_writable(wios); + + // Siphon does not work (as of now) on expandable dst buffers + if (writable >= length) { + do { + assert(src->_r_idx <= src->_w_idx); + _z_iosli_t *rios = _z_wbuf_get_iosli(src, src->_r_idx); + size_t readable = _z_iosli_readable(rios); + if (readable > (size_t)0) { + size_t to_read = (readable <= llength) ? readable : llength; + uint8_t *w_pos = _z_ptr_u8_offset(wios->_buf, (ptrdiff_t)wios->_w_pos); + (void)memcpy(w_pos, rios->_buf + rios->_r_pos, to_read); + rios->_r_pos = rios->_r_pos + to_read; + llength -= to_read; + wios->_w_pos += to_read; + } else { + src->_r_idx++; + } + } while (llength > (size_t)0); + } else { + ret = _Z_ERR_TRANSPORT_NO_SPACE; } - return ret; } diff --git a/src/system/arduino/esp32/network.cpp b/src/system/arduino/esp32/network.cpp index 4e7301604..8c88d4dc6 100644 --- a/src/system/arduino/esp32/network.cpp +++ b/src/system/arduino/esp32/network.cpp @@ -64,6 +64,13 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re ret = _Z_ERR_GENERIC; } +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&optflag, sizeof(optflag)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + #if LWIP_SO_LINGER == 1 struct linger ling; ling.l_onoff = 1; diff --git a/src/system/espidf/network.c b/src/system/espidf/network.c index 95590ae20..bc91f50c3 100644 --- a/src/system/espidf/network.c +++ b/src/system/espidf/network.c @@ -60,6 +60,13 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re ret = _Z_ERR_GENERIC; } +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&optflag, sizeof(optflag)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + #if LWIP_SO_LINGER == 1 struct linger ling; ling.l_onoff = 1; diff --git a/src/system/unix/network.c b/src/system/unix/network.c index 03b00ea1d..86be15dc0 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,12 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re (setsockopt(sock->_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)) < 0)) { ret = _Z_ERR_GENERIC; } - +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif struct linger ling; ling.l_onoff = 1; ling.l_linger = Z_TRANSPORT_LEASE / 1000; diff --git a/src/system/windows/network.c b/src/system/windows/network.c index 21fc706b3..b0d9a6990 100644 --- a/src/system/windows/network.c +++ b/src/system/windows/network.c @@ -75,6 +75,13 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re ret = _Z_ERR_GENERIC; } +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_sock._fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + struct linger ling; ling.l_onoff = 1; ling.l_linger = Z_TRANSPORT_LEASE / 1000; diff --git a/src/system/zephyr/network.c b/src/system/zephyr/network.c index f5ed536d9..d8ac405b3 100644 --- a/src/system/zephyr/network.c +++ b/src/system/zephyr/network.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" @@ -68,6 +69,14 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re // ret = _Z_ERR_GENERIC; } +#if Z_FEATURE_TCP_NODELAY == 1 + int optflag = 1; + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&optflag, sizeof(optflag)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + #if LWIP_SO_LINGER == 1 struct linger ling; ling.l_onoff = 1; diff --git a/src/transport/multicast/tx.c b/src/transport/multicast/tx.c index eedd49509..df5b3bcdc 100644 --- a/src/transport/multicast/tx.c +++ b/src/transport/multicast/tx.c @@ -141,6 +141,8 @@ z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t if (ret == _Z_RES_OK) { ztm->_transmitted = true; // Mark the session that we have transmitted data } + } else { + _Z_ERROR("Fragment serialization failed with err %d", ret); } } } diff --git a/src/transport/unicast/tx.c b/src/transport/unicast/tx.c index a2d946b30..5ed555794 100644 --- a/src/transport/unicast/tx.c +++ b/src/transport/unicast/tx.c @@ -150,6 +150,8 @@ z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n if (ret == _Z_RES_OK) { ztu->_transmitted = true; // Mark the session that we have transmitted data } + } else { + _Z_ERROR("Fragment serialization failed with err %d", ret); } } }