write: no buffer space available socket-can/linux-can - beagleboneblack

I'm running a program with two CAN channels (using TowerTech CAN Cape TT3201).
The two channels are can0 (500k) and can1 (125k). The can0 channels works perfectly but can1 runs a write:No buffer space available error.
I'm using ValueCAN3/VehicleSpy to check the messages.
This is before I run the program. can0 and can1 both seem to send, but only can0 shows up in VehicleSpy.
root#cantool:~# cansend can0 100#00
root#cantool:~# cansend can1 100#20
This is after I try running the program
root#cantool:~# cansend can1 100#20
write: No buffer space available
root#cantool:~# cansend can0 111#10
While my program is running : I get this error for all messages to be sent on can1
2016-11-02 15:36:03,052 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 12f83018 010 1 00
2016-11-02 15:36:03,131 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 0af81118 010 6 00 00 00 00 00 00
2016-11-02 15:36:03,148 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 12f81018 010 6 00 00 00 00 00 00
2016-11-02 15:36:03,174 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 0af87018 010 3 00 00 00
2016-11-02 15:36:03,220 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 12f89018 010 4 00 00 00 00
2016-11-02 15:36:03,352 - can.socketcan.native.tx - WARNING - Failed to send: 0.000000 12f83018 010 1 00
However sometimes the whole program works perfectly (if the module is rebooted or some random instances).
How do I fix this?
root#cantool:~# uname -r
4.1.15-ti-rt-r43
after doing some digging, I found this
root#cantool:-#ip -details link show can0
4:can0: <NOARP,UP,LOWER_UP, ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100
bitrate 500000 sample-point 0.875
tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
c_can: tseg1 2..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp-inc 1
clock 24000000
root#cantool:-#ip -details link show can1
5: can1: <NOARP,UP,LOWER_UP, ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state STOPPED restart-ms 100
bitrate 125000 sample-point 0.875
tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
c_can: tseg1 2..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
clock 8000000
Turns out that can1 is STOPPED for some reason
however when I try:
ip link set can1 type can restart
RNETLINK answers: Invalid argument

After you enable the can0 interface with sudo ifconfig can0 up, run:
sudo ifconfig can0 txqueuelen 1000
This will increase the number of frames allowed per kernel transmission queue for the queuing discipline. More info here
... sometimes the whole program works perfectly (if the module is rebooted or some random instances).
The reason why it works when you restart the SocketCAN interface, is that you might clear up just enough buffer space to make it work.

Related

Why CAN FD communication not working with two nodes

I'm trying to communicate with an actuator device via CAN FD connection, with the help of a Raspberry 4b and a Waveshare CAN hat.
While they are separated, using a tester I read the correct frames on both devices.
But when the Raspberry and the actuator are connected, I receive frames with unexpected ID, data and size on the Raspberry.
The code:
import time
import os
import can
import cantools
def startBus():
os.system('sudo ip link set can0 up type can bitrate 500000 dbitrate 5000000 restart-ms 1000 berr-reporting on fd on')
time.sleep(0.1)
global can0
can0 = can.interface.Bus(bustype='socketcan', channel='can0', bitrate=500000, dbitrate=5000000 receive_own_messages=False, local_loopback=True,
fd=True, can_filters=None, ignore_rx_error_frames=False)
def shutDownBus():
os.system('sudo ifconfig can0 down')
print('shut down')
def periodicSend():
print('sendPeriodic')
messageID1 = 0xC0FFEE
data1 = [0, 1, 2, 3, 4, 5, 6, 7]
msg1 = can.Message(arbitration_id=messageID1,
is_fd=True,
data=data1,
is_extended_id=False)
messageID2 = 0xC0FFFF
data2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
msg2 = can.Message(arbitration_id=messageID2,
is_fd=True,
data=data2,
is_extended_id=False)
task1 = can0.send_periodic(msg1, 0.01)
if not isinstance(task1, can.ModifiableCyclicTaskABC):
task1.stop()
return
task2 = can0.send_periodic(msg2, 0.01)
if not isinstance(task2, can.ModifiableCyclicTaskABC):
task2.stop()
return
def listen():
print("listening")
for message in can0:
print(message)
# Calling the functions:
shutDownBus()
time.sleep(1)
startBus()
periodicSend()
listen()
x = False
while not x: time.sleep(0.1)
The contents of the received frames:
Timestamp: 1667826218.955793 ID: 0088 S Rx E DL: 8 00 00 94 00 00 00 00 00 Channel: can0
Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 90 00 00 00 00 00 Channel: can0
Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 04 00 00 00 00 00 Channel: can0
Timestamp: 1667826218.955... ID: 0088 S Rx E DL: 8 00 00 02 00 00 00 00 00 Channel: can0
And so on, the third byte keeps changing.
These are different from what I am expecting and what I am seeing on the tester (the tester shows the correct frames).
I tried to change the bitrates (500k and 5000k), though I'm rather sure these are correct.
It does not look like a hardware issue, as when separated, both are sending the expected frames.
Setting the ignore_rx_error_frames to False makes the messages disappear, but obviously it is not the solution.
Changing the local_loopback has no visible effect.
Some seemingly similar issues were related to the ACK bit (Sending messages with different ID on a pcan can bus, using python can), but 1) I don't see where and how I could manipulate this and 2) already the very first frame on the bus is not what I am expecting.
Any ideas would be greatly appreciated.
The solution was to adjust the sample-point and the dsample-point parameters when setting up the CAN interface:
sudo ip link set can1 up type can bitrate 500000 dbitrate 5000000 restart-ms 1000 berr-reporting on fd on sample-point .8 dsample-point .8
Apparently CAN FD is more sensitive to these parameters.

SocketCAN error-passive with RevPi CAN Connect. Hardware or Software issue?

We have bought a CAN Connect module for our Revpi Connect, and set it up as can been seen in this thread on the Kunbus forum. As far as we understand this will provide the proper termination.
We have also followed this guide provided by Revolution PI.
When checking that the drivers for the CAN module is properly loaded, everything looks fine:
$ dmesg | grep can
[ 4.616900] hi3110 spi0.0 can0: 3110 successfully initialized.
[ 107.049422] IPv6: ADDRCONF(NETDEV_UP): can0: link is not ready
[ 107.049463] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
Checking ip statistics gives this result:
$ ip -det -statistics link show can0
5: can0: mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can promiscuity 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 50000 sample-point 0.875
tq 1250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
hi3110: tseg1 2..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
clock 16000000
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 overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
However, when we turn on candump and send a message using cansend, candump does not show any traffic.
If we check dmesg for CAN again, we get this result:
$ dmesg | grep can
[ 4.616900] hi3110 spi0.0 can0: 3110 successfully initialized.
[ 107.049422] IPv6: ADDRCONF(NETDEV_UP): can0: link is not ready
[ 107.049463] IPv6: ADDRCONF(NETDEV_CHANGE): can0: link becomes ready
[ 292.285353] can: controller area network core (rev 20170425 abi 9)
[ 292.297811] can: raw protocol (rev 20170425)
And if we check ip -statistics again, we can see that the state of the connection has gone into ERROR-PASSIVE:
$ ip -det -statistics link show can0
5: can0: mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
link/can promiscuity 0
can state ERROR-PASSIVE (berr-counter tx 128 rx 0) restart-ms 0
bitrate 50000 sample-point 0.875
tq 1250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
hi3110: tseg1 2..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
clock 16000000
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 1 1 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
We are trying to communicate with a computer with and Ixxat USB2CAN v2, at 50kbps, with both highspeed and FT settings, but nothing seems to work. Resetting the connection, seems to put it back into ERROR-ACTIVE state.
When trying to communicate with mentioned computer, using another computer with Socketcan and another Ixxat USB2CAN v2 device, everything works fine.
I should perhaps also mention that if we turn loopback on, we can see the messages we are sending.
We are struggling to understand whether this a hardware or software error. Is our termination in order? Are there any magical settings in SocketCAN we have overlooked? Where should we start debugging this issue?
Any help would be greatly appreciated.
As it turns out, the schematic printed directly on the device is wrong.The schematic on their website is correct.
Hopefully this can help someone else avoid pulling their hair out in the future.

Why is there something written in the data section of an ICMPv4 echo ping request?

(My question differs from this one.)I am connected to a AP in a wireless network and I've send a simple ping request to www.google.com. When I analyze the packet in wireshark, I can see, that there are 48 bytes written in the data section of ICMP. After 8 bytes of trash values, the values are sequentially increasing from 0x10 to 0x37.Is there any particular reason, why ICMPv4 fits values instead of just using a bunch of zeroes?
The hexdump of the ICMPv4 data section:
0030 09 d9 0d 00 00 00 00 00 10 11 12 13 14 15 .Ù............
0040 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 .......... !"#$%
0050 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 &'()*+,-./012345
0060 36 37 67
After 8 bytes of trash values
First of all, these are not trash values. In some implementations of ping, the 1st 8 bytes may represent a timestamp.
As #ross-jacobs mentioned, RFC 792 describes the ICMP Echo Request/Reply Packets. For clarity, these two packets are described, in relevant part, as follows:
Echo or Echo Reply Message
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ...
+-+-+-+-+-
...
Description
The data received in the echo message must be returned in the echo
reply message.
Here you can see that the contents of the Data is not described at all; therefore an implementation is free to use whatever data it wishes, including none at all.
Now, since ping is a network test tool, one of the things it can help test is fragmentation/reassembly. Every ping implementation I'm aware of allows the user to specify the size of the payload, and if you exceed the MTU, you should see the ICMP packet fragmented/reassembled. If you examine the payload of the first fragment, you can tell where the second fragment should start just by looking at the sequence of bytes in the payload of the first fragment. If the data was all 0's, it wouldn't be possible to do this. Similarly, if an ICMP packet wasn't reassembled properly, not only would the checksum likely be wrong, but you would most likely be able to tell exactly where the reassembly failed due to a gap or other inconsistency in the payload. This is just one example of why a payload with a sequence of bytes instead of all 0's is more useful to the user.

Flow control message while receiving CAN message with ELM327

I am trying to make a software, which runs under Windows and communicates with an ELM327 device. I created the first version and I went in my SMART ForTwo (SMART 451) vehicle and I managed to connect with the Instrument Cluster (Transmit CAN ID is 782, Receive CAN ID is 783). However I have a huge problem with Flow Control. Here is the log:
TX: ATI
RX: ELM327 v1.5a
TX: ATE0
RX: ATE0 OK
TX: ATSP6
RX: OK
TX: ATH1
RX: OK
TX: ATL1
RX: OK
TX: ATCFC1
RX: OK
TX: ATFCSM0
RX: OK
TX: ATAL
RX: OK
TX: ATSH782
RX: OK
TX: ATCRA783
RX: ?
TX: ATST64
RX: OK
TX: 1092
RX: 783 02 1A 87
TX: 1A87
RX: 783 10 16 5A 87 05 6E 00 08
I used another tool and I saw that the ELM327 device sends the Flow Control Frame, immediately. It is like this:
891.438 782 02 1A 87
891.444 783 10 16 5A 87 05 6E 00 08
891.444 782 30 00 00 00 00 00 00 00
As you can see - Flow Control frame is sent at exactly the same time as the First Frame, that is sent from the other device. I am sure that the other device has a problem to receive the "Flow Control" frame.
I studied the ELM327 documentation, but did not find any info about how to delay the Flow Control frame.
How should I correctly send the request "1A 87" and receive the response?
It's an old post but might help others!
This is my Experience with First Frame (FF) and Flow Control (FC) on MCP2515 connected with SPI.
First of all you should always send the FC message after the FF message and not in the same time.
Secondly the diagnostic reader can use the ID in the ECU response frame to continue communication with a specific ECU. In particular, multi-frame communication requires a response to the specific ECU ID rather than to ID 7DF. In the easy language you should not send your FF message with ID 7DF and you should address the exact ECU that you want to receive the consecutive frames. For instance requesting car VIN (based on real information from Golf VII):
7DF 02 09 00 00 00 00 00 00 //sending request
7E8 10 14 49 02 01 57 56 57 //receving from main ECU
7E0 30 00 00 00 00 00 00 00 //adressing the main ECU and not 7DF anymore !!
7E8 21 5A 5A 5A 41 55 5A 45 //consecutive messages are sending by 7E0!!
7E8 22 50 35 33 30 36 38 35
Hopefully it helps!
It's very easy, I guess..
Use the ATCFC0 command, and then you can process all the response frames from the control unit, and you need to manually send the flow control frame.

How to calculate Internet checksum?

I have a question regarding how the Internet checksum is calculated. I couldn't find any good explanation from the book, so I ask it here.
Have a look at the following example.
The following two messages are sent: 10101001 and 00111001. The checksum is calculated with 1's complement. So far I understand. But how is the sum calculated? At first I thought it maybe is XOR, but it seems not to be the case.
10101001
00111001
--------
Sum 11100010
Checksum: 00011101
And then when they calculate if the message arrived OK. And once again how is the sum calculated?
10101001
00111001
00011101
--------
Sum 11111111
Complement 00000000 means that the pattern is O.K.
It uses addition, hence the name "sum". 10101001 + 00111001 = 11100010.
For example:
+------------+-----+----+----+----+---+---+---+---+--------+
| bin value | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | result |
+------------+-----+----+----+----+---+---+---+---+--------+
| value 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 169 |
| value 2 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 57 |
| sum/result | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 0 | 226 |
+------------+-----+----+----+----+---+---+---+---+--------+
If by internet checksum you mean TCP Checksum there's a good explanation here and even some code.
When you're calculating the checksum remember that it's not just a function of the data but also of the "pseudo header" which puts the source IP, dest IP, protocol, and length of the TCP packet into the data to be checksummed. This ties the TCP meta data to some data in the IP header.
TCP/IP Illustrated Vol 1 is a good reference for this and explains it all in detail.
The calculation of the internet checksum uses ones complement arithmetic. Consider the data being checksummed is a sequence of 8 bit integers. First you need to add them using ones complement arithmetic and take the ones complement of the result.
NOTE: When adding numbers ones complement arithmetic, a carryover from the MSB needs to be added to the result. Consider for eg., the addition of 3(0011) and 5(0101).
3'->1100
5'->1010
0110 with a carry of 1
Thus we have, 0111(1's complement representation of -8).
The checksum is the 1's complement of the result obtained int he previous step. Hence we have 1000. If no carry exists, we just complement the result obtained in the summing stage.
The UDP checksum is created on the sending side by summing all the 16-bit words in the segment, with any overflow being wrapped around and then the 1's complement is performed and the result is added to the checksum field inside the segment.
at the receiver side, all words inside the packet are added and the checksum is added upon them if the result is 1111 1111 1111 1111 then the segment is valid else the segment has an error.
exmaple:
0110 0110 0110 0000
0101 0101 0101 0101
1000 1111 0000 1100
--------------------
1 0100 1010 1100 0001 //there is an overflow so we wrap it up, means add it to the sum
the sum = 0100 1010 1100 0010
now let's take the 1's complement
checksum = 1011 0101 0011 1101
at the receiver the sum is calculated and then added to the checksum
0100 1010 1100 0010
1011 0101 0011 1101
----------------------
1111 1111 1111 1111 //clearly this should be the answer, if it isn't then there is an error
references:Computer networking a top-down approach[Ross-kurose]
Here's a complete example with a real header of an IPv4 packet.
In the following example, I use bc, printf and here strings to calculate the header checksum and verify it. Consequently, it should be easy to reproduce the results on Linux by copy-pasting the commands.
These are the twenty bytes of our example packet header:
45 00 00 34 5F 7C 40 00 40 06 [00 00] C0 A8 B2 14 C6 FC CE 19
The sender hasn't calculated the checksum yet. The two bytes in square brackets is where the checksum will go. The checksum's value is initially set to zero.
We can mentally split up this header as a sequence of ten 16-bit values: 0x4500, 0x0034, 0x5F7C, etc.
Let's see how the sender of the packet calculates the header checksum:
Add all 16-bit values to get 0x42C87: bc <<< 'obase=16;ibase=16;4500 + 0034 + 5F7C + 4000 + 4006 + 0000 + C0A8 + B214 + C6FC + CE19'
The leading digit 4 is the carry count, we add this to the rest of the number to get 0x2C8B: bc <<< 'obase=16;ibase=16;2C87 + 4'
Invert¹ 0x2C8B to get the checksum: 0xD374
Finally, insert the checksum into the header:
45 00 00 34 5F 7C 40 00 40 06 [D3 74] C0 A8 B2 14 C6 FC CE 19
Now the header is ready to be sent.
The recipient of the IPv4 packet then creates the checksum of the received header in the same way:
Add all 16-bit values to get 0x4FFFB: bc <<< 'obase=16;ibase=16;4500 + 0034 + 5F7C + 4000 + 4006 + D374 + C0A8 + B214 + C6FC + CE19'
Again, there's a carry count so we add that to the rest to get 0xFFFF: bc <<< 'obase=16;ibase=16;FFFB + 4'
If the checksum is 0xFFFF, as in our case, the IPv4 header is intact.
See the Wikipedia entry for more information.
¹Inverting the hexadecimal number means converting it to binary, flipping the bits, and converting it to hexadecimal again. You can do this online or with Bash: hex_nr=0x2C8B; hex_len=$(( ${#hex_nr} - 2 )); inverted=$(printf '%X' "$(( ~ hex_nr ))"); trunc_inverted=${inverted: -hex_len}; echo $trunc_inverted

Resources