-
Notifications
You must be signed in to change notification settings - Fork 28
docs: Adds DR-002 for DLT network transport #299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| .. | ||
| # ******************************************************************************* | ||
| # Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| # | ||
| # See the NOTICE file(s) distributed with this work for additional | ||
| # information regarding copyright ownership. | ||
| # | ||
| # This program and the accompanying materials are made available under the | ||
| # terms of the Apache License Version 2.0 which is available at | ||
| # https://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| # ******************************************************************************* | ||
|
|
||
| DLT Network Transport Evolution | ||
| ================================ | ||
|
|
||
| .. dec_rec:: DLT Network Transport Evolution | ||
| :id: dec_rec__logging__dlt_transport_evolution | ||
| :status: proposed | ||
| :version: 1 | ||
| :context: See below. | ||
| :decision: TBA | ||
|
|
||
| Today the remote/DLT path is split across two processes, as described in | ||
| :doc:`index` and :doc:`../../../components/datarouter/index`: | ||
|
|
||
| - `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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be misunderstanding this but we would still have 2 copies of the log message right? |
||
| 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. | ||
|
|
||
| .. uml:: _assets/lsm_plugin.puml | ||
|
|
||
| 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 <https://github.com/comasso>`_. | ||
| - 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. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| ' ******************************************************************************* | ||
| ' Copyright (c) 2026 Contributors to the Eclipse Foundation | ||
| ' | ||
| ' See the NOTICE file(s) distributed with this work for additional | ||
| ' information regarding copyright ownership. | ||
| ' | ||
| ' This program and the accompanying materials are made available under the | ||
| ' terms of the Apache License Version 2.0 which is available at | ||
| ' https://www.apache.org/licenses/LICENSE-2.0 | ||
| ' | ||
| ' SPDX-License-Identifier: Apache-2.0 | ||
| ' ******************************************************************************* | ||
|
|
||
| @startuml network_stack_plugin | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the diagram and text don't make the plugin approach clear, do you think we could add a dummy block for the datarouter to make this clear? |
||
|
|
||
| skinparam componentStyle rectangle | ||
| skinparam nodesep 40 | ||
| skinparam ranksep 60 | ||
| skinparam linetype ortho | ||
|
|
||
| package "Network Stack (default instance)" <<QM>> { | ||
| component "devs-network-driver.so" as driver_default | ||
| } | ||
| component "mw::diag" as mwdiag | ||
| component "DLT Diagnostics" as dltdiag <<QM>> | ||
|
|
||
| driver_default -r-> mwdiag | ||
| mwdiag -r-> dltdiag | ||
|
|
||
| package "client" <<ASIL>> { | ||
| component "mw::log" as mwlog <<FFI>> | ||
| component "GTL" as gtl <<FFI>> | ||
| } | ||
|
|
||
| file "Client\nConfiguration" as clientconfig | ||
| clientconfig -d-> mwlog | ||
|
|
||
| interface "shm\n(payload)" as shmpayload | ||
| interface "shm\n(metadata)" as shmmeta | ||
| interface "shm\n(control block)" as shmctrl | ||
| interface "DLT QNX\nControl Channel" as ctrlchannel | ||
|
|
||
| gtl -r-> shmpayload | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We would later define a format for these log messages, is that right? |
||
| gtl -r-> shmmeta | ||
| gtl -r-> shmctrl | ||
| mwlog -r-> ctrlchannel | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this a signal that there is messages in the shared memory? Might be good to label the edge to make this clear |
||
| dltdiag -r-> ctrlchannel | ||
|
|
||
| package "Network Stack (log_and_trace instance)" <<QM>> { | ||
| package "DLTv2 plugin" { | ||
| component "GTL Backend" as gtlbackend | ||
| component "Core" as core | ||
| component "Statistics\nModule" as stats | ||
| component "DLTv2 Router" as router | ||
| component "DLTv2 File\nWriter" as filewriter | ||
| component "DLTv2 Network\nWriter" as netwriter | ||
| component "Network Stack\nNative APIs" as fbsdapi | ||
| component "devs-network-driver.so" as driver | ||
| } | ||
| } | ||
|
|
||
| shmpayload -r-> gtlbackend : R/O | ||
| shmmeta -r-> gtlbackend : R/W | ||
| shmctrl -r-> core : R/W | ||
| ctrlchannel -r-> core | ||
|
|
||
| ' Hidden constraints only: force the intended left-to-right column order | ||
| ' (diagnostics, client, shared memory, plugin) without drawing extra lines. | ||
| driver_default -[hidden]r-> gtl | ||
| gtl -[hidden]r-> gtlbackend | ||
|
|
||
| gtlbackend -d-> core | ||
| core -d-> router | ||
| core -l-> stats | ||
| router -d-> filewriter | ||
| router -d-> netwriter | ||
| filewriter -d-> fbsdapi | ||
| netwriter -d-> fbsdapi | ||
| fbsdapi -d-> driver | ||
|
|
||
| file "Global\nConfiguration" as globalconfig | ||
| globalconfig -d-> core | ||
|
|
||
| file "Router\nConfiguration" as routerconfig | ||
| routerconfig -d-> router | ||
|
|
||
| database "filesystem\n(devb-*, fs-qnx6.so)" as fsdb | ||
| filewriter -d-> fsdb | ||
|
|
||
| ' Optional/experimental time-sync path, greyed out in the source diagram | ||
| component "gPTP\nLogger Time" as gptp <<optional>> | ||
| interface "shm\n(logger time)" as shmtime <<optional>> | ||
| note right of shmtime | ||
| Optional, not yet available: read by | ||
| ""mw::time::hw_logger_time"" for use by ""mw::log"". | ||
| end note | ||
|
|
||
| fbsdapi -d-> gptp | ||
| gptp -r-> shmtime | ||
|
|
||
| @enduml | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nice to add all the acronyms to a glossary.