CAN Error Frames: Preserve Diagnostic Flags Without Treating Them as Application Payload

Classify an error frame before identifier routing, then decode only fields made meaningful by its error-class bits. SocketCAN error notifications use the same general receive mechanism as traffic, but their data bytes describe diagnostics. Passing them into an application’s measurement or command decoder can manufacture plausible values from unrelated status.

This guide pins Linux v6.12’s error UAPI. It is a proposed decoder and reporting contract, not a hardware diagnosis. Controller and driver support determine which events and details actually appear. No bus fault, socket test or target decoder test was executed.

1. Preserve the frame class at ingestion

The CAN UAPI marks error notifications with CAN_ERR_FLAG. Inspect that flag before reducing the value to an ordinary identifier or selecting an application schema.

Keep the raw identifier/flags, received structure size, payload length, interface identity and observation timestamp. Reject truncated or unsupported representations through a diagnostic path rather than interpreting whatever bytes happened to be copied into a buffer.

The SocketCAN notification reference describes driver-generated error messages and their opt-in class subscription. An application that never subscribed cannot treat an empty error log as evidence of a clean bus.

Original CAN flags select either the application frame path or a validated error decoder whose class guards produce health events with explicit unavailable fields.
Original Linux v6.12 error-decoding model. Synthetic fixtures are proposed only; no electrical fault or target test was performed.

2. Decode fields under their class guard

The v6.12 error header defines an eight-byte error representation. Its class bits select diagnostic meanings; multiple classes can coexist. Decode all supported set classes, preserving unknown bits separately.

Class Associated bytes Decoder rule
LOSTARB data[0] Bit position or unspecified value
CRTL data[1] Controller status bit flags
PROT data[2], data[3] Protocol-type bit flags and a location code
TRX data[4] Defined transceiver-status encoding
CNT data[6], data[7] Reported transmit and receive error counters

Byte 5 is reserved. An absent class does not make its associated bytes valid zero-valued measurements. Retain “unavailable for this event” rather than inventing a normal status from zero-filled storage.

3. Keep flag sets distinct from location values

Protocol type in data[2] is a bitmask; protocol location in data[3] uses defined codes. Do not decode every numeric field by iterating its set bits. A location code can contain several one bits without representing several independent locations.

Implement separate decoding functions for masks and enumerated/structured encodings. Preserve the original byte when a value is unknown to the pinned decoder, and display a bounded unknown-value label instead of silently choosing the nearest known entry.

Keep field validity alongside its decoded value in the event schema. This prevents a downstream database or dashboard from turning “not reported” into zero when it serializes a missing optional field.

4. Use synthetic fixtures that expose false validity

Proposed input Required decoder outcome
CRTL and CNT set with multiple controller flags Retain both classes, all recognized flags and both reported counters
PROT set with stuffing and transmit flags plus an ACK-location code Separate the protocol-type flags from the single location interpretation
CNT absent but counter-byte positions contain nonzero data Do not expose those bytes as valid counters
Unknown class bit or unknown field encoding Preserve raw evidence and explicit unsupported detail
Error flag with incomplete representation Reject decoding with a length/format reason
Ordinary data with identical byte values Use the ordinary schema; never invent error status from payload alone

These fixtures are not executed. They can be implemented entirely in a parser harness using artificial byte arrays. No production traffic or electrical fault is needed to test the representation rules.

Keep the decoder version in every serialized record. When a later kernel adds meanings, an older collector should remain explicit about what it cannot interpret rather than relabel old records retrospectively without provenance.

5. Qualify that the diagnostic path can deliver events

Separate the desired subscription mask from the driver’s actual reporting capability. Check the exact driver and controller documentation for implemented classes, relevant reporting settings and aggregation behavior. A generic UAPI constant does not guarantee hardware support.

The RAW receive path also has a joined-filter interaction that can suppress a single error callback when multiple data filters are joined. Use a separately qualified diagnostic socket with joining disabled when this evidence is required.

Bound queueing and logging work. The UAPI warns that bus-error events can be frequent; an unbounded logging loop can make the observer itself unreliable. Preserve loss indicators and aggregation windows rather than claiming an exact complete event history after overload.

6. Separate observation from root-cause diagnosis

A reported missing acknowledgement is an observation from the reporting path, not proof that a particular cable, transceiver or remote application failed. A protocol-location code identifies a reported part of a frame, not the identity of a defective component.

Correlate events with configuration, controller state, independently captured traffic and the exact test interval. Keep raw notification counts separate from a claim about the number of physical faults: reporting and aggregation can differ by driver.

Likewise, an RX overflow indication must retain its documented reporting layer. Do not merge it automatically with a userspace socket-queue loss counter or infer which application messages were lost without additional evidence.

Hypothetical phantom measurement

A fictional monitor masks away all high identifier bits before dispatch. An error notification then reaches a measurement decoder whose schema happens to accept eight bytes. The dashboard displays a plausible but invented sensor value.

The corrected pipeline classifies the original frame first, validates the diagnostic representation and routes it to a health-event stream. Application state remains unchanged by that event except through an explicit quality policy.

7. Deliver a health-event contract

Record interface and build identity, raw class mask, available decoded fields, unsupported details, timestamp origin, subscription configuration and evidence-loss status. Keep diagnostic state separate from application payload values.

Acceptance requires both decoder correctness and demonstrated delivery under the intended driver and load. Until those tests exist, label the method proposed and leave unsupported health claims unresolved.

Similar Posts