2.3. Diagnostic Tester

This document defines the requirements for the diagnostic tester functionality of the Classic Diagnostic Adapter (CDA), including startup behavior, ECU detection, variant detection, and state management.

2.3.1. Startup Behavior

2.3.1.1. Startup Sequence

Software Requirement: Startup Sequence req~dt-startup-sequence
status: draft
links outgoing: arch~dt-startup-sequence

The CDA must execute startup in a defined sequence to ensure proper initialization of all components.

The startup sequence must include the following phases in order:

  1. Load and validate configuration (from file, environment variables, and CLI arguments)

  2. Initialize logging and tracing subsystems

  3. Start HTTP server (in a starting/not-ready state)

  4. Load diagnostic databases (MDD files)

  5. Initialize DoIP gateway (unless deferred initialization is enabled)

  6. Create UDS manager and register ECUs

  7. Start variant detection (asynchronous, unless deferred)

  8. Register SOVD API routes

  9. Transition to ready state

Rationale

A well-defined startup sequence ensures predictable initialization behavior and allows external systems to monitor startup progress via health endpoints when health monitoring is enabled (see Health Monitoring Endpoint (req~sovd-api-health-endpoint)).

@startuml
skinparam backgroundColor #FFFFFF
skinparam sequenceArrowThickness 2

participant "CDA Main" as CDA
participant "Configuration" as CFG
participant "HTTP Server" as HTTP
participant "Database Loader" as DB
participant "DoIP Gateway" as DOIP
participant "UDS Manager" as UDS

CDA -> CFG: Load configuration
activate CFG
CFG --> CDA: Configuration validated
deactivate CFG

CDA -> CDA: Setup tracing/logging

CDA -> HTTP: Launch server
activate HTTP
HTTP --> CDA: Server running (Starting state)
note right: Health endpoint returns "Starting"\n(when health feature is enabled)

CDA -> DB: Load MDD files
activate DB
note right: Parallel loading for performance
DB --> CDA: Databases loaded
deactivate DB

alt Immediate communication initialization (default)
    CDA -> DOIP: Initialize gateway
    activate DOIP
    DOIP -> DOIP: Broadcast VIR
    DOIP -> DOIP: Collect VAM responses
    DOIP -> DOIP: Establish TCP connections
    DOIP --> CDA: Gateway ready
    deactivate DOIP

    CDA -> UDS: Create UDS manager
    activate UDS
    UDS -> UDS: Register ECUs
    UDS -> UDS: Start variant detection (async)
    UDS --> CDA: Manager ready
    deactivate UDS
else Deferred communication until first request (on-demand)
    note over CDA,UDS: DoIP and ECU discovery
else Deferred until explicit activation through api
    note over CDA,UDS: DoIP and ECU discovery
end

CDA -> HTTP: Register SOVD routes
CDA -> HTTP: Transition to Ready state
note right: Health endpoint returns "Up"\n(when health feature is enabled)
deactivate HTTP
@enduml

CDA Startup Sequence

2.3.1.2. Database Loading

Software Requirement: Database Loading req~dt-database-loading
status: draft
links outgoing: arch~dt-database-loading

The CDA must load diagnostic databases (MDD files) at startup.

The following requirements apply:

  • MDD files must be discovered from a configurable directory path

  • Loading must support parallel execution to improve startup performance

  • Larger files should be prioritized in the loading queue to optimize parallel resource utilization

  • Duplicate ECU names with the same logical address must resolve to the database with the newest revision

  • Duplicate ECU names with different logical addresses must be marked as invalid and excluded

  • Loading failures for individual MDD files must not prevent other databases from loading

  • The total number of parallel loading tasks should be configurable

Rationale

Parallel database loading significantly reduces startup time in deployments with many ECU definitions. Graceful handling of duplicates and failures ensures robust operation in real-world environments where database files may be inconsistent or corrupted.

2.3.1.3. DoIP Gateway Initialization

Software Requirement: DoIP Gateway Initialization req~dt-doip-gateway-init
status: draft

The CDA must initialize the DoIP gateway to enable communication with vehicle ECUs.

The initialization must include:

  • Broadcasting a Vehicle Identification Request (VIR) on the configured network interface

  • Collecting Vehicle Announcement Messages (VAM) from responding DoIP entities

  • Establishing TCP connections to discovered DoIP entities

  • Activating routing for diagnostic communication

The following must be configurable:

  • Tester address

  • VIR broadcast parameters (source port range, net mask)

  • Fallback connection timeouts and retry behavior (if not defined through diagnostic description)

Rationale

DoIP gateway initialization establishes the communication path to vehicle ECUs. Configurable parameters allow adaptation to different network topologies and timing requirements.

2.3.1.4. Communication Initialization Mode

Software Requirement: Communication Initialization Mode req~dt-deferred-initialization
status: draft

The CDA must support a configurable [communication] init_mode, controlling when DoIP gateway initialization and ECU discovery are allowed to begin, and, once begun, whether they always perform a full VIR/VAM broadcast discovery or reuse a previously persisted topology when available:

  • Always (default) – DoIP gateway initialization and ECU discovery proceed immediately at startup, as defined in Startup Sequence (req~dt-startup-sequence), always performing a full VIR/VAM broadcast discovery, regardless of whether a persisted topology exists (see ECU List Persistence (req~dt-ecu-list-persistence)). If ECU list persistence is enabled, results are still persisted afterward (updating the stored topology, states, and last_seen timestamps), but the persisted topology is never used to skip or replace the broadcast discovery itself. This matches the CDA’s established default behavior of always performing a full detection run at startup.

  • WhenNotPersisted – DoIP gateway initialization and ECU discovery proceed immediately at startup, but a full VIR/VAM broadcast discovery is only performed when no persisted topology exists (e.g. on the first-ever startup, or any time after the persisted topology has been cleared, see ECU List Persistence (req~dt-ecu-list-persistence)). Whenever a persisted topology exists, the CDA must instead attempt a direct (unicast) DoIP connection to each persisted gateway’s known network address, skipping the broadcast VIR step; if a gateway cannot be reached at its persisted address, the CDA must fall back to broadcast-based discovery for that specific gateway, as defined in Vehicle Identification (req~doip-vehicle-identification), before marking its ECUs as Offline. This mode requires ECU list persistence to be enabled; it is equivalent to Always if persistence is disabled, since no persisted topology can ever exist in that configuration.

  • OnDemand – DoIP gateway initialization and ECU discovery are postponed until one of the following triggers occurs:

    • Explicit activation via the plugin API – a custom plugin may trigger the activation of ECU communication based on specific conditions (e.g., security unlock, session establishment). This triggers a full initialization of all gateways/ECUs at once, applying the same persisted-vs-broadcast behavior as WhenNotPersisted described above.

    • First diagnostic request to a specific ECU (on-demand initialization) – if a persisted topology exists, this establishes a connection only to that ECU’s gateway (direct reconnect, with broadcast fallback for that gateway alone, as in WhenNotPersisted); other persisted gateways remain unconnected until their own first request. If no persisted topology exists, no gateway network address is yet known, so this necessarily triggers a full, vehicle-wide VIR broadcast discovering and connecting all gateways at once, since VIR-based discovery is inherently broadcast-based and cannot be scoped to a single ECU.

  • Disabled – DoIP gateway initialization and ECU discovery are postponed like in OnDemand mode, but neither the first-diagnostic-request nor the plugin-API trigger apply. Communication only starts once a detection run is explicitly initiated – typically via the networkreset operation with trigger_detection=true (see Vehicle Topology Plugin - R... (req~plugin-vehicle-topology-reset-clear-persisted)), but a plugin or other custom code may equally initiate a detection run directly. Once triggered, this always initializes all gateways/ECUs at once (there is no per-ECU auto-trigger in this mode), applying the same persisted-vs-broadcast behavior as WhenNotPersisted.

In both OnDemand and Disabled mode:

  • The HTTP server and SOVD API must be available before ECU communication is initialized

  • ECU endpoints must return an appropriate status indicating pending initialization

  • Once triggered, initialization must proceed as defined in Startup Sequence (req~dt-startup-sequence), scoped to either a single gateway or all gateways as described above

Once a detection run has completed (regardless of the triggering init_mode), the resulting topology is persisted as described in ECU List Persistence (req~dt-ecu-list-persistence), so that subsequent startups may reuse it (unless init_mode is configured as Always).

Rationale

Configurable initialization supports use cases where the CDA must start quickly without immediately consuming network resources, or where ECU communication should only begin after explicit authorization (e.g., security unlock, session establishment, or plugin-controlled activation). The Disabled mode additionally supports deployments that require the CDA to be reachable via its SOVD API immediately, without generating any vehicle network traffic, until a detection run is explicitly initiated (typically via networkreset, but potentially by a plugin or other custom code) – as opposed to OnDemand mode, where the first diagnostic request to any ECU implicitly authorizes (at least that ECU’s) communication.

Distinguishing Always from WhenNotPersisted avoids leaving the choice between “always rebroadcast, but keep tracking state/last_seen across restarts” and “skip rebroadcasting whenever possible” as an implicit side effect of whether a persisted topology happens to exist. Some deployments may want the freshness/robustness guarantees of always rebroadcasting while still benefiting from persisted state across restarts (e.g. last_seen history); others may prioritize minimizing startup time and vehicle network traffic once an initial topology has been established.

OnDemand and Disabled always behave like WhenNotPersisted once triggered, rather than offering their own Always/WhenNotPersisted choice: these modes exist specifically to avoid vehicle network traffic until explicitly authorized, so unconditionally rebroadcasting even when a persisted topology is already available would be counter to their purpose. Within OnDemand, the two triggers intentionally differ in scope: the plugin-API trigger is a deliberate, whole-vehicle “start communication now” signal and must activate every gateway, matching what a plugin expects after an explicit authorization event; the first-diagnostic-request trigger, by contrast, is an implicit, incidental signal tied to one specific ECU, so it should only establish what is strictly needed to serve that request when a persisted topology makes this possible.

2.3.2. ECU Detection and Variant Detection

2.3.2.1. ECU Discovery

Software Requirement: ECU Discovery req~dt-ecu-discovery
status: draft
links outgoing: arch~dt-ecu-discovery

The CDA must discover and register ECUs based on loaded databases and DoIP gateway responses.

The following requirements apply:

  • ECUs defined in MDD files must be registered with their logical addresses

  • ECUs must be associated with their corresponding DoIP gateway connections

  • ECUs sharing the same logical address (from different MDD files) must be tracked for variant detection

  • ECU availability must be determined based on successful DoIP entity responses

  • The list of available ECUs and their status must be queryable via the SOVD API

Rationale

ECU discovery establishes the mapping between diagnostic descriptions (MDD) and physical vehicle communication endpoints, enabling the SOVD API to expose the correct ECU capabilities.

2.3.2.2. Variant Detection

Software Requirement: Variant Detection req~dt-variant-detection
status: draft

The CDA must perform variant detection to identify the correct ECU variant from potentially multiple definitions.

The following requirements apply:

  • Variant detection must be initiated automatically after startup (unless deferred initialization is enabled)

  • Variant detection requests must be sent as defined in the MDD variant detection configuration

  • Responses must be evaluated against variant patterns defined in the MDD

  • For ECUs with duplicate definitions (same logical address), variant detection must determine which definition applies

  • Fallback to base variant must be configurable when variant detection fails to find a matching pattern

  • Clients must be able to trigger variant detection explicitly via a PUT to the ECU endpoint

  • Variant detection must be retriggerable to handle ECU software changes

Rationale

ECUs may have multiple software variants with different diagnostic capabilities. Variant detection ensures the CDA exposes the correct services and parameters for the actually installed variant.

2.3.2.3. ECU States

Software Requirement: ECU States req~dt-ecu-states
status: draft
links outgoing: arch~dt-ecu-states

ECUs must maintain defined states throughout their lifecycle to reflect their current availability and detection status.

The following states must be supported:

  • NotTested: ECU is registered but variant detection has not been performed

  • Online: ECU is reachable and variant has been successfully detected

  • AssumedOnline: ECU was known to be Online according to a persisted ECU list (see ECU List Persistence (req~dt-ecu-list-persistence)), but has not yet been contacted in the current session

  • NoVariantDetected: ECU is reachable but no matching variant pattern was found (using fallback if enabled)

  • Duplicate: ECU shares its logical address with another ECU that was identified as the correct variant; this ECU’s database is unloaded

  • Offline: ECU was tested but could not be reached; the ECU has never been successfully online since registration or last re-detection

  • Disconnected: ECU was previously online but communication has been lost

State transitions must occur as follows:

  • Registration –> NotTested

  • Registration from a persisted ECU list, for an ECU last known to be Online –> AssumedOnline

  • NotTested –> Online (successful variant detection)

  • NotTested –> NoVariantDetected (detection failed, fallback enabled)

  • NotTested –> Duplicate (another ECU with same logical address detected as correct variant)

  • NotTested –> Offline (variant detection attempted but ECU unreachable)

  • Offline –> NotTested (reconnection attempt or explicit re-detection requested)

  • Online –> Disconnected (connection lost)

  • Online –> NotTested (explicit re-detection requested)

  • AssumedOnline –> Online (successfully contacted, e.g. first diagnostic request or re-detection)

  • AssumedOnline –> Disconnected (contact attempted but ECU unreachable)

  • AssumedOnline –> NotTested (explicit re-detection requested)

  • NoVariantDetected –> Online (successful re-detection)

  • NoVariantDetected –> Duplicate (another ECU with same logical address detected as correct variant)

  • NoVariantDetected –> Disconnected (connection lost)

  • Duplicate –> NotTested (explicit re-detection requested)

  • Disconnected –> NotTested (reconnection attempt)

The current ECU state must be queryable via the SOVD API. Externally, the AssumedOnline state must be reported as Online, so that clients are not required to be aware of this internal distinction (see Components Entity Collection (arch~sovd-api-components-entity-collection)).

In addition to the state, the SOVD API must expose a last_seen timestamp for each ECU, indicating the time of the last successful diagnostic contact with that ECU. This timestamp must be preserved across CDA restarts by persisting it together with the ECU list (see ECU List Persistence (req~dt-ecu-list-persistence) and ECU List Persistence - Shut... (req~dt-ecu-list-persistence-shutdown)).

@startuml
skinparam backgroundColor #FFFFFF
skinparam stateArrowThickness 2

[*] --> NotTested : ECU registered
[*] --> AssumedOnline : ECU registered from\npersisted list (was Online)

state NotTested {
}

state Online {
}

state AssumedOnline {
}

state NoVariantDetected {
}

state Duplicate {
}

state Offline {
}

state Disconnected {
}

NotTested --> Online : Variant detected\nsuccessfully
NotTested --> NoVariantDetected : Detection failed\n(fallback enabled)
NotTested --> Duplicate : Another ECU with same\nlogical address is correct
NotTested --> Offline : Variant detection attempted\nbut ECU unreachable

Offline --> NotTested : Reconnection attempt /\nRe-detection requested

Online --> Disconnected : Connection lost
Online --> NotTested : Re-detection\nrequested

AssumedOnline --> Online : Successfully\ncontacted
AssumedOnline --> Disconnected : Contact attempted\nbut unreachable
AssumedOnline --> NotTested : Re-detection\nrequested

NoVariantDetected --> Online : Variant\nre-detected
NoVariantDetected --> Duplicate : Another ECU with same\nlogical address is correct
NoVariantDetected --> Disconnected : Connection lost

Duplicate --> NotTested : Re-detection\nrequested

Disconnected --> NotTested : Reconnection\nattempt
@enduml

ECU State Chart

Rationale

Explicit state management provides clients with visibility into ECU availability and allows appropriate error handling based on the current state. The AssumedOnline state allows the CDA to immediately report ECUs as reachable based on prior knowledge (e.g. in Communication Initializatio... (req~dt-deferred-initialization)’s OnDemand mode, before its per-ECU trigger has fired) while still internally tracking that this assumption has not yet been confirmed in the current session. The last_seen timestamp gives clients visibility into how stale that assumption might be, which is especially relevant while an ECU remains in the AssumedOnline state.

2.3.3. ECU List Persistence

2.3.3.1. ECU List Persistence

Software Requirement: ECU List Persistence req~dt-ecu-list-persistence
status: draft

The CDA must be able to persist the detected ECU/gateway topology, so that it does not necessarily need to re-run full ECU detection (VIR/VAM discovery and variant detection) on every startup.

This is a core diagnostic-tester capability, usable purely through [communication] configuration (ecu_list_persistence.enabled, init_mode); it does not require the Vehicle Topology Plugin (see Vehicle Topology Plugin (req~plugin-vehicle-topology)) to be loaded. For example, with ecu_list_persistence.enabled = true and init_mode = WhenNotPersisted (see Communication Initializatio... (req~dt-deferred-initialization)), the first-ever startup (or any startup without a persisted topology) performs a full detection run and persists its results; every subsequent startup then reconnects directly to the persisted gateways without needing a full VIR/VAM broadcast again, and without any plugin involvement. When the Vehicle Topology Plugin is loaded, it additionally exposes the networkreset SOVD operation to explicitly (re-)trigger detection or clear the persisted topology at runtime (see Vehicle Topology Plugin - R... (req~plugin-vehicle-topology-reset-clear-persisted)).

This capability must be configurable via an enabled flag, defaulting to false. With persistence disabled, no persisted topology can ever exist, so the default init_mode = Always (see Communication Initializatio... (req~dt-deferred-initialization)) always performs a full VIR/VAM broadcast detection at every startup – matching CDA behavior prior to the introduction of this feature. When disabled (the default):

The following requirements apply when persistence is enabled:

Rationale

Full ECU detection involves broadcasting a VIR, waiting for VAM responses, and running variant detection for every discovered ECU, which can take a noticeable amount of time in vehicles with many ECUs. Persisting the previously detected topology allows the CDA to skip or defer this work on subsequent startups, improving startup time and reducing unnecessary vehicle network traffic. This is an opt-in capability (disabled by default), preserving the CDA’s established default behavior of always performing a full VIR/VAM broadcast detection at startup when left unconfigured (see the Always vs WhenNotPersisted distinction in Communication Initializatio... (req~dt-deferred-initialization)).

2.3.3.2. ECU List Persistence - Shutdown Update

Software Requirement: ECU List Persistence - Shutdown Update req~dt-ecu-list-persistence-shutdown
status: draft

In addition to persisting the topology after a detection run (see ECU List Persistence (req~dt-ecu-list-persistence)), the CDA must, as part of a graceful shutdown, update the persisted last_seen timestamp of each ECU that was contacted since the last time the topology was persisted, so that this information survives a restart. This shutdown update must be skipped entirely when ECU list persistence is disabled (see ECU List Persistence (req~dt-ecu-list-persistence)).

Rationale

The last_seen timestamp is updated frequently during normal operation (on every successful diagnostic response), which is not practical to persist and flush on every single occurrence without impacting performance and flash wear. Persisting the latest value at shutdown ensures the timestamp surviving a restart is reasonably up to date, without requiring a flush on every diagnostic response.

2.3.4. Error Handling

Software Requirement: Startup Error Handling req~dt-error-handling
status: draft
links outgoing: arch~dt-error-handling

The CDA must handle startup failures gracefully to maximize availability.

The following error handling behaviors must be supported:

  • No databases loaded: Behavior must be configurable (exit with error or continue with empty ECU list)

  • Individual database load failure: Must not prevent other databases from loading; failures must be logged

  • DoIP connection failure: Must not prevent startup for other DoIP entities; affected ECUs must be marked as Offline

  • Variant detection failure: Must not prevent ECU registration; ECU must remain in NotTested, Offline, or NoVariantDetected state

  • Configuration validation failure: Must prevent startup with a clear error message

All errors must be logged with sufficient detail for troubleshooting.

Rationale

Graceful degradation ensures the CDA remains partially operational even when some components fail, which is critical for diagnostic scenarios where partial functionality may still be useful.