| .. SPDX-License-Identifier: (GPL-2.0 OR MIT) |
| |
| =================== |
| J1939 Documentation |
| =================== |
| |
| Overview / What Is J1939 |
| ======================== |
| |
| SAE J1939 defines a higher layer protocol on CAN. It implements a more |
| sophisticated addressing scheme and extends the maximum packet size above 8 |
| bytes. Several derived specifications exist, which differ from the original |
| J1939 on the application level, like MilCAN A, NMEA2000, and especially |
| ISO-11783 (ISOBUS). This last one specifies the so-called ETP (Extended |
| Transport Protocol), which has been included in this implementation. This |
| results in a maximum packet size of ((2 ^ 24) - 1) * 7 bytes == 111 MiB. |
| |
| Specifications used |
| ------------------- |
| |
| * SAE J1939-21 : data link layer |
| * SAE J1939-81 : network management |
| * ISO 11783-6 : Virtual Terminal (Extended Transport Protocol) |
| |
| .. _j1939-motivation: |
| |
| Motivation |
| ========== |
| |
| Given the fact there's something like SocketCAN with an API similar to BSD |
| sockets, we found some reasons to justify a kernel implementation for the |
| addressing and transport methods used by J1939. |
| |
| * **Addressing:** when a process on an ECU communicates via J1939, it should |
| not necessarily know its source address. Although, at least one process per |
| ECU should know the source address. Other processes should be able to reuse |
| that address. This way, address parameters for different processes |
| cooperating for the same ECU, are not duplicated. This way of working is |
| closely related to the UNIX concept, where programs do just one thing and do |
| it well. |
| |
| * **Dynamic addressing:** Address Claiming in J1939 is time critical. |
| Furthermore, data transport should be handled properly during the address |
| negotiation. Putting this functionality in the kernel eliminates it as a |
| requirement for _every_ user space process that communicates via J1939. This |
| results in a consistent J1939 bus with proper addressing. |
| |
| * **Transport:** both TP & ETP reuse some PGNs to relay big packets over them. |
| Different processes may thus use the same TP & ETP PGNs without actually |
| knowing it. The individual TP & ETP sessions _must_ be serialized |
| (synchronized) between different processes. The kernel solves this problem |
| properly and eliminates the serialization (synchronization) as a requirement |
| for _every_ user space process that communicates via J1939. |
| |
| J1939 defines some other features (relaying, gateway, fast packet transport, |
| ...). In-kernel code for these would not contribute to protocol stability. |
| Therefore, these parts are left to user space. |
| |
| The J1939 sockets operate on CAN network devices (see SocketCAN). Any J1939 |
| user space library operating on CAN raw sockets will still operate properly. |
| Since such a library does not communicate with the in-kernel implementation, care |
| must be taken that these two do not interfere. In practice, this means they |
| cannot share ECU addresses. A single ECU (or virtual ECU) address is used by |
| the library exclusively, or by the in-kernel system exclusively. |
| |
| J1939 concepts |
| ============== |
| |
| Data Sent to the J1939 Stack |
| ---------------------------- |
| |
| The data buffers sent to the J1939 stack from user space are not CAN frames |
| themselves. Instead, they are payloads that the J1939 stack converts into |
| proper CAN frames based on the size of the buffer and the type of transfer. The |
| size of the buffer influences how the stack processes the data and determines |
| the internal code path used for the transfer. |
| |
| **Handling of Different Buffer Sizes:** |
| |
| - **Buffers with a size of 8 bytes or less:** |
| |
| - These are handled as simple sessions internally within the stack. |
| |
| - The stack converts the buffer directly into a single CAN frame without |
| fragmentation. |
| |
| - This type of transfer does not require an actual client (receiver) on the |
| receiving side. |
| |
| - **Buffers up to 1785 bytes:** |
| |
| - These are automatically handled as J1939 Transport Protocol (TP) transfers. |
| |
| - Internally, the stack splits the buffer into multiple 8-byte CAN frames. |
| |
| - TP transfers can be unicast or broadcast. |
| |
| - **Broadcast TP:** Does not require a receiver on the other side and can be |
| used in broadcast scenarios. |
| |
| - **Unicast TP:** Requires an active receiver (client) on the other side to |
| acknowledge the transfer. |
| |
| - **Buffers from 1786 bytes up to 111 MiB:** |
| |
| - These are handled as ISO 11783 Extended Transport Protocol (ETP) transfers. |
| |
| - ETP transfers are used for larger payloads and are split into multiple CAN |
| frames internally. |
| |
| - **ETP transfers (unicast):** Require a receiver on the other side to |
| process the incoming data and acknowledge each step of the transfer. |
| |
| - ETP transfers cannot be broadcast like TP transfers, and always require a |
| receiver for operation. |
| |
| **Non-Blocking Operation with `MSG_DONTWAIT`:** |
| |
| The J1939 stack supports non-blocking operation when used in combination with |
| the `MSG_DONTWAIT` flag. In this mode, the stack attempts to take as much data |
| as the available memory for the socket allows. It returns the amount of data |
| that was successfully taken, and it is the responsibility of user space to |
| monitor this value and handle partial transfers. |
| |
| - If the stack cannot take the entire buffer, it returns the number of bytes |
| successfully taken, and user space should handle the remainder. |
| |
| - **Error handling:** When using `MSG_DONTWAIT`, the user must rely on the |
| error queue to detect transfer errors. See the **SO_J1939_ERRQUEUE** section |
| for details on how to subscribe to error notifications. Without the error |
| queue, there is no other way for user space to be notified of transfer errors |
| during non-blocking operations. |
| |
| **Behavior and Requirements:** |
| |
| - **Simple transfers (<= 8 bytes):** Do not require a receiver on the other |
| side, making them easy to send without needing address claiming or |
| coordination with a destination. |
| |
| - **Unicast TP/ETP:** Requires a receiver on the other side to complete the |
| transfer. The receiver must acknowledge the transfer for the session to |
| proceed successfully. |
| |
| - **Broadcast TP:** Allows sending data without a receiver, but only works for |
| TP transfers. ETP cannot be broadcast and always needs a receiving client. |
| |
| These different behaviors depend heavily on the size of the buffer provided to |
| the stack, and the appropriate transport mechanism (TP or ETP) is selected |
| based on the payload size. The stack automatically manages the fragmentation |
| and reassembly of large payloads and ensures that the correct CAN frames are |
| generated and transmitted for each session. |
| |
| PGN |
| --- |
| |
| The J1939 protocol uses the 29-bit CAN identifier with the following structure: |
| |
| ============ ============== ==================== |
| 29 bit CAN-ID |
| -------------------------------------------------- |
| Bit positions within the CAN-ID |
| -------------------------------------------------- |
| 28 ... 26 25 ... 8 7 ... 0 |
| ============ ============== ==================== |
| Priority PGN SA (Source Address) |
| ============ ============== ==================== |
| |
| The PGN (Parameter Group Number) is a number to identify a packet. The PGN |
| is composed as follows: |
| |
| ============ ============== ================= ================= |
| PGN |
| ------------------------------------------------------------------ |
| Bit positions within the CAN-ID |
| ------------------------------------------------------------------ |
| 25 24 23 ... 16 15 ... 8 |
| ============ ============== ================= ================= |
| R (Reserved) DP (Data Page) PF (PDU Format) PS (PDU Specific) |
| ============ ============== ================= ================= |
| |
| In J1939-21 distinction is made between PDU1 format (where PF < 240) and PDU2 |
| format (where PF >= 240). Furthermore, when using the PDU2 format, the PS-field |
| contains a so-called Group Extension, which is part of the PGN. When using PDU2 |
| format, the Group Extension is set in the PS-field. |
| |
| ============== ======================== |
| PDU1 Format (specific) (peer to peer) |
| ---------------------------------------- |
| Bit positions within the CAN-ID |
| ---------------------------------------- |
| 23 ... 16 15 ... 8 |
| ============== ======================== |
| 00h ... EFh DA (Destination address) |
| ============== ======================== |
| |
| ============== ======================== |
| PDU2 Format (global) (broadcast) |
| ---------------------------------------- |
| Bit positions within the CAN-ID |
| ---------------------------------------- |
| 23 ... 16 15 ... 8 |
| ============== ======================== |
| F0h ... FFh GE (Group Extension) |
| ============== ======================== |
| |
| On the other hand, when using PDU1 format, the PS-field contains a so-called |
| Destination Address, which is _not_ part of the PGN. When communicating a PGN |
| from user space to kernel (or vice versa) and PDU1 format is used, the PS-field |
| of the PGN shall be set to zero. The Destination Address shall be set |
| elsewhere. |
| |
| Regarding PGN mapping to 29-bit CAN identifier, the Destination Address shall |
| be get/set from/to the appropriate bits of the identifier by the kernel. |
| |
| |
| Addressing |
| ---------- |
| |
| Both static and dynamic addressing methods can be used. |
| |
| For static addresses, no extra checks are made by the kernel and provided |
| addresses are considered right. This responsibility is for the OEM or system |
| integrator. |
| |
| For dynamic addressing, so-called Address Claiming, extra support is foreseen |
| in the kernel. In J1939 any ECU is known by its 64-bit NAME. At the moment of |
| a successful address claim, the kernel keeps track of both NAME and source |
| address being claimed. This serves as a base for filter schemes. By default, |
| packets with a destination that is not locally will be rejected. |
| |
| Mixed mode packets (from a static to a dynamic address or vice versa) are |
| allowed. The BSD sockets define separate API calls for getting/setting the |
| local & remote address and are applicable for J1939 sockets. |
| |
| Filtering |
| --------- |
| |
| J1939 defines white list filters per socket that a user can set in order to |
| receive a subset of the J1939 traffic. Filtering can be based on: |
| |
| * SA |
| * SOURCE_NAME |
| * PGN |
| |
| When multiple filters are in place for a single socket, and a packet comes in |
| that matches several of those filters, the packet is only received once for |
| that socket. |
| |
| How to Use J1939 |
| ================ |
| |
| API Calls |
| --------- |
| |
| On CAN, you first need to open a socket for communicating over a CAN network. |
| To use J1939, ``#include <linux/can/j1939.h>``. From there, ``<linux/can.h>`` will be |
| included too. To open a socket, use: |
| |
| .. code-block:: C |
| |
| s = socket(PF_CAN, SOCK_DGRAM, CAN_J1939); |
| |
| J1939 does use ``SOCK_DGRAM`` sockets. In the J1939 specification, connections are |
| mentioned in the context of transport protocol sessions. These still deliver |
| packets to the other end (using several CAN packets). ``SOCK_STREAM`` is not |
| supported. |
| |
| After the successful creation of the socket, you would normally use the ``bind(2)`` |
| and/or ``connect(2)`` system call to bind the socket to a CAN interface. After |
| binding and/or connecting the socket, you can ``read(2)`` and ``write(2)`` from/to the |
| socket or use ``send(2)``, ``sendto(2)``, ``sendmsg(2)`` and the ``recv*()`` counterpart |
| operations on the socket as usual. There are also J1939 specific socket options |
| described below. |
| |
| In order to send data, a ``bind(2)`` must have been successful. ``bind(2)`` assigns a |
| local address to a socket. |
| |
| Different from CAN is that the payload data is just the data that get sends, |
| without its header info. The header info is derived from the sockaddr supplied |
| to ``bind(2)``, ``connect(2)``, ``sendto(2)`` and ``recvfrom(2)``. A ``write(2)`` with size 4 will |
| result in a packet with 4 bytes. |
| |
| The sockaddr structure has extensions for use with J1939 as specified below: |
| |
| .. code-block:: C |
| |
| struct sockaddr_can { |
| sa_family_t can_family; |
| int can_ifindex; |
| union { |
| struct { |
| __u64 name; |
| /* pgn: |
| * 8 bit: PS in PDU2 case, else 0 |
| * 8 bit: PF |
| * 1 bit: DP |
| * 1 bit: reserved |
| */ |
| __u32 pgn; |
| __u8 addr; |
| } j1939; |
| } can_addr; |
| } |
| |
| ``can_family`` & ``can_ifindex`` serve the same purpose as for other SocketCAN sockets. |
| |
| ``can_addr.j1939.pgn`` specifies the PGN (max 0x3ffff). Individual bits are |
| specified above. |
| |
| ``can_addr.j1939.name`` contains the 64-bit J1939 NAME. |
| |
| ``can_addr.j1939.addr`` contains the address. |
| |
| The ``bind(2)`` system call assigns the local address, i.e. the source address when |
| sending packages. If a PGN during ``bind(2)`` is set, it's used as a RX filter. |
| I.e. only packets with a matching PGN are received. If an ADDR or NAME is set |
| it is used as a receive filter, too. It will match the destination NAME or ADDR |
| of the incoming packet. The NAME filter will work only if appropriate Address |
| Claiming for this name was done on the CAN bus and registered/cached by the |
| kernel. |
| |
| On the other hand ``connect(2)`` assigns the remote address, i.e. the destination |
| address. The PGN from ``connect(2)`` is used as the default PGN when sending |
| packets. If ADDR or NAME is set it will be used as the default destination ADDR |
| or NAME. Further a set ADDR or NAME during ``connect(2)`` is used as a receive |
| filter. It will match the source NAME or ADDR of the incoming packet. |
| |
| Both ``write(2)`` and ``send(2)`` will send a packet with local address from ``bind(2)`` and the |
| remote address from ``connect(2)``. Use ``sendto(2)`` to overwrite the destination |
| address. |
| |
| If ``can_addr.j1939.name`` is set (!= 0) the NAME is looked up by the kernel and |
| the corresponding ADDR is used. If ``can_addr.j1939.name`` is not set (== 0), |
| ``can_addr.j1939.addr`` is used. |
| |
| When creating a socket, reasonable defaults are set. Some options can be |
| modified with ``setsockopt(2)`` & ``getsockopt(2)``. |
| |
| RX path related options: |
| |
| - ``SO_J1939_FILTER`` - configure array of filters |
| - ``SO_J1939_PROMISC`` - disable filters set by ``bind(2)`` and ``connect(2)`` |
| |
| By default no broadcast packets can be send or received. To enable sending or |
| receiving broadcast packets use the socket option ``SO_BROADCAST``: |
| |
| .. code-block:: C |
| |
| int value = 1; |
| setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)); |
| |
| The following diagram illustrates the RX path: |
| |
| .. code:: |
| |
| +--------------------+ |
| | incoming packet | |
| +--------------------+ |
| | |
| V |
| +--------------------+ |
| | SO_J1939_PROMISC? | |
| +--------------------+ |
| | | |
| no | | yes |
| | | |
| .---------' `---------. |
| | | |
| +---------------------------+ | |
| | bind() + connect() + | | |
| | SOCK_BROADCAST filter | | |
| +---------------------------+ | |
| | | |
| |<---------------------' |
| V |
| +---------------------------+ |
| | SO_J1939_FILTER | |
| +---------------------------+ |
| | |
| V |
| +---------------------------+ |
| | socket recv() | |
| +---------------------------+ |
| |
| TX path related options: |
| ``SO_J1939_SEND_PRIO`` - change default send priority for the socket |
| |
| Message Flags during send() and Related System Calls |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| ``send(2)``, ``sendto(2)`` and ``sendmsg(2)`` take a 'flags' argument. Currently |
| supported flags are: |
| |
| * ``MSG_DONTWAIT``, i.e. non-blocking operation. |
| |
| recvmsg(2) |
| ^^^^^^^^^^ |
| |
| In most cases ``recvmsg(2)`` is needed if you want to extract more information than |
| ``recvfrom(2)`` can provide. For example package priority and timestamp. The |
| Destination Address, name and packet priority (if applicable) are attached to |
| the msghdr in the ``recvmsg(2)`` call. They can be extracted using ``cmsg(3)`` macros, |
| with ``cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR``, |
| ``SCM_J1939_DEST_NAME`` or ``SCM_J1939_PRIO``. The returned data is a ``uint8_t`` for |
| ``priority`` and ``dst_addr``, and ``uint64_t`` for ``dst_name``. |
| |
| .. code-block:: C |
| |
| uint8_t priority, dst_addr; |
| uint64_t dst_name; |
| |
| for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
| switch (cmsg->cmsg_level) { |
| case SOL_CAN_J1939: |
| if (cmsg->cmsg_type == SCM_J1939_DEST_ADDR) |
| dst_addr = *CMSG_DATA(cmsg); |
| else if (cmsg->cmsg_type == SCM_J1939_DEST_NAME) |
| memcpy(&dst_name, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0)); |
| else if (cmsg->cmsg_type == SCM_J1939_PRIO) |
| priority = *CMSG_DATA(cmsg); |
| break; |
| } |
| } |
| |
| setsockopt(2) |
| ^^^^^^^^^^^^^ |
| |
| The ``setsockopt(2)`` function is used to configure various socket-level |
| options for J1939 communication. The following options are supported: |
| |
| ``SO_J1939_FILTER`` |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| The ``SO_J1939_FILTER`` option is essential when the default behavior of |
| ``bind(2)`` and ``connect(2)`` is insufficient for specific use cases. By |
| default, ``bind(2)`` and ``connect(2)`` allow a socket to be associated with a |
| single unicast or broadcast address. However, there are scenarios where finer |
| control over the incoming messages is required, such as filtering by Parameter |
| Group Number (PGN) rather than by addresses. |
| |
| For example, in a system where multiple types of J1939 messages are being |
| transmitted, a process might only be interested in a subset of those messages, |
| such as specific PGNs, and not want to receive all messages destined for its |
| address or broadcast to the bus. |
| |
| By applying the ``SO_J1939_FILTER`` option, you can filter messages based on: |
| |
| - **Source Address (SA)**: Filter messages coming from specific source |
| addresses. |
| |
| - **Source Name**: Filter messages coming from ECUs with specific NAME |
| identifiers. |
| |
| - **Parameter Group Number (PGN)**: Focus on receiving messages with specific |
| PGNs, filtering out irrelevant ones. |
| |
| This filtering mechanism is particularly useful when: |
| |
| - You want to receive a subset of messages based on their PGNs, even if the |
| address is the same. |
| |
| - You need to handle both broadcast and unicast messages but only care about |
| certain message types or parameters. |
| |
| - The ``bind(2)`` and ``connect(2)`` functions only allow binding to a single |
| address, which might not be sufficient if the process needs to handle multiple |
| PGNs but does not want to open multiple sockets. |
| |
| To remove existing filters, you can pass ``optval == NULL`` or ``optlen == 0`` |
| to ``setsockopt(2)``. This will clear all currently set filters. If you want to |
| **update** the set of filters, you must pass the updated filter set to |
| ``setsockopt(2)``, as the new filter set will **replace** the old one entirely. |
| This behavior ensures that any previous filter configuration is discarded and |
| only the new set is applied. |
| |
| Example of removing all filters: |
| |
| .. code-block:: c |
| |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, NULL, 0); |
| |
| **Maximum number of filters:** The maximum amount of filters that can be |
| applied using ``SO_J1939_FILTER`` is defined by ``J1939_FILTER_MAX``, which is |
| set to 512. This means you can configure up to 512 individual filters to match |
| your specific filtering needs. |
| |
| Practical use case: **Monitoring Address Claiming** |
| |
| One practical use case is monitoring the J1939 address claiming process by |
| filtering for specific PGNs related to address claiming. This allows a process |
| to monitor and handle address claims without processing unrelated messages. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| struct j1939_filter filt[] = { |
| { |
| .pgn = J1939_PGN_ADDRESS_CLAIMED, |
| .pgn_mask = J1939_PGN_PDU1_MAX, |
| }, { |
| .pgn = J1939_PGN_REQUEST, |
| .pgn_mask = J1939_PGN_PDU1_MAX, |
| }, { |
| .pgn = J1939_PGN_ADDRESS_COMMANDED, |
| .pgn_mask = J1939_PGN_MAX, |
| }, |
| }; |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, &filt, sizeof(filt)); |
| |
| In this example, the socket will only receive messages with the PGNs related to |
| address claiming: ``J1939_PGN_ADDRESS_CLAIMED``, ``J1939_PGN_REQUEST``, and |
| ``J1939_PGN_ADDRESS_COMMANDED``. This is particularly useful in scenarios where |
| you want to monitor and process address claims without being overwhelmed by |
| other traffic on the J1939 network. |
| |
| ``SO_J1939_PROMISC`` |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| The ``SO_J1939_PROMISC`` option enables socket-level promiscuous mode. When |
| this option is enabled, the socket will receive all J1939 traffic, regardless |
| of any filters set by ``bind()`` or ``connect()``. This is analogous to |
| enabling promiscuous mode for an Ethernet interface, where all traffic on the |
| network segment is captured. |
| |
| However, **`SO_J1939_FILTER` has a higher priority** compared to |
| ``SO_J1939_PROMISC``. This means that even in promiscuous mode, you can reduce |
| the number of packets received by applying specific filters with |
| `SO_J1939_FILTER`. The filters will limit which packets are passed to the |
| socket, allowing for more refined traffic selection while promiscuous mode is |
| active. |
| |
| The acceptable value size for this option is ``sizeof(int)``, and the value is |
| only differentiated between `0` and non-zero. A value of `0` disables |
| promiscuous mode, while any non-zero value enables it. |
| |
| This combination can be useful for debugging or monitoring specific types of |
| traffic while still capturing a broad set of messages. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| int value = 1; |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_PROMISC, &value, sizeof(value)); |
| |
| In this example, setting ``value`` to any non-zero value (e.g., `1`) enables |
| promiscuous mode, allowing the socket to receive all J1939 traffic on the |
| network. |
| |
| ``SO_BROADCAST`` |
| ~~~~~~~~~~~~~~~~ |
| |
| The ``SO_BROADCAST`` option enables the sending and receiving of broadcast |
| messages. By default, broadcast messages are disabled for J1939 sockets. When |
| this option is enabled, the socket will be allowed to send and receive |
| broadcast packets on the J1939 network. |
| |
| Due to the nature of the CAN bus as a shared medium, all messages transmitted |
| on the bus are visible to all participants. In the context of J1939, |
| broadcasting refers to using a specific destination address field, where the |
| destination address is set to a value that indicates the message is intended |
| for all participants (usually a global address such as 0xFF). Enabling the |
| broadcast option allows the socket to send and receive such broadcast messages. |
| |
| The acceptable value size for this option is ``sizeof(int)``, and the value is |
| only differentiated between `0` and non-zero. A value of `0` disables the |
| ability to send and receive broadcast messages, while any non-zero value |
| enables it. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| int value = 1; |
| setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)); |
| |
| In this example, setting ``value`` to any non-zero value (e.g., `1`) enables |
| the socket to send and receive broadcast messages. |
| |
| ``SO_J1939_SEND_PRIO`` |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| The ``SO_J1939_SEND_PRIO`` option sets the priority of outgoing J1939 messages |
| for the socket. In J1939, messages can have different priorities, and lower |
| numerical values indicate higher priority. This option allows the user to |
| control the priority of messages sent from the socket by adjusting the priority |
| bits in the CAN identifier. |
| |
| The acceptable value **size** for this option is ``sizeof(int)``, and the value |
| is expected to be in the range of 0 to 7, where `0` is the highest priority, |
| and `7` is the lowest. By default, the priority is set to `6` if this option is |
| not explicitly configured. |
| |
| Note that the priority values `0` and `1` can only be set if the process has |
| the `CAP_NET_ADMIN` capability. These are reserved for high-priority traffic |
| and require administrative privileges. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| int prio = 3; // Priority value between 0 (highest) and 7 (lowest) |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &prio, sizeof(prio)); |
| |
| In this example, the priority is set to `3`, meaning the outgoing messages will |
| be sent with a moderate priority level. |
| |
| ``SO_J1939_ERRQUEUE`` |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| The ``SO_J1939_ERRQUEUE`` option enables the socket to receive error messages |
| from the error queue, providing diagnostic information about transmission |
| failures, protocol violations, or other issues that occur during J1939 |
| communication. Once this option is set, user space is required to handle |
| ``MSG_ERRQUEUE`` messages. |
| |
| Setting ``SO_J1939_ERRQUEUE`` to ``0`` will purge any currently present error |
| messages in the error queue. When enabled, error messages can be retrieved |
| using the ``recvmsg(2)`` system call. |
| |
| When subscribing to the error queue, the following error events can be |
| accessed: |
| |
| - **``J1939_EE_INFO_TX_ABORT``**: Transmission abort errors. |
| - **``J1939_EE_INFO_RX_RTS``**: Reception of RTS (Request to Send) control |
| frames. |
| - **``J1939_EE_INFO_RX_DPO``**: Reception of data packets with Data Page Offset |
| (DPO). |
| - **``J1939_EE_INFO_RX_ABORT``**: Reception abort errors. |
| |
| The error queue can be used to correlate errors with specific message transfer |
| sessions using the session ID (``tskey``). The session ID is assigned via the |
| ``SOF_TIMESTAMPING_OPT_ID`` flag, which is set by enabling the |
| ``SO_TIMESTAMPING`` option. |
| |
| If ``SO_J1939_ERRQUEUE`` is activated, the user is required to pull messages |
| from the error queue, meaning that using plain ``recv(2)`` is not sufficient |
| anymore. The user must use ``recvmsg(2)`` with appropriate flags to handle |
| error messages. Failure to do so can result in the socket becoming blocked with |
| unprocessed error messages in the queue. |
| |
| It is **recommended** that ``SO_J1939_ERRQUEUE`` be used in combination with |
| ``SO_TIMESTAMPING`` in most cases. This enables proper error handling along |
| with session tracking and timestamping, providing a more detailed analysis of |
| message transfers and errors. |
| |
| The acceptable value **size** for this option is ``sizeof(int)``, and the value |
| is only differentiated between ``0`` and non-zero. A value of ``0`` disables |
| error queue reception and purges any existing error messages, while any |
| non-zero value enables it. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| int enable = 1; // Enable error queue reception |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_ERRQUEUE, &enable, sizeof(enable)); |
| |
| // Enable timestamping with session tracking via tskey |
| int timestamping = SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_TX_ACK | |
| SOF_TIMESTAMPING_TX_SCHED | |
| SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_OPT_CMSG; |
| setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, ×tamping, |
| sizeof(timestamping)); |
| |
| When enabled, error messages can be retrieved using ``recvmsg(2)``. By |
| combining ``SO_J1939_ERRQUEUE`` with ``SO_TIMESTAMPING`` (with |
| ``SOF_TIMESTAMPING_OPT_ID`` and ``SOF_TIMESTAMPING_OPT_CMSG`` enabled), the |
| user can track message transfers, retrieve precise timestamps, and correlate |
| errors with specific sessions. |
| |
| For more information on enabling timestamps and session tracking, refer to the |
| `SO_TIMESTAMPING` section. |
| |
| ``SO_TIMESTAMPING`` |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| The ``SO_TIMESTAMPING`` option allows the socket to receive timestamps for |
| various events related to message transmissions and receptions in J1939. This |
| option is often used in combination with ``SO_J1939_ERRQUEUE`` to provide |
| detailed diagnostic information, session tracking, and precise timing data for |
| message transfers. |
| |
| In J1939, all payloads provided by user space, regardless of size, are |
| processed by the kernel as **sessions**. This includes both single-frame |
| messages (up to 8 bytes) and multi-frame protocols such as the Transport |
| Protocol (TP) and Extended Transport Protocol (ETP). Even for small, |
| single-frame messages, the kernel creates a session to manage the transmission |
| and reception. The concept of sessions allows the kernel to manage various |
| aspects of the protocol, such as reassembling multi-frame messages and tracking |
| the status of transmissions. |
| |
| When receiving extended error messages from the error queue, the error |
| information is delivered through a `struct sock_extended_err`, accessible via |
| the control message (``cmsg``) retrieved using the ``recvmsg(2)`` system call. |
| |
| There are two typical origins for the extended error messages in J1939: |
| |
| 1. ``serr->ee_origin == SO_EE_ORIGIN_TIMESTAMPING``: |
| |
| In this case, the `serr->ee_info` field will contain one of the following |
| timestamp types: |
| |
| - ``SCM_TSTAMP_SCHED``: This timestamp is valid for Extended Transport |
| Protocol (ETP) transfers and simple transfers (8 bytes or less). It |
| indicates when a message or set of frames has been scheduled for |
| transmission. |
| |
| - For simple transfers (8 bytes or less), it marks the point when the |
| message is queued and ready to be sent onto the CAN bus. |
| |
| - For ETP transfers, it is sent after receiving a CTS (Clear to Send) |
| frame on the sender side, indicating that a new set of frames has been |
| scheduled for transmission. |
| |
| - The Transport Protocol (TP) case is currently not implemented for this |
| timestamp. |
| |
| - On the receiver side, the counterpart to this event for ETP is |
| represented by the ``J1939_EE_INFO_RX_DPO`` message, which indicates the |
| reception of a Data Page Offset (DPO) control frame. |
| |
| - ``SCM_TSTAMP_ACK``: This timestamp indicates the acknowledgment of the |
| message or session. |
| |
| - For simple transfers (8 bytes or less), it marks when the message has |
| been sent and an echo confirmation has been received from the CAN |
| controller, indicating that the frame was transmitted onto the bus. |
| |
| - For multi-frame transfers (TP or ETP), it signifies that the entire |
| session has been acknowledged, typically after receiving the End of |
| Message Acknowledgment (EOMA) packet. |
| |
| 2. ``serr->ee_origin == SO_EE_ORIGIN_LOCAL``: |
| |
| In this case, the `serr->ee_info` field will contain one of the following |
| J1939 stack-specific message types: |
| |
| - ``J1939_EE_INFO_TX_ABORT``: This message indicates that the transmission |
| of a message or session was aborted. The cause of the abort can come from |
| various sources: |
| |
| - **CAN stack failure**: The J1939 stack was unable to pass the frame to |
| the CAN framework for transmission. |
| |
| - **Echo failure**: The J1939 stack did not receive an echo confirmation |
| from the CAN controller, meaning the frame may not have been successfully |
| transmitted to the CAN bus. |
| |
| - **Protocol-level issues**: For multi-frame transfers (TP/ETP), this |
| could include protocol-related errors, such as an abort signaled by the |
| receiver or a timeout at the protocol level, which causes the session to |
| terminate prematurely. |
| |
| - The corresponding error code is stored in ``serr->ee_data`` |
| (``session->err`` on kernel side), providing additional details about |
| the specific reason for the abort. |
| |
| - ``J1939_EE_INFO_RX_RTS``: This message indicates that the J1939 stack has |
| received a Request to Send (RTS) control frame, signaling the start of a |
| multi-frame transfer using the Transport Protocol (TP) or Extended |
| Transport Protocol (ETP). |
| |
| - It informs the receiver that the sender is ready to transmit a |
| multi-frame message and includes details about the total message size |
| and the number of frames to be sent. |
| |
| - Statistics such as ``J1939_NLA_TOTAL_SIZE``, ``J1939_NLA_PGN``, |
| ``J1939_NLA_SRC_NAME``, and ``J1939_NLA_DEST_NAME`` are provided along |
| with the ``J1939_EE_INFO_RX_RTS`` message, giving detailed information |
| about the incoming transfer. |
| |
| - ``J1939_EE_INFO_RX_DPO``: This message indicates that the J1939 stack has |
| received a Data Page Offset (DPO) control frame, which is part of the |
| Extended Transport Protocol (ETP). |
| |
| - The DPO frame signals the continuation of an ETP multi-frame message by |
| indicating the offset position in the data being transferred. It helps |
| the receiver manage large data sets by identifying which portion of the |
| message is being received. |
| |
| - It is typically paired with a corresponding ``SCM_TSTAMP_SCHED`` event |
| on the sender side, which indicates when the next set of frames is |
| scheduled for transmission. |
| |
| - This event includes statistics such as ``J1939_NLA_BYTES_ACKED``, which |
| tracks the number of bytes acknowledged up to that point in the session. |
| |
| - ``J1939_EE_INFO_RX_ABORT``: This message indicates that the reception of a |
| multi-frame message (Transport Protocol or Extended Transport Protocol) has |
| been aborted. |
| |
| - The abort can be triggered by protocol-level errors such as timeouts, an |
| unexpected frame, or a specific abort request from the sender. |
| |
| - This message signals that the receiver cannot continue processing the |
| transfer, and the session is terminated. |
| |
| - The corresponding error code is stored in ``serr->ee_data`` |
| (``session->err`` on kernel side ), providing further details about the |
| reason for the abort, such as protocol violations or timeouts. |
| |
| - After receiving this message, the receiver discards the partially received |
| frames, and the multi-frame session is considered incomplete. |
| |
| In both cases, if ``SOF_TIMESTAMPING_OPT_ID`` is enabled, ``serr->ee_data`` |
| will be set to the session’s unique identifier (``session->tskey``). This |
| allows user space to track message transfers by their session identifier across |
| multiple frames or stages. |
| |
| In all other cases, ``serr->ee_errno`` will be set to ``ENOMSG``, except for |
| the ``J1939_EE_INFO_TX_ABORT`` and ``J1939_EE_INFO_RX_ABORT`` cases, where the |
| kernel sets ``serr->ee_data`` to the error stored in ``session->err``. All |
| protocol-specific errors are converted to standard kernel error values and |
| stored in ``session->err``. These error values are unified across system calls |
| and ``serr->ee_errno``. Some of the known error values are described in the |
| `Error Codes in the J1939 Stack` section. |
| |
| When the `J1939_EE_INFO_RX_RTS` message is provided, it will include the |
| following statistics for multi-frame messages (TP and ETP): |
| |
| - ``J1939_NLA_TOTAL_SIZE``: Total size of the message in the session. |
| - ``J1939_NLA_PGN``: Parameter Group Number (PGN) identifying the message type. |
| - ``J1939_NLA_SRC_NAME``: 64-bit name of the source ECU. |
| - ``J1939_NLA_DEST_NAME``: 64-bit name of the destination ECU. |
| - ``J1939_NLA_SRC_ADDR``: 8-bit source address of the sending ECU. |
| - ``J1939_NLA_DEST_ADDR``: 8-bit destination address of the receiving ECU. |
| |
| - For other messages (including single-frame messages), only the following |
| statistic is included: |
| |
| - ``J1939_NLA_BYTES_ACKED``: Number of bytes successfully acknowledged in the |
| session. |
| |
| The key flags for ``SO_TIMESTAMPING`` include: |
| |
| - ``SOF_TIMESTAMPING_OPT_ID``: Enables the use of a unique session identifier |
| (``tskey``) for each transfer. This identifier helps track message transfers |
| and errors as distinct sessions in user space. When this option is enabled, |
| ``serr->ee_data`` will be set to ``session->tskey``. |
| |
| - ``SOF_TIMESTAMPING_OPT_CMSG``: Sends timestamp information through control |
| messages (``struct scm_timestamping``), allowing the application to retrieve |
| timestamps alongside the data. |
| |
| - ``SOF_TIMESTAMPING_TX_SCHED``: Provides the timestamp for when a message is |
| scheduled for transmission (``SCM_TSTAMP_SCHED``). |
| |
| - ``SOF_TIMESTAMPING_TX_ACK``: Provides the timestamp for when a message |
| transmission is fully acknowledged (``SCM_TSTAMP_ACK``). |
| |
| - ``SOF_TIMESTAMPING_RX_SOFTWARE``: Provides timestamps for reception-related |
| events (e.g., ``J1939_EE_INFO_RX_RTS``, ``J1939_EE_INFO_RX_DPO``, |
| ``J1939_EE_INFO_RX_ABORT``). |
| |
| These flags enable detailed monitoring of message lifecycles, including |
| transmission scheduling, acknowledgments, reception timestamps, and gathering |
| detailed statistics about the communication session, especially for multi-frame |
| payloads like TP and ETP. |
| |
| Example: |
| |
| .. code-block:: c |
| |
| // Enable timestamping with various options, including session tracking and |
| // statistics |
| int sock_opt = SOF_TIMESTAMPING_OPT_CMSG | |
| SOF_TIMESTAMPING_TX_ACK | |
| SOF_TIMESTAMPING_TX_SCHED | |
| SOF_TIMESTAMPING_OPT_ID | |
| SOF_TIMESTAMPING_RX_SOFTWARE; |
| |
| setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &sock_opt, sizeof(sock_opt)); |
| |
| |
| |
| Dynamic Addressing |
| ------------------ |
| |
| Distinction has to be made between using the claimed address and doing an |
| address claim. To use an already claimed address, one has to fill in the |
| ``j1939.name`` member and provide it to ``bind(2)``. If the name had claimed an address |
| earlier, all further messages being sent will use that address. And the |
| ``j1939.addr`` member will be ignored. |
| |
| An exception on this is PGN 0x0ee00. This is the "Address Claim/Cannot Claim |
| Address" message and the kernel will use the ``j1939.addr`` member for that PGN if |
| necessary. |
| |
| To claim an address following code example can be used: |
| |
| .. code-block:: C |
| |
| struct sockaddr_can baddr = { |
| .can_family = AF_CAN, |
| .can_addr.j1939 = { |
| .name = name, |
| .addr = J1939_IDLE_ADDR, |
| .pgn = J1939_NO_PGN, /* to disable bind() rx filter for PGN */ |
| }, |
| .can_ifindex = if_nametoindex("can0"), |
| }; |
| |
| bind(sock, (struct sockaddr *)&baddr, sizeof(baddr)); |
| |
| /* for Address Claiming broadcast must be allowed */ |
| int value = 1; |
| setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)); |
| |
| /* configured advanced RX filter with PGN needed for Address Claiming */ |
| const struct j1939_filter filt[] = { |
| { |
| .pgn = J1939_PGN_ADDRESS_CLAIMED, |
| .pgn_mask = J1939_PGN_PDU1_MAX, |
| }, { |
| .pgn = J1939_PGN_REQUEST, |
| .pgn_mask = J1939_PGN_PDU1_MAX, |
| }, { |
| .pgn = J1939_PGN_ADDRESS_COMMANDED, |
| .pgn_mask = J1939_PGN_MAX, |
| }, |
| }; |
| |
| setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER, &filt, sizeof(filt)); |
| |
| uint64_t dat = htole64(name); |
| const struct sockaddr_can saddr = { |
| .can_family = AF_CAN, |
| .can_addr.j1939 = { |
| .pgn = J1939_PGN_ADDRESS_CLAIMED, |
| .addr = J1939_NO_ADDR, |
| }, |
| }; |
| |
| /* Afterwards do a sendto(2) with data set to the NAME (Little Endian). If the |
| * NAME provided, does not match the j1939.name provided to bind(2), EPROTO |
| * will be returned. |
| */ |
| sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, sizeof(saddr)); |
| |
| If no-one else contests the address claim within 250ms after transmission, the |
| kernel marks the NAME-SA assignment as valid. The valid assignment will be kept |
| among other valid NAME-SA assignments. From that point, any socket bound to the |
| NAME can send packets. |
| |
| If another ECU claims the address, the kernel will mark the NAME-SA expired. |
| No socket bound to the NAME can send packets (other than address claims). To |
| claim another address, some socket bound to NAME, must ``bind(2)`` again, but with |
| only ``j1939.addr`` changed to the new SA, and must then send a valid address claim |
| packet. This restarts the state machine in the kernel (and any other |
| participant on the bus) for this NAME. |
| |
| ``can-utils`` also include the ``j1939acd`` tool, so it can be used as code example or as |
| default Address Claiming daemon. |
| |
| Send Examples |
| ------------- |
| |
| Static Addressing |
| ^^^^^^^^^^^^^^^^^ |
| |
| This example will send a PGN (0x12300) from SA 0x20 to DA 0x30. |
| |
| Bind: |
| |
| .. code-block:: C |
| |
| struct sockaddr_can baddr = { |
| .can_family = AF_CAN, |
| .can_addr.j1939 = { |
| .name = J1939_NO_NAME, |
| .addr = 0x20, |
| .pgn = J1939_NO_PGN, |
| }, |
| .can_ifindex = if_nametoindex("can0"), |
| }; |
| |
| bind(sock, (struct sockaddr *)&baddr, sizeof(baddr)); |
| |
| Now, the socket 'sock' is bound to the SA 0x20. Since no ``connect(2)`` was called, |
| at this point we can use only ``sendto(2)`` or ``sendmsg(2)``. |
| |
| Send: |
| |
| .. code-block:: C |
| |
| const struct sockaddr_can saddr = { |
| .can_family = AF_CAN, |
| .can_addr.j1939 = { |
| .name = J1939_NO_NAME; |
| .addr = 0x30, |
| .pgn = 0x12300, |
| }, |
| }; |
| |
| sendto(sock, dat, sizeof(dat), 0, (const struct sockaddr *)&saddr, sizeof(saddr)); |
| |
| |
| Error Codes in the J1939 Stack |
| ------------------------------ |
| |
| This section lists all potential kernel error codes that can be exposed to user |
| space when interacting with the J1939 stack. It includes both standard error |
| codes and those derived from protocol-specific abort codes. |
| |
| - ``EAGAIN``: Operation would block; retry may succeed. One common reason is |
| that an active TP or ETP session exists, and an attempt was made to start a |
| new overlapping TP or ETP session between the same peers. |
| |
| - ``ENETDOWN``: Network is down. This occurs when the CAN interface is switched |
| to the "down" state. |
| |
| - ``ENOBUFS``: No buffer space available. This error occurs when the CAN |
| interface's transmit (TX) queue is full, and no more messages can be queued. |
| |
| - ``EOVERFLOW``: Value too large for defined data type. In J1939, this can |
| happen if the requested data lies outside of the queued buffer. For example, |
| if a CTS (Clear to Send) requests an offset not available in the kernel buffer |
| because user space did not provide enough data. |
| |
| - ``EBUSY``: Device or resource is busy. For example, this occurs if an |
| identical session is already active and the stack is unable to recover from |
| the condition. |
| |
| - ``EACCES``: Permission denied. This error can occur, for example, when |
| attempting to send broadcast messages, but the socket is not configured with |
| ``SO_BROADCAST``. |
| |
| - ``EADDRNOTAVAIL``: Address not available. This error occurs in cases such as: |
| |
| - When attempting to use ``getsockname(2)`` to retrieve the peer's address, |
| but the socket is not connected. |
| |
| - When trying to send data to or from a NAME, but address claiming for the |
| NAME was not performed or detected by the stack. |
| |
| - ``EBADFD``: File descriptor in bad state. This error can occur if: |
| |
| - Attempting to send data to an unbound socket. |
| |
| - The socket is bound but has no source name, and the source address is |
| ``J1939_NO_ADDR``. |
| |
| - The ``can_ifindex`` is incorrect. |
| |
| - ``EFAULT``: Bad address. Occurs mostly when the stack can't copy from or to a |
| sockptr, when there is insufficient data from user space, or when the buffer |
| provided by user space is not large enough for the requested data. |
| |
| - ``EINTR``: A signal occurred before any data was transmitted; see ``signal(7)``. |
| |
| - ``EINVAL``: Invalid argument passed. For example: |
| |
| - ``msg->msg_namelen`` is less than ``J1939_MIN_NAMELEN``. |
| |
| - ``addr->can_family`` is not equal to ``AF_CAN``. |
| |
| - An incorrect PGN was provided. |
| |
| - ``ENODEV``: No such device. This happens when the CAN network device cannot |
| be found for the provided ``can_ifindex`` or if ``can_ifindex`` is 0. |
| |
| - ``ENOMEM``: Out of memory. Typically related to issues with memory allocation |
| in the stack. |
| |
| - ``ENOPROTOOPT``: Protocol not available. This can occur when using |
| ``getsockopt(2)`` or ``setsockopt(2)`` if the requested socket option is not |
| available. |
| |
| - ``EDESTADDRREQ``: Destination address required. This error occurs: |
| |
| - In the case of ``connect(2)``, if the ``struct sockaddr *uaddr`` is ``NULL``. |
| |
| - In the case of ``send*(2)``, if there is an attempt to send an ETP message |
| to a broadcast address. |
| |
| - ``EDOM``: Argument out of domain. This error may happen if attempting to send |
| a TP or ETP message to a PGN that is reserved for control PGNs for TP or ETP |
| operations. |
| |
| - ``EIO``: I/O error. This can occur if the amount of data provided to the |
| socket for a TP or ETP session does not match the announced amount of data for |
| the session. |
| |
| - ``ENOENT``: No such file or directory. This can happen when the stack |
| attempts to transfer CTS or EOMA but cannot find a matching receiving socket |
| anymore. |
| |
| - ``ENOIOCTLCMD``: No ioctls are available for the socket layer. |
| |
| - ``EPERM``: Operation not permitted. For example, this can occur if a |
| requested action requires ``CAP_NET_ADMIN`` privileges. |
| |
| - ``ENETUNREACH``: Network unreachable. Most likely, this occurs when frames |
| cannot be transmitted to the CAN bus. |
| |
| - ``ETIME``: Timer expired. This can happen if a timeout occurs while |
| attempting to send a simple message, for example, when an echo message from |
| the controller is not received. |
| |
| - ``EPROTO``: Protocol error. |
| |
| - Used for various protocol-level errors in J1939, including: |
| |
| - Duplicate sequence number. |
| |
| - Unexpected EDPO or ECTS packet. |
| |
| - Invalid PGN or offset in EDPO/ECTS. |
| |
| - Number of EDPO packets exceeded CTS allowance. |
| |
| - Any other protocol-level error. |
| |
| - ``EMSGSIZE``: Message too long. |
| |
| - ``ENOMSG``: No message available. |
| |
| - ``EALREADY``: The ECU is already engaged in one or more connection-managed |
| sessions and cannot support another. |
| |
| - ``EHOSTUNREACH``: A timeout occurred, and the session was aborted. |
| |
| - ``EBADMSG``: CTS (Clear to Send) messages were received during an active data |
| transfer, causing an abort. |
| |
| - ``ENOTRECOVERABLE``: The maximum retransmission request limit was reached, |
| and the session cannot recover. |
| |
| - ``ENOTCONN``: An unexpected data transfer packet was received. |
| |
| - ``EILSEQ``: A bad sequence number was received, and the software could not |
| recover. |
| |