GithubHelp home page GithubHelp logo

hartkopp / can-isotp Goto Github PK

View Code? Open in Web Editor NEW
233.0 32.0 66.0 106 KB

Linux Kernel Module for ISO 15765-2:2016 CAN transport protocol PLEASE NOTE: This module is part of the mainline Linux kernel since version 5.10

License: Other

Makefile 4.49% C 95.51%

can-isotp's Introduction

============================================================================

README.isotp

CREDITS

This repository contains a rework to simplify the build of the former ISO-TP
development repository at https://github.com/hartkopp/can-isotp-modules.

The build and repository cleanup provided by Nathan L. Conrad  was merged from
https://github.com/downwith/linux-isotp . Thanks Nathan!

DOWNLOAD and BUILD

1. Download repository and enter the repositories root directory

      git clone https://github.com/hartkopp/can-isotp.git

      cd can-isotp

2. Build ISO-TP kernel module

   Ensure build dependencies are installed. E.g. for Debian (or Ubuntu):

      sudo apt-get install build-essential linux-headers-$(uname -r)

   To build:

      (you need to be in the repositories root path)

      make

   To install (optional):

      sudo make modules_install


3. When the PF_CAN core module is loaded ('modprobe can') the ISO-TP module
   can be loaded into the kernel with

       insmod ./net/can/can-isotp.ko

   When the can-isotp.ko module has been installed into the Linux Kernels
   modules directory (e.g. with 'make modules_install') the module should
   load automatically when opening a CAN_ISOTP socket.

   Note: on UEFI systems with Secure Boot enabled, it is not possible to insert
   unsigned kernel modules. One option is to sign them manually. The comments
   linked below can help you in the process:
   #25 (comment)
   #25 (comment)

----------------------------------------------------------------------------

Readme file for ISO 15765-2 CAN transport protocol for protocol family CAN

* This implementation is already widely used in automotive use-cases, e.g.
* for UDS based OBD diagnosis. Although some small adaptions may be applied
* to make it ready for Linux Mainline. Feedback is welcome.
*
* Current behaviour:
*
* - no ISO-TP specific return values are provided to the userspace
* - when a transfer (tx) is on the run the next write() blocks until it's done
* - no support for sending wait frames to the data source in the rx path


  1 What is ISO-TP for CAN

  2 Tools and Examples
    2.1 isotpsend - send PDUs from stdin to CAN
    2.2 isotprecv - print received PDU on stdout
    2.3 isotpdump - dump CAN frames with PCI decoding (using CAN_RAW socket)
    2.4 isotpsniffer - dump reassembled ISO-TP PDUs (using CAN_ISOTP socket)
    2.5 isotptun - create an IP tunnel over unreliable ISO-TP PDUs

  3 Remarks
    3.1 tx_queue_len on real CAN busses (!!!)
    3.2 State of the Socket API & Discussion

1 What is ISO-TP for CAN
------------------------

  CAN Transport Protocols offer support for segmented Point-to-Point
  communication between CAN nodes via two defined CAN Identifiers.
  This protocol driver implements data transfers according ISO 15765-2.

  CAN ISO-TP is an unreliable datagram protocol and is implemented like this.
  For that reason error indications, like 'dropped PDUs in the receive path due
  to wrong SequenceNumbers' are intentionally not supported.
  See discussion in section 3.2

  Code examples of how to use ISO-TP sockets can be found in the source code
  of the available tools described below. The API is still a RFC and will be
  described in detail later, when it's finalized.


2 Tools and Examples
--------------------

  The source code of these tools can be found in the can-utils repository
  on GitHub at https://github.com/linux-can/can-utils

  For the examples below we assume a test setup with two hosts:

         _______          _______ 
        |       |        |       |
        | Host1 |        | Host2 |
        |       |        |       |
        | can1  |        | can2  |
        |_______|        |_______|
            |                |
     |------------------------------| CAN bus


  2.1 isotpsend - send PDUs from stdin to CAN

  isotpsend gives this help when invoked without any parameters:

  Usage: isotpsend [options] <CAN interface>
  Options: -s <can_id>  (source can_id. Use 8 digits for extended IDs)
           -d <can_id>  (destination can_id. Use 8 digits for extended IDs)
           -x <addr>    (extended addressing mode. Use 'any' for all addresses)
           -p <byte>    (set and enable padding byte)
           -P <mode>    (check padding in FC. (l)ength (c)ontent (a)ll)
           -t <time ns> (transmit time in nanosecs)

  CAN IDs and addresses are given and expected in hexadecimal values.
  The pdu data is expected on STDIN in space separated ASCII hex values.
  
  Example (send ISOTP PDU from Host2 to Host1):
  echo 11 22 33 44 55 66 DE AD BE EF | isotpsend -s 321 -d 123 can2


  2.2 isotprecv - print received PDU on stdout

  isotprecv gives this help when invoked without any parameters:

  Usage: isotprecv [options] <CAN interface>
  Options: -s <can_id>  (source can_id. Use 8 digits for extended IDs)
           -d <can_id>  (destination can_id. Use 8 digits for extended IDs)
           -x <addr>    (extended addressing mode.)
           -p <byte>    (set and enable padding byte)
           -P <mode>    (check padding in SF/CF. (l)ength (c)ontent (a)ll)
           -b <bs>      (blocksize. 0 = off)
           -m <val>     (STmin in ms/ns. See spec.)
           -w <num>     (max. wait frame transmissions.)
           -l           (loop: do not exit after pdu receiption.)

  CAN IDs and addresses are given and expected in hexadecimal values.
  The pdu data is written on STDOUT in space separated ASCII hex values.

  Example (receive ISOTP PDU from Host2 on Host1):
  isotprecv -s 123 -d 321 -l can1

  In this example '-l' is set which causes isotprecv to continue listening on
  the given connection after printing a received PDU.


  2.3 isotpdump - dump CAN frames with PCI decoding (using CAN_RAW socket)

  isotpdump gives this help when invoked without any parameters:

  Usage: isotpdump [options] <CAN interface>
  Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)
           -d <can_id> (destination can_id. Use 8 digits for extended IDs)
           -x <addr>   (extended addressing mode. Use 'any' for all addresses)
           -c          (color mode)
           -a          (print data also in ASCII-chars)
           -t <type>   (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)

  CAN IDs and addresses are given and expected in hexadecimal values.

  Example (dump CAN Frames on Host1):
  isotpdump -s 123 -d 321 -c -ta can1


  2.4 isotpsniffer - dump reassembled ISO-TP PDUs (using CAN_ISOTP socket)

  The difference to isotpdump is, that isotpsniffer opens two CAN_ISOTP
  sockets and sets the CAN_ISOTP_LISTEN_MODE flag on both of these sockets.
  This causes the ISO-TP protocol driver to reassemble the received data but
  not send and flow control frames on the CAN bus.

  isotpsniffer gives this help when invoked without any parameters:

  Usage: isotpsniffer [options] <CAN interface>
  Options: -s <can_id> (source can_id. Use 8 digits for extended IDs)
           -d <can_id> (destination can_id. Use 8 digits for extended IDs)
           -x <addr>   (extended addressing mode.)
           -c          (color mode)
           -t <type>   (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)
           -f <format> (1 = HEX, 2 = ASCII, 3 = HEX & ASCII - default: 3)
           -h <len>    (head: print only first <len> bytes)

  CAN IDs and addresses are given and expected in hexadecimal values.

  Example (dump reassembled ISO-TP PDUs on Host1):
  isotpsniffer -s 123 -d 321 -c -ta can1


  2.5 isotptun - create an IP tunnel over unreliable ISO-TP PDUs

  The ISO-TP provides an unreliable datagram protocol with PDU sizes up to
  4095 bytes. Having Linux tunnel driver in mind creating an IP over ISO-TP
  tunnel became obvious - so here it is ;-)

  From linux/Documentation/networking/tuntap.txt:
  TUN/TAP provides packet reception and transmission for user space programs. 
  It can be seen as a simple Point-to-Point or Ethernet device, which,
  instead of receiving packets from physical media, receives them from 
  user space program and instead of sending packets via physical media 
  writes them to the user space program. 

  isotptun gives this help when invoked without any parameters:

  Usage: isotptun [options] <CAN interface>

  This program creates a Linux tunnel netdevice 'ctunX' and transfers the
  ethernet frames inside ISO15765-2 (unreliable) datagrams on CAN.

  Options: -s <can_id>  (source can_id. Use 8 digits for extended IDs)
           -d <can_id>  (destination can_id. Use 8 digits for extended IDs)
           -x <addr>    (extended addressing mode.)
           -p <byte>    (padding byte rx path)
           -q <byte>    (padding byte tx path)
           -P <mode>    (check padding. (l)ength (c)ontent (a)ll)
           -t <time ns> (transmit time in nanosecs)
           -b <bs>      (blocksize. 0 = off)
           -m <val>     (STmin in ms/ns. See spec.)
           -w <num>     (max. wait frame transmissions.)
           -h           (half duplex mode.)
           -v           (verbose mode. Print symbols for tunneled msgs.)

  CAN IDs and addresses are given and expected in hexadecimal values.
  Use e.g. 'ifconfig ctun0 123.123.123.1 pointopoint 123.123.123.2 up'
  to create a point-to-point IP connection on CAN.

  Example:

  on Host1 run as root:
  isotptun -s 123 -d 321 -v can1 (this blocks, so use a separate terminal)

  ifconfig ctun0 123.123.123.1 pointopoint 123.123.123.2 up

  on Host2 run as root:
  isotptun -s 321 -d 123 -v can2 (this blocks, so use a separate terminal)

  ifconfig ctun0 123.123.123.2 pointopoint 123.123.123.1 up

  Have fun (like in early modem dialup days):
  ping 123.123.123.1
  ssh [email protected]
  scp [email protected]:myfile.tar.gz .

  scp get's about 27kByte/s over a 500kbit/s CAN interface.


3 Remarks
---------

  3.1 tx_queue_len on real CAN busses (!!!)

  The blocksize (BS) splits the CAN frame stream into chunks that need to be
  acknowledged on the receiver side with a flow control frame. In the case
  the blocksize is set to zero the protocol does not wait for flow control
  frames and sends all the CAN frames for the ISO-TP PDU in one burst.

  In the case of a 4095 bytes PDU the protocol driver must create 586(!)
  CAN frames, that are pushed into the CAN network device. This is no problem
  with virtual CAN devices (vcan) but for real CAN devices with real bus
  timings. Even though the frame_txtime (N_As/N_Ar) can be set in the ISO-TP
  socket options, it is recommended to have an appropriate tx queue available
  in the CAN driver, e.g.:

    echo 4000 > /sys/class/net/can0/tx_queue_len

  or with the 'ip' tool from the iproute2 package

    ip link set can0 txqueuelen 4000

  3.2 State of the Socket API for this Linux CAN ISO-TP implementation

  Implementing transport protocol drivers in userspace on top of a CAN_RAW
  socket is possible but has massive drawbacks for fullfilling timing
  constrains and multi-user handling. Implementing a CAN transport protocol
  inside the Kernel brings different requirements, as ...

  - it needs to fit into a standard socket API
  - datagram sockets should always behave similar (e.g. like UDP/IP)
  - reduce user interaction to a minimal absolutely required level
  - reduce user programming interface to a minimal absolutely required level

  In the real world applications using unreliable datagram protocols recognize
  problems via timeouts. So do ISO-TP applications. So the questions is:
  What does it help for the application to know, that someone 'dropped a PDU
  in the receive path due to wrong SequenceNumbers'?

  The application does not know the (so far received) content and therefore
  gets this completely useless information to do *what* with it?

  From current applications perspective the things that have not been
  implemented have not been required so far. So this might become the
  discussion upon this implementation:

  - what is really needed and for what use-case?
  - how does this fit into standard networking and socket philosophy?

Oliver Hartkopp (2017-11-06)

can-isotp's People

Contributors

barsnick avatar cydfrey avatar derek-will avatar gizero avatar hartkopp avatar marckleinebudde avatar pylessard avatar sigttou avatar thomseeen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

can-isotp's Issues

Unrecoverable error when using python socket with CAN_ISOTP.

Hello and thank you for your work on this kernel module. I appreciate being able to make a high quality system with it.

I have an issue that is probably a python issue, but I am hoping you may know something about it. I have a full write up at the following link:
pylessard/python-can-isotp#80

Basic details:
I am using the python-can-isotp library as a helper library to create a connection to the socketcan interface on my raspberry pi CM4 with MCP2515 chip onboard. This kernel module is running on the raspberry pi.

Everything works fine with a short delay between new calls to send, but if I send data too quickly the python socket will eventually enter a condition where it starts exclusively throwing socket.timeout errors on every call to send, never sending another packet again. If I try to close the socket the program locks up. During this error condition I am still able to send frames over that same CAN connection using isotpsend from another terminal window even as the python program repeatedly throws socket.timeout errors.

If I create the socket with the WAIT_TX_DONE flag, then when this error occurs it will lock up my entire python program and I will have to kill the program from another terminal. The timeout is only 100 milliseconds so I don't understand why this would lock up, and if this is a bug or I am simply misusing it.

Since I can use isotpsend from another terminal window during this lockup, this shows me that the actual CAN link is fine. So the problem should be between your kernel module and the python socket. Thus I should probably ask the python-help list for assistance, but I worry that concerns about CAN bus may be too specialized, or that such an email would only get routed to you anyway.

Here is what the system says about the link when my python program is locked up:

acorn@acornv2:~$ ip -details -statistics link show can1
4: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 20000
    link/can  promiscuity 0 minmtu 0 maxmtu 0 
    can state ERROR-ACTIVE restart-ms 0 
	  bitrate 500000 sample-point 0.875 
	  tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
	  mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
	  clock 8000000 
	  re-started bus-errors arbit-lost error-warn error-pass bus-off
	  0          0          0          0          0          0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 
    RX: bytes  packets  errors  dropped missed  mcast   
    1509504    188688   0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    6484689    891876   0       0       0       0   

I would like to find out what is actually happening when it locks up, but I don't know how to debug that. I would also like to know how I can check the socket to confirm it is safe to send without having to hard code a wait, and finally I would like to know how to recover from this condition.

Any and all help is greatly appreciated. If I should take my question to python-help please let me know. Thank you!

missing real examples

hello
because is to hard to find real examples and options is to complicated here is real example from beaglebone black - Linux beaglebone 4.14.49-ti-r54 - with BMW car connected to diagnostic bus talking to ecu 0x40 (CAS) with tester address 0xF1:

echo "22 31 01" | isotpsend -s 6F1 -d 640 -x 640 can1

isotprecv -s 6F1 -d 640 -x 640:6F1 -l can1
62 31 01 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 30 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 04 50 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 04 50 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

isotpdump -s 6F1 -d 640 -x 640 can1
can1 6F1{40} [5] [SF] ln: 3 data: 22 31 01
can1 640{F1} [8] [FF] ln: 234 data: 62 31 01 08 00
can1 6F1{40} [4] [FC] FC: 0 = CTS # BS: 0 = off # STmin: 0x00 = 0 ms
can1 640{F1} [8] [CF] sn: 1 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 2 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 3 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 4 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 5 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 6 data: 00 08 00 00 00 00
can1 640{F1} [8] [CF] sn: 7 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 8 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 9 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: A data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: B data: 00 00 00 00 08 00
can1 640{F1} [8] [CF] sn: C data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: D data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: E data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: F data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 0 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 1 data: 00 03 30 18 00 00
can1 640{F1} [8] [CF] sn: 2 data: 00 50 50 00 00 00
can1 640{F1} [8] [CF] sn: 3 data: E7 70 00 00 20 00
can1 640{F1} [8] [CF] sn: 4 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 5 data: 14 A0 13 A0 00 00
can1 640{F1} [8] [CF] sn: 6 data: 00 00 00 00 04 50
can1 640{F1} [8] [CF] sn: 7 data: 18 00 00 00 50 50
can1 640{F1} [8] [CF] sn: 8 data: 00 00 00 E7 70 00
can1 640{F1} [8] [CF] sn: 9 data: 00 20 00 00 00 00
can1 640{F1} [8] [CF] sn: A data: 00 00 00 14 A0 13
can1 640{F1} [8] [CF] sn: B data: A0 00 00 00 00 00
can1 640{F1} [8] [CF] sn: C data: 00 04 50 18 00 00
can1 640{F1} [8] [CF] sn: D data: 00 50 50 00 00 00
can1 640{F1} [8] [CF] sn: E data: E7 70 00 00 20 00
can1 640{F1} [8] [CF] sn: F data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 0 data: 14 A0 13 A0 00 00
can1 640{F1} [8] [CF] sn: 1 data: 00 00 00 00 08 00
can1 640{F1} [8] [CF] sn: 2 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 3 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 4 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 5 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 6 data: 00 00 00 00 00 00
can1 640{F1} [8] [CF] sn: 7 data: 00 FF FF FF FF FF

isotpsniffer -s 640 -d 6F1 -x 6F1 -X 640 -f 1 can1
can1 6F1 [3] 22 31 01
can1 640 [234] 62 31 01 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 30 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 04 50 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 04 50 18 00 00 00 50 50 00 00 00 E7 70 00 00 20 00 00 00 00 00 00 00 14 A0 13 A0 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

to work isotpsniffer and isotpdump - isotprecv must be running to send FC frames.

sign-file: certs/signing_key.pem: No such file or directory

akast@ubuntu:~/can-isotp$ sudo make modules_install
make -C /lib/modules/4.10.0-19-generic/build M=/home/akast/can-isotp modules_install
make[1]: Entering directory '/usr/src/linux-headers-4.10.0-19-generic'
INSTALL /home/akast/can-isotp/net/can/can-isotp.ko
At main.c:158:

  • SSL error:02001002:system library:fopen:No such file or directory: bss_file.c:175
  • SSL error:2006D080:BIO routines:BIO_new_file:no such file: bss_file.c:178
    sign-file: certs/signing_key.pem: No such file or directory
    DEPMOD 4.10.0-19-generic
    make[1]: Leaving directory '/usr/src/linux-headers-4.10.0-19-generic'

wait_tx_done does not seem to be working [RPi + python-can-isotp]

I am enabling the wait_tx_done flag via python-can-isotp project and if I read back the socket opts it is showing as set:

<OPTS_GENERAL: optflag=0x404, frame_txtime=0x0, ext_address=0x0, txpad=0x0, rxpad=0xcc, rx_ext_address=0x0>

However, when I test sending a large message (>3kB), the send returns almost immediately (within ~2ms).

The kernel I have is: 5.13.0-1016-raspi

Is there a way to know if the can-isotp I have supports the wait_tx_done flag? And, if so, any idea why this might not be working for me?

~5ms delay between consecutive frames

There appears to be a ~5ms delay introduced between consecutive frames when sending a large message, and the ECU has responded with a st_min of 0 (30 00 00).

This seems to be around the check for so->tx_gap (which was so->tx_gap.tv64). iosotp_tx_burst. Have made a quick change to look at the st_min rather than the tx_gap which is working for now. Not a kernel expert so unsure if this would have any side effects.

FlowControl frame address tx_id vs. rx_id - 8?

This is more of a question than an issue. I'm new to ISO-TP, so please forgive my ignorance. Should the ArbID of the FlowControl frame be the tx_id, or should it be the rx_id - 8?

When my scan tool sends OBD-2 messages, it uses a tx_id of 7DF, and listens for responses from 7E8-7EF. However, whenever it needs to send a FlowControl frame, it sends the FC frame with an ArbID that is the ECU response ID minus 8 (e.g. ECU responds on 7E8, FC frame sent with ArbID 7E0). I see the same behavior when looking at the uds.py code for the panda.

If I create an ISOTP socket using this kernel module, I cannot use just a single socket to request the VIN (OBD2 Service 09, PID 02) because my car expects the FC frame to be sent with ArbID = rx_id - 8. I have to create 2 sockets, one to send the request, and one to listen for the response. This doesn't seem to me like normal use, but like I said, I'm new to this, so I'm happy to learn.

Thanks!

fatal error: linux/can/isotp.h: No such file or directory

akast@ubuntu:~/can-isotp/net/can$ make
make -C /lib/modules/4.10.0-19-generic/build M=/home/akast/can-isotp/net/can modules
make[1]: Entering directory '/usr/src/linux-headers-4.10.0-19-generic'
CC [M] /home/akast/can-isotp/net/can/isotp.o
/home/akast/can-isotp/net/can/isotp.c:68:29: fatal error: linux/can/isotp.h: No such file or directory
#include <linux/can/isotp.h>
^
compilation terminated.

FlowControl: isotp vs. "real" OBD2 adapter behavior

I'm running this question through here to solicit feedback before adressing the can-devel mailing list, since I'm not sure whether you would consider this as an issue or not.

I'm working on a custom CANbus adapter based on Linux. This adapter is specialized for UDS (in particular for reprogramming ECUs), but should also work with the usual set of OBD2 commands. In general, everything works great with the isotp module, however I noticed a behavioral difference to a "real" OBD2 adapter:

When talking via CAN broadcast addresses, isotp sends flow control frames to the (functional) broadcast address instead of using the (computed) physical device address.

Here's the beginning of an isotp exchange when querying 0902 with an off-the-shelve OBD2 adapter:

(004.597396)  toucan2  7DF   [8]  02 09 02 00 00 00 00 00   '........'
(000.001399)  toucan2  7E8   [8]  10 14 49 02 01 57 44 58   '..I..WDX'
(000.000408)  toucan2  7E0   [8]  30 00 00 00 00 00 00 00   '0.......'

Here's the same with my linux device and the isotp module:

(016.312861)  toucan2  7DF   [8]  02 09 02 AA AA AA AA AA   '........'
(000.001555)  toucan2  7E8   [8]  10 14 49 02 01 57 44 58   '..I..WDX'
(000.000897)  toucan2  7DF   [8]  30 20 00 AA AA AA AA AA   '0 ......'

Can you spot the difference (not the padding bytes)? Although we are communicating via the CAN 11-bit broadcast address, the OBD2 adapter computes the address of the device that sent the FF. Whereas the isotp module "just" continues using the broadcast address.

I wonder whether we could improve isotp by allowing to set up an additional CAN address that is being used only for the flow control frames.

insmod: ERROR: could not insert module ./net/can/can-isotp.ko: Unknown symbol in module

When I sudo insmod ./net/can/can-isotp.ko ,terminal print “insmod: ERROR: could not insert module ./net/can/can-isotp.ko: Unknown symbol in module”.
The results of "dmesg | tail -n 1" is "can_isotp: Unknown symbol can_rx_register (err -2)".
I want to load this on raspiberry pi 3b+.

The result of "uname -a" is "Linux raspberrypi 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux".
The result of "file net/can/can-isotp.ko" is "net/can/can-isotp.ko: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=f52ef777e54005ea9204e616f0fb5a7335f543a8, not stripped".
What should I do to solve this problem ? thanks.

blocking read() function using ISO-TP driver !

Hello !

I used to make an application that sends a lot of CAN frames (encapsulating UDS requests) with the write() function using the ISO-TP driver through a peak-can device to an ECU that responds with the appropriate CAN frame/frames and i should get those responses each time i send a request using the read() function...the sending/receiving of requests/responses is done inside a while() loop, i extract the requests from a text file which has a structure like:
SID1 DID11 DID21
SID1 DID12 DID22
SID1 DID13 DID23
.....
SID2 DID11 DID21
SID2 DID12 DID22
SID2 DID13 DID23
....
then when getting the responses i write them in an xml file, the problem when i launch the app, it starts correctly and makes the necessary send/receive until it blocks after a while, (it can blocks in any part of the whole number of requests, it can be just in the beginning (after sending/receiving 6to9 requests/responses) , in the middle or just before finishing, there is no particular position), this picture show one of those blocking scenarios :
image

the red lines corresponds to the requests and the blue ones are the responses,

i fetched the code and i found that the read() function is causing the block situation, normally if the ECU didn't response in a certain timeout the read() must not stay waiting and blocking the whole program no ?

i have the an Ubuntu 14.04, i used the isotp module to handle the socketCAN just the way like the isotp utilies (isotpdump, isotprecv, ..)

does the ISO-TP driver handle any sort of timeout when getting stacked in a such situation, knowing that, when i open a terminal in parallel when the app get blocked and send a random request using isotpsend, the app gets out of the blocking situation and continue to send but then it blocks again !

Thank you very much !

warning and ssl error when make modules_install

make -C /lib/modules/5.3.0-28-generic/build M=/home/xyz/candemo/can-isotp modules_install
make[1]: Entering directory '/usr/src/linux-headers-5.3.0-28-generic'
INSTALL /home/xyz/candemo/can-isotp/net/can/can-isotp.ko
At main.c:160:

  • SSL error:02001002:system library:fopen:No such file or directory: ../crypto/bio/bss_file.c:72
  • SSL error:2006D080:BIO routines:BIO_new_file:no such file: ../crypto/bio/bss_file.c:79
    sign-file: certs/signing_key.pem: No such file or directory
    DEPMOD 5.3.0-28-generic
    Warning: modules_install: missing 'System.map' file. Skipping depmod.
    make[1]: Leaving directory '/usr/src/linux-headers-5.3.0-28-generic'

similiar to #15 (comment)
I can receive first frame, I can't receive consecutive frames over isotp. Anyone could help to fix it?

How to fix OSError: [Errno 97] on Jetson TX2?

Hi everyone,
I'm trying to use this library on a Jetson TX2 Board (arm architecture if that matters) inside of an docker container.

If I test the following code from the docs:

import isotp

s = isotp.socket()
s2 = isotp.socket()
# Configuring the sockets.
s.set_fc_opts(stmin=5, bs=10)

s.bind("vcan0", isotp.Address(rxid=0x123 txid=0x456))
s2.bind("vcan0", isotp.Address(rxid=0x456, txid=0x123))
s2.send(b"Hello, this is a long payload sent in small chunks of 8 bytes.")
print(s.recv())

I get the following error message:

root@d1a297bae985:/# python3.7 test.py
Traceback (most recent call last):
File "test.py", line 3, in
s = isotp.socket()
File "/usr/local/lib/python3.7/site-packages/isotp/tpsock/init.py", line 74, in init
self._socket = socket_module.socket(socket_module.AF_CAN, socket_module.SOCK_DGRAM, socket_module.CAN_ISOTP)
File "/usr/local/lib/python3.7/socket.py", line 151, in init
_socket.socket.init(self, family, type, proto, fileno)
OSError: [Errno 97] Address family not supported by protocol

I already searched the internet but didn't find anything helping me in this context. I am not sure why it isn't working (it worked before on a RPI3). Ifconfig shows both interfaces, can0 and can1.

I would really appreciate any help!

Can't open utils' source code refence

Hi,
Just wanted to check utils' source code on the link that you provided in howto, but I wasn't able to make my browser to resolve it.
Does this site still exist and up?

Not able to compile on raspberry pi jessie

I did tried to compile on raspberry pi jessie and observed following error:

make -C /lib/modules/4.9.78-v7+/build M=/home/pi/socCan/can-isotp PROJECT_DIR=/home/pi/socCan/can-isotp modules
make[1]: *** /lib/modules/4.9.78-v7+/build: No such file or directory. Stop.
Makefile:21: recipe for target 'modules' failed
make: *** [modules] Error 2

I did tried to fix this using apt update and upgrade but issue is not getting fixed.

Following is my system configuration
Linux pilinux 4.9.78-v7+ #1084 SMP Thu Jan 25 18:05:49 GMT 2018 armv7l GNU/Linux

Can someone please help me to resolve this issue?

Not able to build for raspberry pi

Hello ,

i am trying to build the ISO TP for the R-PI, But i am getting the error like below when I am executing the command :
sudo apt-get install build-essential linux-headers-$(uname -r)

kindly help me with this I am really new to this.

pi@raspberrypi:~/can-isotp $ sudo apt-get install build-essential linux-headers-$(uname -r)
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package linux-headers-5.10.17-v7l
E: Couldn't find any package by glob 'linux-headers-5.10.17-v7l'
E: Couldn't find any package by regex 'linux-headers-5.10.17-v7l'

Hardware Details :
R-PI 4 .
OS : rasbian deb_buster version

Regards,
Kallappa

SIOCGSTAMP fails with Linux Kernel 5.2.1

Recently, I updated to the kernel 5.2.1-1-MANJARO.

Since then ISOTP socket throw an error. With 5.1.18-1-MANJARO the error does not appear.

Program to reproduce:

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>

#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>

#define CAN_ISOTP 6

int main() {
    int fd = socket(AF_CAN, SOCK_DGRAM, CAN_ISOTP);

    struct timeval tv;
    int res = ioctl(fd, SIOCGSTAMP, &tv);

    printf("error code: %d\nerrorno: %d\n", res, errno);
    perror("ioctl() failed");

    close(fd);
    return 0;
}

Output:

~ $ ./test
error code: -1
errorno: 25
ioctl() failed: Inappropriate ioctl for device

With 5.1.18-1-MANJARO the output is:

~ $ ./test
error code: -1
errorno: 2
ioctl() failed: No such file or directory

Which is fine because no packet has been received.

This commit might be related to this problem:
torvalds/linux@c7cbdbf#diff-35a396ec1d0c44b5f7a45af70ec25268

candump shows traffic, isotpdump shows traffic, isotprecv does not receive frame

What data can I provide for you?

$ candump can0
  can0  7E5   [8]  02 10 03 55 55 55 55 55
  can0  7E5   [8]  02 10 03 55 55 55 55 55
  can0  7E5   [8]  02 10 03 55 55 55 55 55
  can0  7E5   [8]  02 10 03 55 55 55 55 55
$ isotpdump -s 7e5 -d 7ed can0
 can0  7E5  [8]  [SF] ln: 2    data: 10 03 55 55 55 55 55 
$ isotprecv -s 7e5 -d 7ed can0

never returns a frame, no matter how many times I resend it (yet it still shows up in isotpdump + candump while isotprecv is running + waiting)

warning when make modules_install

I followed the instructions to install the module, in which I get a warning and the module isn't installed.

I am on a beagle bone black with kernel 4.19.24-ti-r10

this is what I get after running sudo make modules install


make -C /lib/modules/4.19.24-ti-r10/build M=/home/debian/can-isotp modules_install
make[1]: Entering directory '/usr/src/linux-headers-4.19.24-ti-r10'
  INSTALL /home/debian/can-isotp/net/can/can-isotp.ko
  DEPMOD  4.19.24-ti-r10
Warning: modules_install: missing 'System.map' file. Skipping depmod.
make[1]: Leaving directory '/usr/src/linux-headers-4.19.24-ti-r10'

Doubt: Message Recovery

Hey everyone!

I have a simple can client server, that uses can-isotp to send data, and I want to know if there's any way of finding if the message was fully sent, if there's any packet loss, or any sort of callback that helps me lead with message recovery.

Thanks is advance!
Alfonso

Is there a timeout between Consecutive Frames on isotprecv?

In my current set up I am running a real CAN-bus with three different devices to produce ISO-TP messages and one Ethernet adapter used as a sink for those messages.

  1. A real ECU, that quickly responds to the Flow Control Frame. I can see the full conversation via candump and the assembled message via isotpsniffer and isotprecv (which is used to produce the Consecutive Frame).
  2. A second adapter, USB, to generate messages on my own. Works just as 1. does. All raw CAN frames visible via candump and the assembled PDUs via isotpsniffer and isotprecv.
  3. The curious one. A OBD-Simulator. Once again I can see all messages via candump and isotpsniffer can reassemble them, but isotprecv doesn't! Could this be caused as the OBD simulator responds quite slow? About 2ms for the first CF after the Flow Control Frame but 50ms till the second/last CF after the FCF. Maybe a timeout? It's weird as isotpsniffer seems like it doesn't timeout in this way.
$ isotprecv -s 7E0 -d 7E8 can0 -p 0 -l

$ candump -L can0,7FF:700 
(0000012752.119897) can0 7DF#0209020000000000
(0000012752.121322) can0 7E8#1014490201574458
(0000012752.121678) can0 7E0#3000000000000000
(0000012752.122951) can0 7E8#212D53494D303031
(0000012753.171596) can0 7E8#2239323132333435

$ isotpsniffer -s 7E0 -d 7E8 can0
 can0  7E8  [20]  49 02 01 57 44 58 2D 53 49 4D 30 30 31 39 32 31 32 33 34 35  - 'I..WDX-SIM0019212345'

use read() function and add notify function.

hi,
first, I have a question, what if I use read() and Incoming len parameter more than upcoming cantp message length, weather sure to be able to guarantee read() function recevie the whole cantp message?

then, when develop uds with can-isotp base linux , P2client's definition is shown in the figure below. But when I read can-isotp source code, i cannot find can-isotp support user get this event. This is caused by my ignorance or not implement it. Is it possible to add this if not implemented? Because I don't understand linux kernel development, even if I have ideas(register callback and i can implement it), I don't know how to do it. Similarly, can some cantp error(e.g. SF_DL error handling, FF_DL error handling and so on) be notified to the upper layer.

image
image

Can't insert kernel module because of version issue

Hi,
I am using your library for quite a time and it was working fine until yesterday. I already opened an issue here: pylessard/python-can-isotp#37

I thought that I inserted the kernel module as described in the description the correct way (and I did since it was working fine). Now I faced the mentioned issue and discovered that I get an error inserting the module:

image

After using

dmesg

I can see that there is a problem with my kernel version:

image

I already did the standard procedure

sudo apt-get update & sudo apt-get upgrade

And tried to manually get the correct version from https://packages.ubuntu.com/bionic/linux-image-generic and updated my ubuntu version from 18.04 to 20 but its still not working.

Do you have any suggestions how to solve this?

Edit:
I also tried to remove the false version by hand and install the required kernel header, but its still not possible to insert the kernel module:

image
image

Best regards,

Backward compatibility for Linux 5.4+ versions in bind()

Hi,
I've been flagged an issue with my Python Iso-TP module (pylessard/python-can-isotp#22) regarding a backward compatibility issue. After diving into it, I believe the issue is a conflict between Python and this module.

Apparently, opening an ISOTP socket with Python 3.7.6 and a can-isotp.ko built under Linux 5.4 doesn't work. I believe the problem arise from the addition of J1939 support that modified the size of the sockaddr_can structure (change acknowledges by yourself :) ).

Python create the address object for the user and deduce the length of the address object by using sizeof(*addr). If Python has been compiled with a headers of Linux 5.3, then the this value should be smaller than what one would get with Linux headers of Linux 5.4+.

This line here, checks for conflicts by validating the size of the address object. This verification will prevent the creation of ISO-TP socket if an older Python is used with a freshly compiled kernel module.

Is there a way to be backward compatible with this or should one make sure to keep his Python version aligned with his Kernel version?

Thanks!

#include "compat.h" obsolete?

Searching for compatibility issues I have (probably on my side may come back later if I can't resolve them :D), I found this #include "compat.h" in isotp.c which seems to be something from the old repository but isn't needed anymore?!

no license specified

Hi!
I'm working on including your kernel module into an embedded distribution build framework (OpenEmbedded). I noticed there is no reference to the license this code is available under. I'd expect it to be GPLv2, but having it clearly stated would be much appreciated. If that's the case, could you please add the GPLv2 COPYING file to the repo?

Error while building

I run the make command and this is the answer that I receive is:

make -C /lib/modules/3.16.0-8-amd64/build M=/home/rubio/can-isotp modules
make[1]: Entering directory '/usr/src/linux-headers-3.16.0-8-amd64'
make[1]: Entering directory `/usr/src/linux-headers-3.16.0-8-amd64'
CC [M] /home/rubio/can-isotp/net/can/isotp.o
/home/rubio/can-isotp/net/can/isotp.c: In function ‘isotp_bind’:
/home/rubio/can-isotp/net/can/isotp.c:1141:2: error: too few arguments to function ‘can_rx_register’
can_rx_register(dev, addr->can_addr.tp.rx_id,
^
In file included from /home/rubio/can-isotp/net/can/isotp.c:67:0:
/usr/src/linux-headers-3.16.0-8-common/include/linux/can/core.h:48:5: note: declared here
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
^
/usr/src/linux-headers-3.16.0-8-common/scripts/Makefile.build:262: recipe for target '/home/rubio/can-isotp/net/can/isotp.o' failed
make[5]: *** [/home/rubio/can-isotp/net/can/isotp.o] Error 1
/usr/src/linux-headers-3.16.0-8-common/scripts/Makefile.build:409: recipe for target '/home/rubio/can-isotp/net/can' failed
make[4]: *** [/home/rubio/can-isotp/net/can] Error 2
/usr/src/linux-headers-3.16.0-8-common/Makefile:1362: recipe for target 'module/home/rubio/can-isotp' failed
make[3]: *** [module/home/rubio/can-isotp] Error 2
Makefile:181: recipe for target 'sub-make' failed
make[2]: *** [sub-make] Error 2
Makefile:8: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-3.16.0-8-amd64'
Makefile:21: recipe for target 'modules' failed
make: *** [modules] Error 2

I have tried to upgrade my kernel and also y update can-utils but I still receiving the same error.

difference between python-can-isotp and can-isotp and stmin discrepancy

While going through a solution for stmin discrepancy like it was not consistent with stmin timings , I came across yours and pylessard's python-can-istotp.
please can you highlight implementation and what would be the best solution in order to use flow control for multiframe which is having stmin.

ISSUE: ISO-TP Kernel build on Raspberry-Pi 4B

Hi,

I am trying to build CAN-ISOTP module by refering the link https://github.com/hartkopp/can-isotp and facing problem with installing Kernel headers
Error log for command : sudo apt-get install build-essential linux-headers-$(uname -r)

pi@raspberrypi:~/ISOTP/can-isotp $ sudo apt-get install build-essential linux-headers-$(uname -r)
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package linux-headers-5.4.44-v7l
E: Couldn't find any package by glob 'linux-headers-5.4.44-v7l'
E: Couldn't find any package by regex 'linux-headers-5.4.44-v7l'

kindly suggest how to build for RPI because i am new to these things

Thanks in advance

Requires a way to reset socket state

This issue is a mix of requirements and questions that arise maybe from my limited knowledge of the Linux kernel. I have been facing many times in the past a situation where I open many IsoTP socket and don't close them properly and end up not being able to use a specific socket address.

Basically, I try to create a new socket using the same txid and rxid of the previous unclosed socket and the result is that I cannot changes its parameters (stmin, bs, wftmax) and reception is working interrmitently, (just like if 2 sockets were emptying the same buffer).

I know I created that problem by mishandling the sockets, but when that happens, I have found no other solution than rebooting my mahcine to clean that up. I've tried resetting the networking services, putting down/up the vcan interface, unloading the kernel module. None works.

Is there a way to reset the state of the kernel module?

ERRNO 84 on recv()

Hi, I recently discovered an error during receive. This error was discovered during some tests from Scapy.

Here is a log from python:

>>> load_contrib("isotp")
>>> s = ISOTPNativeSocket("vcan0", did=0x587, sid=0x607)
>>> s.recv()
WARNING: Captured no data. [Errno 84] Invalid or incomplete multibyte or wide character
Traceback (most recent call last):
  File "/home/nils/PycharmProjects/secdev_scapy/scapy/contrib/isotp/isotp_native_socket.py", line 332, in recv_raw
    pkt, _, ts = self._recv_raw(self.ins, x)
  File "/home/nils/PycharmProjects/secdev_scapy/scapy/supersocket.py", line 130, in _recv_raw
    pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len)
OSError: [Errno 84] Invalid or incomplete multibyte or wide character

Anyway, I could track this error down and found a way to reproduce it. Here is a candump file, which triggers this error.
candump_error.log

This error can even be triggered on isotprecv. I've attached a patch to show this error.
isotprecv.patch.txt

This patch produces the following output:

 ./isotprecv -d 587 -s 607 vcan0
received -1, 84

I've sent the malformed CAN messages with canplayer like this:

canplayer -I candump_error.log vcan0=can1 

From my first quick analysis, this bug comes from somewhere underneath the isotp-kernel module.

Canfd support on virtual can?

I want to learn can fd unfortunately I have pi can2 bord which does not support can fd. I am wondering if I can use virtual can for canfd?

Idea/Enhancement: Anonym/discarding bind addresse

Hi once again :)

I got the following Use-Case:

  • 8 ISO-TP sockets bound to the common OBD/UDS diagnostic addresses, TX: 0x7E0 to 0x7E7 and RX: 0x7E8 to 0x7EF.
  • I want to send a functional request using 0x7DF as TX address.

This is problematic as it forces me to open another socket to send those functional requests. That socket needs an RX address for which I have to pick some, hopefully not otherwise used, address/ID, while it actually should never receive something.

Is there/could there be a way to bind to a "I-don't-care" address, have an "only-sending" socket mode or anything along those lines?

How to install kernel module on Jetson TX2 (arm architecture)?

Hi @hartkopp , first of all thanks for the library. I used on my RPI3 where I did not have any problems. Now I switched to a Jetson TX2 and got the known [OSError: [Errno 93] Protocol not supported] issue.

I read about the kernel module https://github.com/hartkopp/can-isotp-modules, but get the following error messages during the procedure:

ccd3@ccd3-desktop:~/can-isotp-modules/net/can$ ./make_isotp.sh

CAN ISO-TP has moved to https://github.com/hartkopp/can-isotp.git
This repository is not maintained anymore.
Are you sure you want to continue the build? (if so press ENTER)

make -C /lib/modules/4.9.140-tegra/build M=/home/ccd3/can-isotp-modules/net/can modules TOPDIR=/home/ccd3/can-isotp-modules/net/can/../..
make[1]: Entering directory '/usr/src/linux-headers-4.9.140-tegra-ubuntu18.04_aarch64/kernel-4.9'
arch/arm64/Makefile:49: LSE atomics not supported by binutils
make[1]: *** No rule to make target 'before'. Stop.
make[1]: Leaving directory '/usr/src/linux-headers-4.9.140-tegra-ubuntu18.04_aarch64/kernel-4.9'
Makefile:12: recipe for target 'modules' failed
make: *** [modules] Error 2

I tried to find somethong about this issue and some information if it may is a NVIDIA TX2 issue but wasn't able to find anything about it.

I would be very happy about every hint, how to install the kernel module in my case. Best regards!

read() does not return after a call to close()

In the main(), I'm opening a can-isotp socket, and I perform write() operation on it. This part is working, the expected CAN frames are sent on the bus.
Now, I'm performing a blocking call to read() on a separated thread. This part is also working, I'm receiving the expected CAN frames.
The issue arises when I'm calling close() on the main() function. I would expect the read() function to return an error (such as EBADF or something similar), but instead of this, it keeps blocking, while the close() function returns 0.
Is it the expected behaviour? If it is the case, what is the proper way to exit from a blocking read()?

missing step from installation instructions

I am on ubuntu 18.04 and can-isotp did not work unless I also ran sudo depmod -a after installing.

You may want to add this step to the installation instructions.

It's possible that this was required as a byproduct of #7 , which I resolved by generating a signing key. I am not sure if the initial install attempts without the signing key created a messed up install that was not completely overwritten by subsequent install attempts with the signing key present (and I don't know how to uninstall, so I can't try again to be sure!).

Either way, I don't think running sudo depmod -a hurts anything, so why not add it to the install instructions?

Issue : Not able to build can-isotp

Hello,

I am able to build the can-isotp the first time but when I restart my system and try to do insmod I am getting errors.
For error, I attached the Screenshot kindly help me in this how should I proceed furtur.
Screenshot (43)

CAN frames lost when stmin > 0

When specifying a value for stmin, some CAN frame seems to be lost. candump shows missing frames. Reading with a CAN_RAW socket shows the same behaviour. Strangely, isotprecv has a complete payload.

I ran :
isotprecv -s 701 -d 700 -m 64 vcan0
then
python3 -c "print(' '.join(['%02x' % x for x in range(100)]))" | isotpsend -s 700 -d 701 vcan0

image

This not only happen with isotpsend and isotprecv. I can reproduce the same behaviour by sending through a socket in Python.

If I set StMin = 0. I get this good behaviour

image

Incorrect include path during kernel build?

I am trying to create a deb package for this module. I can successfully create the package, but I get this compilation error when trying to install it:

gcc -Wp,-MD,/var/lib/dkms/can-isotp/0.1.0/build/net/can/.isotp.o.d -nostdinc -isystem /usr/lib/gcc/x86_64-linux-gnu/4.8/include -I./arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -Iinclude -I./arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -Iubuntu/include -D__KERNEL__ -fno-pie -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -fno-PIE -fno-pie -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -falign-jumps=1 -falign-loops=1 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -maccumulate-outgoing-args -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -mindirect-branch=thunk-extern -mindirect-branch-register -DRETPOLINE -fno-delete-null-pointer-checks -Wno-maybe-uninitialized -O2 --param=allow-store-data-races=0 -DCC_HAVE_ASM_GOTO -Wframe-larger-than=1024 -fstack-protector -Wno-unused-but-set-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-var-tracking-assignments -pg -mfentry -DCC_USING_FENTRY -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -fconserve-stack -Werror=implicit-int -Werror=strict-prototypes -I/include/uapi -DMODULE '-DKBUILD_STR(s)=#s' '-DKBUILD_BASENAME=KBUILD_STR(isotp)' '-DKBUILD_MODNAME=KBUILD_STR(can_isotp)' -c -o /var/lib/dkms/can-isotp/0.1.0/build/net/can/.tmp_isotp.o /var/lib/dkms/can-isotp/0.1.0/build/net/can/isotp.c
/var/lib/dkms/can-isotp/0.1.0/build/net/can/isotp.c:74:29: fatal error: linux/can/isotp.h: No such file or directory
 #include <linux/can/isotp.h>
                             ^
compilation terminated.
make[2]: *** [/var/lib/dkms/can-isotp/0.1.0/build/net/can/isotp.o] Error 1
make[1]: *** [/var/lib/dkms/can-isotp/0.1.0/build/net/can] Error 2
make: *** [_module_/var/lib/dkms/can-isotp/0.1.0/build] Error 2
make: Leaving directory `/usr/src/linux-headers-4.4.0-116-generic'

Based on -I/include/uapi in the gcc command, I believe that the failure is because PROJECT_DIR is unset in net/can/Makefile. Presumably this is because the kernel's Makefile does not propagate PROJECT_DIR during the second-pass invocation of can-isotp's top-level Makefile...?

The package installs correctly if I change net/can/Makefile to use this instead:

ccflags-y += -I$(M)/include/uapi

However, I am unfamiliar with best practices so I'm not sure whether this is the best fix. Suggestions?

Sending rate cannot be faster than 300us

Hi,

I try to send the consecutive frame as fast as possible. (stmin =0 in the receiver)
I am noticing when using this ISTOP stack the best rate I can get is : Sending a consecutive frame each 350us.
But I can get up about 15us when using another ISTOP stack (running on windows)
Wondering what could cause this delay?

System information :
kernel : 5.10.90
CPU usage < 15%
Tx buffer 4000
Bit Rate 500kBit/s

How to preproduce the issue :
Send more few conductive frames using isotpsend where set stmin to 0 in the receiver.

Catching missing Flow Control Frame during data transmission

This issue was opened after an exchange of emails with @hartkopp

Extract of the e-mail sent to @hartkopp

I had a question concerning the behavior when sending a multi-frame packet. When I (client side) send a large chunk of data to the server (ECU), and the server does not send a Flow Control frame back to the client, the write(2) operation does not return any clue about this misbehaving transaction (no error returned, and the number of bytes sent corresponds to the size of the packet).
I wanted to know if there is a way to know when the client enters in such a state.

I digged into the examples but did not found such a use-case.

extract of the reply from @hartkopp

When there's no FC we run into a timeout here:

https://elixir.bootlin.com/linux/v5.11.10/source/net/can/isotp.c#L751

I wanted to know if there is a way to know when the client enters in
such a state.

Good point. Usually you catch these errors by monitoring for a timeout on application(!) level as ISO-TP is an unreliable datagramm protocol anyway (like UDP).

Btw. there is a 'blocking write' feature with the CAN_ISOTP_WAIT_TX_DONE flag. This only returns from the write call when either the transmission is completed OR there has been a problem (e.g. timeout).

In the 'problem' case the sk_error is set.

But looking at the code here ...

https://elixir.bootlin.com/linux/v5.11.10/source/net/can/isotp.c#L955

... it always seems to return the original length value. And I did not test how the sk_error is propagated to the user.

Hm - maybe we can both take a look at this.

Did you try CAN_ISOTP_WAIT_TX_DONE?

Without CAN_ISOTP_WAIT_TX_DONE the errors can not be assigned to a specific PDU.

Get status of transmission?

Hi
I guess this question applies to sockets in general, but I figured I'd ask here anyway.
Is there a way to get a status of the transmission after writing to the socket? The goal would be to know if the last frames has been sent.

The rationale behind this is that UDS protocol has some reply timeout values defined and they appear to be relative to the moment a request has been completely sent. For large request, it can takes seconds to get the whole payload transmitted. If I want to check the timeout correctly, I have to start counting from the end of that delay, not from the moment I write to the socket.

Any idea how this could be handled with your module?

isotp.c: can_rx_register() kernel version guard is incorrect

With Linux 4.4.67, I get this error:

net/can/isotp.c: In function ‘isotp_bind’:
net/can/isotp.c:1120:2: error: too few arguments to function ‘can_rx_register’
  can_rx_register(dev, addr->can_addr.tp.rx_id,
  ^
In file included from net/can/isotp.c:67:0:
include/linux/can/core.h:48:5: note: declared here
 int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
     ^
scripts/Makefile.build:258: recipe for target 'net/can/isotp.o' failed
make[2]: *** [net/can/isotp.o] Error 1

Apparently, the kernel API of can_rx_register() was changed in 4.4.50, not 4.9.11. I commented in downwith's repo here:

downwith/linux-isotp@d3bb87f#commitcomment-23411680

The upstream commit which changed it was this:
torvalds/linux@e6c654c

Too bad both you and downwith chose to copy over the code (that's so 20th century ;-)), instead of doing github-internal forks. With the latter solution, we could have tracked history through all of the development.

unstable transmission of data: sequence number of consecutive frames get messed up

Hello,

I'm using an UDS client that uses the can-isotp Linux kernel module as the transport layer to carry out a firmware update on an ECU.

After requesting a download and receiving a confirmation from the ECU I proceed to transfer blocks of 3074 bytes over CAN-ISOTP to deliver the firmware to the ECU. For this, I call write(int fd, const void *buf, size_t count) with the file descriptor obtained from calling socket(AF_CAN, SOCK_DGRAM | SOCK_NONBLOCK, CAN_ISOTP) and bound to an specified address. This transfer is performed by a development board with a Linux Gateway (to which I'm connected over SSH) to the ECU. I sniff out the whole bus traffic with the PCAN-USB adapter (https://www.peak-system.com/PCAN-USB.199.0.html?&L=1) connected to an Ubuntu VM with the candump command from can-utils.

That's when I observe that after the eleventh consecutive frame (CF) is sent, the next sequence number is not right (0x0 instead of 0xC) and further down it gets even worse; some sequence numbers get sent twice or three times. It also does not transmit all required 3074 bytes. Here the example "candumped" trace (IDs hidden):

(255.316173)  can0  18DAXXF1   [8]  1C 02 36 01 5B 47 65 6E   // start of transfer, (0xC02) is for 3074 bytes
(255.318129)  can0  18DAF1XX   [8]  30 00 00 FF FF FF FF FF   // flow control from ECU
(255.319999)  can0  18DAXXF1   [8]  21 65 72 61 6C 49 6E 66   // sending consecutive frames
(255.319999)  can0  18DAXXF1   [8]  22 6F 5D 0D 0A 54 59 50
(255.322550)  can0  18DAXXF1   [8]  23 45 20 3D 20 30 78 30
(255.324832)  can0  18DAXXF1   [8]  24 30 30 38 0D 0A 42 4F
(255.327750)  can0  18DAXXF1   [8]  25 41 52 44 20 3D 20 22
(255.327750)  can0  18DAXXF1   [8]  26 78 43 55 2D 54 48 48
(255.327751)  can0  18DAXXF1   [8]  27 22 0D 0A 5B 4D 53 57
(255.330786)  can0  18DAXXF1   [8]  28 43 6F 6E 74 65 6E 74
(255.330787)  can0  18DAXXF1   [8]  29 5D 0D 0A 3A 32 30 30
(255.333698)  can0  18DAXXF1   [8]  2A 30 30 30 30 30 37 34
(255.333698)  can0  18DAXXF1   [8]  2B 37 34 35 46 36 36 37  // all sequence numbers were alright until here
(255.335666)  can0  18DAXXF1   [8]  20 30 32 30 30 30 30 36
(255.335667)  can0  18DAXXF1   [8]  26 31 46 41 35 44 33 34
(255.335667)  can0  18DAXXF1   [8]  23 33 41 44 45 44 43 46
(255.337927)  can0  18DAXXF1   [8]  21 39 34 43 39 43 35 34  // sequence number 1 three times
(255.337928)  can0  18DAXXF1   [8]  21 30 41 30 30 30 32 32  
(255.337928)  can0  18DAXXF1   [8]  21 32 33 38 38 36 31 44
(255.340456)  can0  18DAXXF1   [8]  20 32 46 39 43 32 39 43  // sequence number 0 two times 
(255.340456)  can0  18DAXXF1   [8]  20 30 44 33 39 30 41 34
(255.342514)  can0  18DAXXF1   [8]  2F 44 33 37 44 39 41 39
(255.342514)  can0  18DAXXF1   [8]  20 45 42 32 31 45 33 42

I have come to a few ideas why this might not be working like e.g. that there is maybe interference on the CAN bus (physical reason) because I don't want to think that there might be something wrong with this kernel module. After double-checking my code I came to the realization that it all happens after the already mentioned write() call and then the kernel module takes care of the ISOTP part of the transfer.

I would highly appreciate any input as to why this might be happening - hardware or software related. Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.