Skip to content

Feature/optimize tcp driver (EPROT-77) - #182

Open
Octaviarius wants to merge 5 commits into
espressif:mainfrom
Octaviarius:feature/optimize-tcp-driver
Open

Feature/optimize tcp driver (EPROT-77)#182
Octaviarius wants to merge 5 commits into
espressif:mainfrom
Octaviarius:feature/optimize-tcp-driver

Conversation

@Octaviarius

@Octaviarius Octaviarius commented Aug 4, 2026

Copy link
Copy Markdown

Title

fix(tcp): reduce transaction latency and handle fragmented TCP frames

Summary

This PR reduces Modbus TCP transaction latency, removes the redundant esp_event
loop from the TCP driver, and makes TCP frame reception work correctly when an
MBAP header or payload is split across multiple TCP segments.

The driver task remains responsible for serializing all connection and protocol
events. Events are now stored in a lightweight per-driver FreeRTOS queue, while
eventfd is used only to wake the task blocked in select().

Motivation

The previous implementation used both:

  • an esp_event queue for event storage and dispatch;
  • an eventfd to wake the TCP task;
  • a separately executed esp_event_loop_run() call.

This added queueing, copying, dispatch, and timeout overhead without providing
additional concurrency or isolation. It could also delay socket processing while
the event loop was running.

TCP receive handling also assumed that a single recv() call returned an entire
requested block. TCP does not preserve message boundaries, so fragmented MBAP
headers and payloads could be treated as invalid frames or connection failures.

Changes

Event processing

  • Replace the private esp_event loop with a per-driver FreeRTOS event queue.
  • Dispatch registered handlers directly from the TCP driver task.
  • Keep eventfd only as a wake-up source for select().
  • Preserve the symmetric event-handler set for master and slave instances.
  • Remove the obsolete esp_event component dependency.
  • Remove the unused event-loop processing budget Kconfig option.
  • Remove obsolete event-loop handles, handler instances, debug tables, and
    callback parameters.

TCP receive path

  • Add a persistent receive accumulator to each TCP node.
  • Receive socket data with MSG_DONTWAIT after select() reports readiness.
  • Preserve partial MBAP headers and payloads between task iterations.
  • Validate protocol ID and MBAP length before accepting a frame.
  • Reset accumulated receive state on frame completion or connection failure.
  • Avoid blocking the shared driver task while waiting for the remainder of a
    fragmented frame.

Socket handling

  • Apply TCP_NODELAY using setsockopt() after a connection is established.
  • Stop passing TCP_NODELAY as a flag to send().
  • Validate file descriptors using fd >= 0.
  • Use the socket descriptor, rather than the virtual node index, when checking
    socket readiness.
  • Process only descriptors returned in the select() read set.
  • Fix master and slave targeted-close handlers that could call FD_ISSET() with
    a negative socket descriptor.
  • Remove unnecessary one-tick delays from timeout handlers.

Lifecycle

  • Make event queue and eventfd ownership per driver instance.
  • Correct cleanup during partial initialization and driver destruction.
  • Add the missing slave error-handler deregistration.

Performance observation

In a local Modbus TCP polling test with one outstanding transaction at a time:

  • 50 requests completed over a 249 ms Tx-to-Tx observation window;
  • average request interval: approximately 5.08 ms;
  • average request frequency: approximately 197 requests/s.

These numbers are hardware- and application-specific and are included only as an
indication of the reduced scheduling overhead.

Validation

  • Compiled the modified TCP translation units with the ESP32-P4 RISC-V target
    compiler and the project -Werror flags:
    • port_tcp_driver.c
    • port_tcp_master.c
    • port_tcp_slave.c
    • port_tcp_utils.c
  • All four target syntax checks pass.
  • git diff --check passes.

A complete ESP-IDF application build and the upstream hardware test suite were
not run as part of this change.

@CLAassistant

CLAassistant commented Aug 4, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot changed the title Feature/optimize tcp driver Feature/optimize tcp driver (EPROT-77) Aug 4, 2026
@Octaviarius
Octaviarius force-pushed the feature/optimize-tcp-driver branch from 950fa20 to 36b44d6 Compare August 4, 2026 06:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants