DLT Network Transport Evolution#

DLT Network Transport Evolution
status: proposed
context: See below.
decision: TBA
version: 1

Today the remote/DLT path is split across two processes, as described in Logging Architecture and Datarouter:

  • mw::log (application side) serialises log/trace records and writes them into a shared-memory buffer.

  • datarouter (a separate process) reads that buffer, constructs the DLT protocol headers, and transmits the resulting UDP/IPv4 multicast packets using the standard BSD Socket API over the platform’s default network stack, shared with all other networked services.

A second, feature-flagged client backend (shm_dma_enabled) would allow forwarding of records through a GTL client into a DMA-capable shared-memory region instead of the DataRouter ring buffer, handing them to a DLT-aware daemon on the receiving side. This is not the default today, and it does not by itself change how that receiving daemon talks to the network stack, so the properties below still apply regardless of which client backend feeds it.

This works, but has three structural properties worth revisiting:

  • Every message crosses two IPC hops before it reaches the wire: one between mw::log and datarouter, and a second one from datarouter into the network stack itself, since the socket API it uses is, on this class of platforms, implemented over IPC to a separate network-stack process rather than executing inline. Each hop also implies copying the message (application buffer into shared memory, shared memory into a new buffer with headers prepended, and again into the network stack’s own send buffers). It is this combination of copies and context switches across both hops, not a single IPC call, that drives CPU load.

  • Where that network-stack process is a single-threaded resource manager (e.g. QNX’s io-pkt), it serialises all socket traffic on the system through one queue. This is a separate overhead from the copies above: it is contention/scheduling cost, so a burst of log and trace traffic can add latency for every other socket user of that same instance, and vice versa. Newer, multithreaded stack implementations (e.g. io-sock) reduce this specific contention, but do not by themselves remove the two IPC hops and copies above.

  • log and trace traffic shares the same network stack and send queue as other service traffic (E.g. Someip communication), so there is no structural isolation between the two; any queuing or scheduling behaviour of one can influence the other.

Way Forward:

Part 1: A GTL-based client backend as the remote-logging path.

Part 2: Provide a compile-time seam to select between the DLTv1 wire format and the DLTv2 wire format, analogous to the existing build-flag pattern for Part 1, rather than replacing one with the other. Payload serialisation (verbose/non-verbose argument encoding) is identical between DLTv1 and DLTv2 and does not need a seam. The concrete DLTv2 protocol implementation behind this seam is closed-source and maintained outside this repository; this repository only needs to own the seam/interface, not the DLTv2 implementation itself.

Part 3: Move the DLT header-construction and transmission stage (i.e. the network-writing responsibility on the daemon receiving GTL records) into a module that is loaded directly by the network stack, running on a second, dedicated network-stack instance used exclusively for log and trace traffic:

  • Removes the second IPC hop (and its associated copy) between the router logic and the network stack for the transmit path.

  • Allows direct use of the network stack’s native buffer/interface APIs instead of the generic socket API, removing at least one further copy and enabling zero-copy transmission where supported by the driver.

  • Structurally isolates log and trace traffic from other network traffic, since it no longer shares a network-stack instance, queue, or scheduling domain with it.

  • Enables transport-level controls (e.g. egress traffic shaping) to be applied specifically to the log and trace traffic instance without affecting other traffic.

Out of scope / unaffected:

  • The mw::log application-facing logging APIs are unaffected; only the backend/transport selected underneath it changes.

  • The DLT payload serialisation (verbose/non-verbose argument encoding) is unaffected, since it is identical between DLTv1 and DLTv2.

  • The DLTv2 protocol implementation is out of scope: this repository only provides the compile-time seam to select it (Part 2); the implementation behind that seam is closed-source and lives in a separate, non-public repository.

  • Freedom-from-interference (FFI) guarantees is unaffected and already provided by the existing mw::log infrastructure.

Trade-offs

  • Both halves of this evolution targets DMA/zero-copy where the target hardware happens to support it. Each target platform needs to be verified and configured individually; where DMA/zero-copy isn’t available, the transport still works, just without the associated performance benefit.

  • Introduces a second network-stack instance that must be configured, operated, and kept isolated from the default one.

  • Requires a feasibility phase to confirm the target network stack supports loadable modules with the required capabilities for the supported target platforms.