# CAN-J1939 on linux ## CAN on linux See [Wikipedia:socketcan](http://en.wikipedia.org/wiki/Socketcan) ## J1939 networking in short * Add addressing on top of CAN (destination address & broadcast) * Any (max 1780) length packets. Packets of 9 or more use **Transport Protocol** (fragmentation) Such packets use different CANid for the same PGN. * only **29**bit, non-**RTR** CAN frames * CAN id is composed of * 0..8: SA (source address) * 9..26: * PDU1: PGN+DA (destionation address) * PDU2: PGN * 27..29: PRIO * SA / DA may be dynamically assigned via j1939-81 Fixed rules of precedence in Specification, no master necessary ## J1939 on SocketCAN J1939 is *just another protocol* that fits in the Berkely sockets. socket(AF_CAN, SOCK_DGRAM, CAN_J1939) ## differences from CAN_RAW ### addressing SA, DA & PGN are used, not CAN id. Berkeley socket API is used to communicate these to userspace: * SA+PGN is put in sockname ([getsockname](http://man7.org/linux/man-pages/man2/getsockname.2.html)) * DA+PGN is put in peername ([getpeername](http://man7.org/linux/man-pages/man2/getpeername.2.html)) PGN is put in both structs PRIO is a datalink property, and irrelevant for interpretation Therefore, PRIO is not in *sockname* or *peername*. The *data* that is [recv][recvfrom] or [send][sendto] is the real payload. Unlike CAN_RAW, where addressing info is data. ### Packet size J1939 handles packets of 8+ bytes with **Transport Protocol** fragmentation transparently. No fixed data size is necessary. send(sock, data, 8, 0); will emit a single CAN frame. send(sock, data, 9, 0); will use fragementation, emitting 1+ CAN frames. # Enable j1939 CAN has no protocol id field. Enabling protocols must be done manually ### netlink ip link set can0 j1939 on ### procfs for legacy kernel (2.6.25) This API is dropped for kernels with netlink support! echo can0 > /proc/net/can-j1939/net # Using J1939 ## BSD socket implementation * socket * bind / connect * recvfrom / sendto * getsockname / getpeername ## Modified *struct sockaddr_can* struct sockaddr_can { sa_family_t can_family; int can_ifindex; union { struct { __u64 name; __u32 pgn; __u8 addr; } j1939; } can_addr; } * *can_addr.j1939.pgn* is PGN * *can_addr.j1939.addr* & *can_addr.j1939.name* determine the ECU * receiving address information, *addr* is always set, *name* is set when available. * When providing address information, *name* != 0 indicates dynamic addressing ## iproute2 ### Static addressing ip addr add j1939 0x80 dev can0 ### Dynamic addressing ip addr add j1939 name 0x012345678abcdef dev can0 # Kickstart guide to j1939 on linux ## Prepare using VCAN You may skip this step entirely if you have a functional **can0** bus on your system. Load module, when *vcan* is not in-kernel modprobe vcan Create a virtual can0 device and start the device ip link add can0 type vcan ip link set can0 up ## First steps with j1939 Use [testj1939](testj1939.c) When *can-j1939* is compiled as module, load it. modprobe can-j1939 Enable the j1939 protocol stack on the CAN device ip link set can0 j1939 on Most of the subsequent examples will use 2 sockets programs (in 2 terminals). One will use CAN_J1939 sockets using *testj1939*, and the other will use CAN_RAW sockets using cansend+candump. testj1939 can be told to print the used API calls by adding **-v** program argument. ### receive without source address Do in terminal 1 ./testj1939 -r can0: Send raw CAN in terminal 2 cansend can0 1823ff40#0123 You should have this output in terminal 1 40 02300: 01 23 This means, from NAME 0, SA 40, PGN 02300 was received, with 2 databytes, *01* & *02*. now emit this CAN message: cansend can0 18234140#0123 In J1939, this means that ECU 0x40 sends directly to ECU 0x41 Since we did not bind to address 0x41, this traffic is not meant for us and *testj1939* does not receive it. ### Use source address ./testj1939 can0:0x80 will say ./testj1939: bind(): Cannot assign requested address Since J1939 maintains addressing, **0x80** has not yet been assigned as an address on **can0** . This behaviour is very similar to IP addressing: you cannot bind to an address that is not your own. Now tell the kernel that we *own* address 0x80. It will be available from now on. ip addr add j1939 0x80 dev can0 ./testj1939 can0:0x80 now succeeds. ### receive with source address Terminal 1: ./testj1939 -r can0:0x80 Terminal 2: cansend can0 18238040#0123 Will emit this output 40 02300: 01 23 This is because the traffic had destination address __0x80__ . ### send Open in terminal 1: candump -L can0 And to these test in another terminal ./testj1939 -s can0:0x80 This produces **1BFFFF80#0123456789ABCDEF** on CAN. ./testj1939 -s can0: will produce exactly the same because **0x80** is the only address currently assigned to **can0:** and is used by default. ### Multiple source addresses on 1 CAN device ip addr add j1939 0x90 dev can0 ./testj1939 -s can0:0x90 produces **1BFFFF90#0123456789ABCDEF** , ./testj1939 -s can0: still produces **1BFFFF80#0123456789ABCDEF** , since **0x80** is the default _source address_. Check ip addr show can0 emits X: can0: mtu 16 qdisc noqueue state UNKNOWN link/can can-j1939 0x80 scope link can-j1939 0x90 scope link 0x80 is the first address on can0. ### Use specific PGN ./testj1939 -s can0:,0x12345 emits **1923FF80#0123456789ABCDEF** . Note that the real PGN is **0x12300**, and destination address is **0xff**. ### Emit destination specific packets The destination field may be set during sendto(). *testj1939* implements that like this ./testj1939 -s can0:,0x12345 can0:0x40 emits **19234080#0123456789ABCDEF** . The destination CAN iface __must__ always match the source CAN iface. Specifing one during bind is therefore sufficient. ./testj1939 -s can0:,0x12300 :0x40 emits the very same. ### Emit different PGNs using the same socket The PGN is provided in both __bind( *sockname* )__ and __sendto( *peername* )__ , and only one is used. *peername* PGN has highest precedence. For broadcasted transmissions ./testj1939 -s can0:,0x12300 :,0x32100 emits **1B21FF80#0123456789ABCDEF** rather than 1923FF80#012345678ABCDEF Desitination specific transmissions ./testj1939 -s can0:,0x12300 :0x40,0x32100 emits **1B214080#0123456789ABCDEF** . It makes sometimes sense to omit the PGN in __bind( *sockname* )__ . ### Larger packets J1939 transparently switches to *Transport Protocol* when packets do not fit into single CAN packets. ./testj1939 -s20 can0:0x80 :,0x12300 emits: 18ECFF80#20140003FF002301 18EBFF80#010123456789ABCD 18EBFF80#02EF0123456789AB 18EBFF80#03CDEF01234567 The fragments for broadcasted *Transport Protocol* are seperated __50ms__ from each other. Destination specific *Transport Protocol* applies flow control and may emit CAN packets much faster. ./testj1939 -s20 can0:0x80 :0x90,0x12300 emits: 18EC9080#1014000303002301 18EC8090#110301FFFF002301 18EB9080#010123456789ABCD 18EB9080#02EF0123456789AB 18EB9080#03CDEF01234567 18EC8090#13140003FF002301 The flow control causes a bit overhead. This overhead scales very good for larger J1939 packets. ## Advanced topics with j1939 ### Change priority of J1939 packets ./testj1939 -s can0:0x80,0x0100 ./testj1939 -s -p3 can0:0x80,0x0200 emits 1801FF80#0123456789ABCDEF 0C02FF80#0123456789ABCDEF ### using connect ### advanced filtering ## dynamic addressing