From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kurt Van Dijck Subject: [PATCH v4 4/5] can-j1939: add documentation Date: Wed, 27 Apr 2011 11:00:11 +0200 Message-ID: <20110427090011.GE757@kurt.e-circ.dyndns.org> References: <20110427085330.GA757@kurt.e-circ.dyndns.org> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org, netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org Return-path: Content-Disposition: inline In-Reply-To: <20110427085330.GA757-ozGf4kBk5synFtIcQ8t7k3L8HoS0Hn3T@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: socketcan-core-bounces-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org Errors-To: socketcan-core-bounces-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org List-Id: netdev.vger.kernel.org Add documentation of the SAE J1939 protocol stack Signed-off-by: Kurt Van Dijck --- Documentation/networking/j1939.txt | 576 ++++++++++++++++++++++++++++++++++++ MAINTAINERS | 8 + 2 files changed, 584 insertions(+), 0 deletions(-) create mode 100644 Documentation/networking/j1939.txt diff --git a/Documentation/networking/j1939.txt b/Documentation/networking/j1939.txt new file mode 100644 index 0000000..ef0a963 --- /dev/null +++ b/Documentation/networking/j1939.txt @@ -0,0 +1,576 @@ +============================================================================ + +j1939.txt + +Readme file for the J1939 Protocol + +This file contains + + 1 Overview / What is j1939 + 1.1 specifications used + + 2 Motivation + + 3 J1939 concepts + 3.1 socket type + 3.2 addressing + 3.3 priority + 3.4 PGN + 3.5 filtering + 3.6 destinations with dynamic address + + 4 How to use J1939 + 4.1 rtnetlink interface + 4.2 API calls + 4.2.1 Message flags during sendmsg + 4.2.2 SCM_J1939_DEST_ADDR & SCM_J1939_DEST_NAME + 4.2.3 SCM_J1939_PRIORITY + 4.3 Dynamic addressing + 4.4 Send Examples + 4.4.1 Static address + 4.4.2 Dynamic address + 4.4.3 Mixed mode + + 5 socket options + 5.1 SO_J1939_FILTER + 5.2 SO_J1939_PROMISC + 5.3 SO_J1939_RECV_OWN + 5.4 SO_J1939_SEND_PRIO + + 6 can-j1939 procfs interface + 6.1 /proc/net/can-j1939/ecu + 6.2 /proc/net/can-j1939/filter + 6.3 /proc/net/can-j1939/sock + 6.4 /proc/net/can-j1939/transport + + 7 can-j1939 SYSCTL + 7.1 /proc/sys/net/can-j1939/transport_max_payload_in_bytes + 7.2 /proc/sys/net/can-j1939/transport_cts_nr_of_frames + 7.3 /proc/sys/net/can-j1939/transport_tx_retry_ms + + 8 Credits + +============================================================================ + +1. Introduction +-------------------------------- + + 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 exists, which differ from the + original j1939 on the application level, like MilCAN, NMEA2000 and + especially ISO-11783 (ISOBUS). This last one specifies the so-called ETP + (Extended Transport Protocol) which is has been included in this + implementation. This inclusion results in a maximum packet size of + ((2^24)-1)*7 bytes + + +1.1 specifications used + + SAE J1939-21 : data link layer + SAE J1939-81 : network management + ISO 11783-6 : Virtual Terminal (Extended Transport Protocol) + + +2. 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 1 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 1 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 these + functionality in the kernel eliminates this functionality as a requirement + for _every_ userspace process that communicates via J1939. This results in + a consistent J1939 bus with proper addressing. + + * transport: + Both TP & ETP reuse some PGN's to relay big packets over them. Different + processes may thus use the same TP & ETP PGN's without actually knowing it. + The individual TP & ETP sessions _must_ be serialized (synchronised) + between different processes. The kernel solves this problem properly, and + eliminates the serialisation (synchronisation) as a requirement for + _every_ userspace 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 userspace. + + The j1939 sockets operate on CAN network devices (see SocketCAN). Any j1939 + userspace library operating on CAN raw sockets will still operate properly. + Since such library does not communicate with the in-kernel implementation, + care must be taken that these 2 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. + + +3. J1939 concepts +-------------------------------- + +3.1 PGN + + The PGN (Parameter Group Number) is a number to identify a packet. The PGN + is composed as follows: + 1 bit : Reserved Bit + 1 bit : Data Page + 8 bits : PF (PDU Format) + 8 bits : PS (PDU Specific) + + In J1939-21, distinction is made between PDU1 Format (where PF < 240) and + PDU2 Format (where PF >= 240). Furthermore, when using 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. + + 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 userspace to kernel (or visa versa) and PDU2 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 apropriate bits of the identifier by the kernel. + + +3.2 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 forseen + in the kernel. In J1939 any ECU is known by it's 64-bit NAME. At the moment + of succesfull 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 soon after + reception. + + Mixed mode packets (from a static to a dynamic address or vice versa) are + allowed. The BSD sockets define seperate API calls for getting/setting the + local & remote address and are applicable for J1939 sockets. + + +3.3 Filtering + + Similar to SocketCAN, j1939 defines filters per socket that a user can set + in order to receive a subset of the j1939 traffic. Filtering can base on + * SA + * NAME + * PGN + + There is a semantic difference with SocketCAN with regard to filtering. + 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. + The rationale behind this difference originates in the filter capabilities. + Where SocketCAN filters on only 1 orthogonal (can id), J1939 can filter + on 3 orthogonal properties (sa, name, pgn). + + When a filter on the SA is set, j1939 traffic with a matching SA, but with + its NAME set (aka having claimed SA successfully) will match, although + the filter would not match its NAME. + + Filtering on priority is _not_ supported. + + +4. How to use J1939 +-------------------------------- + +4.1 rtnetlink interface + + Per default j1939 is not active. Specifying can_ifindex != 0 in bind(2) + or connect(2) needs an active j1939 on that interface. You must have done + $ ip link set canX j1939 on + on that interface. + + $ ip link set canX j1939 down + disables j1939 on canX. + + Assigning addresses is done via + $ ip addr add dev canX j1939 0xXX + statically or + $ ip addr add dev canX j1939 name 0xXX + dynamically. In the latter case, address claiming must take place + before other traffic can leave. + + Removing addresses is done similarly via + $ ip addr del dev canX j1939 0xXX + $ ip addr del dev canX j1939 name 0xXX + + A static address cannot be assigned together with a 64bit name. + +4.2 API calls + + Like TCP/IP and CAN, you first need to open a socket for communicating over a + CAN network. To use j1939, include . From there, + will be included too. + To open a socket, you would write + + 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 never appropriate. + + 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 + (which is different from TCP/IP due to different addressing) 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 succeeded. bind(2) assigns a local + address to a socket. For this to succeed, you can only choose addresses + that have been assigned earlier (see 4.1). When an empty address is assigned + (ie. SA=0xff && name=0), a default is taken for the device that is bound to. + + Different from CAN is that the payload data is just the data that get send, + without it's 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: + struct sockaddr_can { + sa_family_t can_family; + int can_ifindex; + union { + struct { + __u64 name; + __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 source address. + + When sending data, the source address is applied as follows: If + can_addr.j1939.name != 0 the NAME is looked up by the kernel and the + corresponding Source Address is used. If can_addr.j1939.name == 0, + can_addr.j1939.addr is used. + + After a bind(2), the local address is assigned, i.e. the source address. + After a connect(2), the remote address is assigned, i.e. the destination + address. + + Both write(2) and send(2) will send a packet with local address from bind, + remote address from connect(2). When the address was not set, a broadcast is + sent. The PGN is used from bind(2) or overruled with sendto(2), which will + override the destination address when valid, and the PGN when valid. + + Both read(2) and recv(2) will receive packets matching the sockets filters. + recvfrom(2) will receive these packets with originator's address. + + When creating a socket, reasonable defaults have been set. Some options can be + modified with setsockopt(2) & getsockopt(2). + +4.2.1 Message flags during sendmsg + + send(2), sendto(2) and sendmsg(2) take a 'flags' argument. J1939 interpretes + these flags during outgoing traffic: + + * MSG_DONTWAIT determines nonblocking operation. When a packet must wait for + any reason, -EAGAIN is returned. + + * MSG_SYN + Packets flagged with MSG_SYN will wait for all pending packets on a socket + to be sent before trying to send. This means that if a socket just started + a Transport Protocol session, a packet with MSG_SYN will wait for that + session to complete before proceeding. + Traffic without MSG_SYN (on that very same socket) will still continue. + +4.2.2 SCM_J1939_DEST_ADDR & SCM_J1939_DEST_NAME + + Different received j1939 packets could have had different destionations: + - broadcast packet, i.e. no destination address + - destination address that matches the sockets local address + - destination address that matches _a_ local address on the system, and the + socket had no local address defined. + - SO_J1939_PROMISC was set + + The destination address & destination name (if applicable) are attached + to the msghdr in the recvmsg(2) call. It can be extracted using cmsg(3) macros, + with cmsg_level == SOL_J1939 && cmsg_type == SCM_J1939_DEST_ADDR + or SCM_J1939_DEST_NAME. The returned data is a uint8_t/uint64_t. + +4.2.3 SCM_J1939_PRIORITY + + Attached to the msghdr is also the packet's priority on the bus. This is a + uint8_t, packed as cmsg_type == SCM_J1939_PRIORITY. + +4.3 Dynamic Addressing + + Distinction has to be made in and 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 PGN's 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 when the kernel will use the j1939.addr member for that + pgn if necessary. + + To claim an address, bind(2) with: + j1939.pgn set to 0x0ee00 + j1939.addr set to the desired Source Address. + j1939.name set to the NAME you want the Source Address to claim to. + + Afterwards do a write(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. One might use sendto(2) also to send the Addres Claim. In + that case, the j1939.addr member must be set to the broadcast address (255) + and the j1939.pgn must be set to 0x0ee00. If This combination is not given, + EPROTO is returned. + + If no-one else contest 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. + + +4.4 Send Examples + +4.4.1 Static addressing + + This example will send a pgn (0x12300) from SA 0x20 to DA 0x30. + + Add the address to the system: + $ ip addr add j1939 0x20 dev can0 + + Bind: + struct sockaddr_can addr; + + memset(&addr, 0, sizeof(addr)); + addr.can_ifindex = ifindex("can0"); // ifindex is a substitute. + addr.can_addr.j1939.name = J1939_NO_NAME; + addr.can_addr.j1939.addr = 0x20; + addr.can_addr.j1939.pgn = J1939_NO_PGN; + + bind(sk, (void *)&addr, sizeof(addr)); + + Now, the socket 'sk' is bound to the address 0x20. Since no pgn + was specified during bound, a pgn will be necessary during sendto() operations. + Alternatively, specifying addr.can_addr.j1939.pgn during bind() allows + for using send() & write(), since a default pgn (the pgn specified during bind()) + can be used then. + + Send: + struct sockaddr_can addr; + + memset(&addr, 0, sizeof(addr)); + addr.can_addr.j1939.name = J1939_NO_NAME; + addr.can_addr.j1939.addr = 0x30; + addr.can_addr.j1939.pgn = 0x12300; + // addr.can_ifindex is not necessary here. + + sendto(sk, data, sizeof(data), 0, (void *)&addr, sizeof(addr)); + +4.4.2 Dynamic addressing + + This example will send a pgn (0x12300) from 12345678 to 9ABCDEF + + Add the name to the system: + $ ip addr add j1939 name 12345678 dev can0 + + Start an address claiming daemon (e.g. jacd) + $ jacd -r 0x20-0x30 12345678 can0 & + + Bind: + struct sockaddr_can addr; + + memset(&addr, 0, sizeof(addr)); + addr.can_ifindex = ifindex("can0"); // ifindex is a substitute. + addr.can_addr.j1939.name = 0x12345678ULL; + addr.can_addr.j1939.addr = J1939_NO_ADDR; + addr.can_addr.j1939.pgn = J1939_NO_PGN; + + bind(sk, (void *)&addr, sizeof(addr)); + + Send: + struct sockaddr_can addr; + + memset(&addr, 0, sizeof(addr)); + addr.can_addr.j1939.name = 0x9ABCDEFULL; + addr.can_addr.j1939. = J1939_NO_ADDR; + addr.can_addr.j1939.pgn = 0x12300; + + sendto(sk, data, sizeof(data), 0, (void *)&addr, sizeof(addr)); + +4.4.3 Mixed mode + + A scenario that sends a packet from a static address to a dynamic address + or vice versa is called 'mixed mode' here. + + Combining the setup of the static address with a sendto() to a dynamic + address from the above examples is legal, and implements such mixed mode + addressing. The same applies for the setup of the dynamic address combined + with the sendto() towards a dynamic address. + + +5 Socket Options +-------------------------------- + + j1939 sockets have some options that are configurable via setsockopt(2). + Each of those options is initialized with a reasonable default. + + +5.1 SO_J1939_FILTER + + As mentioned above, J1939 supports filtering in both NAME, Source Address + and PGN. All members must match. + + struct j1939_filter filter = { + .name = ... + .name_mask = ... + .addr = ... + .addr_mask = ... + .pgn = ... + .pgn_mask = ... + } + + setsockopt(s, SOL_CAN_J1939, SO_J1939_FILTER, &filter, sizeof(filter)); + + +5.2 SO_J1939_PROMISC + + When set, j1939 will receive all packets, not just those with a destination + on the local system. + default off. + + int promisc = 1; /* 0 = disabled (default), 1 = enabled */ + + setsockopt(s, SOL_CAN_J1939, SO_J1939_PROMISC, &promisc, sizeof(promisc)); + + +5.3 SO_J1939_RECV_OWN + + All the sent j1939 packets are looped back in the system. + The reception of the j1939 packets on the same socket that was + sending the j1939 packet is assumed to be unwanted and therefore + disabled by default. This default behaviour may be changed on + demand: + + int recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */ + + setsockopt(s, SOL_CAN_J1939, SO_J1939_RECV_OWN, + &recv_own_msgs, sizeof(recv_own_msgs)); + + +5.4 SO_J1939_SEND_PRIO + + To set the priority field for outgoing packets, the SO_J1939_SEND_PRIO can + be changed. This int field specifies the priority that will be used. + j1939 defines a priority between 0 and 7 inclusive, + with 7 the lowest priority. + Per default, the priority is set to 6 (conforming J1939). + This priority socket option operates on the same value that is modified + with + + setsockopt(s, SOL_SOCKET, SO_PRIORITY, &pri, sizeof(pri)) + + socketoption, with a difference that SOL_SOCKET/SO_PRIORITY is defined with + 0 the lowest priority. SOL_CAN_J1939/SO_J1939_SEND_PRIO inverts this value + for you. + + +6. /proc/net/can-j1939 Interface. +-------------------------------- + + Files giving you a view on the in-kernel operation of J1939 are located at: + /proc/net/j1939. + +6.1 /proc/net/can-j1939/ecu + + This file gives an overview of the known ECU's to the kernel. + - iface : network interface they operate on. + - SA : current address. + - name : 64bit NAME + - flags : 'L' = local, 'R' = remote + +6.2 /proc/net/can-j1939/filter + +6.3 /proc/net/can-j1939/sock + + This file gives a list of all j1939 sockets currently open. + - iface : network interface + - flags : + 'b' : bound + 'c' : connected + 'P' : PROMISC + 'o' : RECV_OWN + 'd' : RECV_DEST + 'p' : RECV_PRIO + - local: [NAME],SA + - remote: [NAME]/MASK,DA + - pgn : PGN + - prio : priority + - pending : # packets pending (see MSG_SYN on 4.2.1) + +6.4 /proc/net/can-j1939/transport + + This file shows a list of pending transport sessions + - iface + - src : XX (addr) or XXXXXXXXXXXXXXXX (name) + - dst : XX or XXXXXXXXXXXXXXXX or '-' (broadcast) + - pgn : + - done/total : current # transferred bytes / total + + +7. /proc/sys/net/can-j1939 - SYSCTL +-------------------------------- + + Via these sysctl files, some parameters of the j1939 module can be tuned. + +7.1 /proc/sys/net/can-j1939/transport_max_payload_in_bytes [int] + + Is the maximum packet size to accept on both transmit & receive side. + Bigger packets will be rejected (local sender), aborted (local receiver) + or ignored (broadcasts & remote recievers in PROMISC). + +7.2 /proc/sys/net/can-j1939/transport_cts_nr_frames [int] + + Controls the number of packets to allow between consecutive CTS frames + (default 255). + This number is communicated within the CTS frame from receiver to transmitter. + Setting this has effect on received transport sessions only. + +7.3 /proc/sys/net/can-j1939/transport_tx_retry_ms [int] + + Controls how many time to wait before retrying to send an individual TP + flow or data packet after transmission failure (default 20). + + +8. Credits +-------------------------------- + + Kurt Van Dijck (j1939 core, transport protocol, API) + Pieter Beyens (j1939 core, address claiming) + diff --git a/MAINTAINERS b/MAINTAINERS index b5266ad..ec7b016 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1648,6 +1648,14 @@ F: include/linux/can/error.h F: include/linux/can/netlink.h F: include/linux/can/platform/ +CAN-J1939 NETWORK LAYER +M: Kurt Van Dijck +L: socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org +L: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org +S: Maintained +F: net/can/j1939/ +F: include/linux/can/j1939.h + CELL BROADBAND ENGINE ARCHITECTURE M: Arnd Bergmann L: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org -- 1.7.2.5