SocketCAN Filters: Match Frame Format and Flags, Not Only the Numeric Identifier
Define a receive rule as identifier bits plus relevant frame flags, then test its Boolean combination with every other rule. Matching only the low eleven identifier bits can admit extended frames and remote-transmission requests that a standard-data consumer never intended to process.
This guide pins Linux v6.12 CAN_RAW behavior. The worked examples concern ordinary Classical CAN identifiers and flags; CAN FD admission is a separate socket setting, and CAN XL is outside scope. The tables are source-derived expectations, not results from a running socket or bus.
1. Write the intended frame set first
Describe the interface, standard or extended identifier format, data versus remote-request type, allowed identifiers and application schema. Keep error notifications in a separate diagnostic contract.
For example: “On the selected interface, accept standard data frames with identifier 0x321.” This is narrower than “accept identifier 0x321,” which leaves the relevant frame format and flags ambiguous.
The UAPI definitions place identifier bits and EFF, RTR and ERR flags in can_id. Decode the representation before formatting a log or comparing a value. A printed decimal identifier that drops flags loses information needed to explain a match.

2. Apply the mask to both sides
The filter contract compares received and configured identifiers after applying the mask. Bits absent from the mask do not constrain that ordinary comparison. Include EFF and RTR in the mask when their values matter.
For the standard-data example, use a configured value of 0x321 with the symbolic mask CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG. The configured EFF and RTR bits remain clear, so both are required to be clear in a matching frame.
For a specific extended data identifier, set EFF in the configured value and use CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG. Setting a flag in the mask means “compare this bit”; setting it in the value means “the compared bit must be one.”
3. Use a truth table that exposes omitted bits
The following hypothetical frames compare a loose 0x321/SFF-mask rule with the strict standard-data rule above. Error events are deliberately excluded from this ordinary-frame arithmetic table.
| Input | Loose low-eleven-bit rule | Strict standard-data rule |
|---|---|---|
| Standard data, 0x321 | Match | Match |
| Standard remote request, 0x321 | Match | No match |
| Extended data, 0x321 | Match | No match |
| Extended data, 0x123321 | Match: same low eleven bits | No match |
| Standard data, 0x322 | No match | No match |
Keep these as expected fixture results until a test is actually executed. An arithmetic model can check mask logic; it cannot demonstrate that the intended socket received the intended configuration or that a hardware controller supplied the frame.
4. Review the whole filter array
Multiple normal filters are OR-combined by default. CAN_RAW_JOIN_FILTERS changes the intended combination to require all filters, while inverted rules negate their own match. These semantics are described in the socket-option reference.
Adding a broad rule beside a strict rule can therefore admit traffic the strict rule rejects. A common mistake is to treat the second entry as a refinement of the first when it is actually another acceptance route.
Write a parenthesized predicate for the entire proposed set before installation. For a range with exclusions, verify whether the design needs union, intersection or inversion. Test at least one frame that matches only each individual rule, one that matches all relevant rules and one that matches none.
The RAW receive path implements join bookkeeping and suppresses duplicate deliveries caused by multiple matches. Do not use duplicate message count as a substitute for checking which rules admitted the frame.
5. Keep error subscription out of payload selection
Error events have separate handling in the CAN receive lists. Configure their subscription through CAN_RAW_ERR_FILTER and dispatch received error frames before application decoding.
Check the shared receive callback interaction. In v6.12, joining more than one data filter makes raw_rcv() wait for multiple matching callbacks. An error frame reaches only the error list and its single registered callback, so the same joined socket can suppress a subscribed error notification. For dependable diagnostic observation, use a separate diagnostic socket with joining disabled, then qualify its reception and loss reporting.
Add a proposed fixture that delivers the same subscribed synthetic error event with joining disabled, then with two joined data filters. Expect the latter callback path to suppress it in this version; confirm the independent diagnostic socket still receives it. This test has not been executed.
A strict data-ID filter does not replace that diagnostic policy. Conversely, observing a requested error notification does not prove that the data filter admitted an unexpected application identifier. Preserve the frame class in captures so the two mechanisms remain distinguishable.
Do not manually repurpose special error/inversion bits as ordinary identifier mask bits without following the actual API semantics. Their meaning is not the same as another payload-address bit.
6. Qualify the installed receive contract
- Save the exact intended socket options, bound interface and expected truth table.
- Check every socket-option return; fail initialization visibly if a required option is rejected.
- Read back supported option state and retain the effective filter set.
- Use an isolated virtual fixture for format, mask and combination cases.
- Repeat necessary cases with the real driver on an approved inert bench, preserving frame flags and interface identity.
No such fixture was run here. Virtual traffic can qualify software selection but cannot establish controller acceptance, electrical timing or a mixed Classical/FD network’s compatibility.
If FD reception is enabled, the same identifier rule does not by itself distinguish Classical from FD payload representation. The RAW implementation has separate format admission. Continue validating receive size, payload length and the application’s schema after filtering.
Hypothetical unexpected extension
A fictional monitor expects standard 0x321 data but logs an extended 0x123321 frame. Its rule masked only the low eleven bits. The capture is consistent with that rule; the filter did not randomly fail.
The corrected contract includes format and RTR constraints, then rechecks the complete filter array. Acceptance ends with a versioned predicate and fixture report, not merely a screenshot showing one desired frame arriving.