4

Is it possible to send a "one-shot" CAN message using SocketCAN? This is basically a message that does not expect an acknowledgement back from the receiver. The protocol allows this ACK bit not to be set.

ilya1725
  • 4,496
  • 7
  • 43
  • 68

2 Answers2

2

I'm not sure what you mean by "one-shot", but I send single CAN frames all the time using the cansend utility from can-utils, like this:

$ cansend can0 135#02080426A10D112A

I've also written C programs that do the same using an AF_CAN socket. (You can basically crib from cansend.c to figure out how.)

Regarding retransmission of messages, this doesn't happen with cansend:

$ timeout 20s tcpdump -i can0 -w out.pcap &                                                                                                                                               
[1] 16509
tcpdump: listening on can0, link-type CAN_SOCKETCAN (CAN-bus with SocketCAN headers), capture size 262144 bytes

$ cansend can0 135#02080426A10D112A

$ 1 packet captured
0 packets received by filter
0 packets dropped by kernel

[1]  + 16509 exit 124   timeout 20s tcpdump -i can0 -w out.pcap

In the sequence above, there are no consumers online, so nobody ACKs the message, but I still only capture a single packet on can0. It seems safe to conclude that the SocketCAN stack isn't 'automagically' trying to re-send the message in the background after cansend exits.

evadeflow
  • 4,704
  • 38
  • 51
  • 1
    If you don't have a receiver to read the message and send ACK back, the sender would keep retrying. I just want to send a message and if there is no one there to read it it would be lost but the sender would move on. – ilya1725 Oct 18 '17 at 21:04
  • I updated my answer to note that `cansend` does not attempt to retransmit messages. I've worked quite a bit with CAN, but I'm by no means an expert, so... perhaps I've misunderstood your problem. Can you not shell out to `cansend` (using, e.g., `system()`) to achieve your stated goal? – evadeflow Oct 19 '17 at 22:13
  • 1
    No, cansend will not retransmit. That is entirely handled by the CAN controller. What I suppose @ilya1725 is after is the one-shot mode that most CAN controllers are capable of using. E.g. from MCP2515: `One-Shot mode ensures that a message will only attempt to transmit one time. Normally, if a CAN message loses arbitration, or is destroyed by an error frame, the message is retransmitted. With One-Shot mode enabled, a message will only attempt to transmit one time, regardless of arbitration loss or error frame.` – matli Sep 28 '18 at 11:25
  • CAN frames that had already reached the peripheral's internal buffer are not captured by Wireshark. I suggest to listen with another device on the bus. – Fusho Sep 28 '18 at 12:16
0

The CAN frame will be retransmitted again and again until a bus error is detected (bus off). This is done by the CAN peripheral (it is part of the spec, search for "retransmission"), SocketCan does not know anything about that.

SocketCan allows you to subscribe to different error notifications on the bus/controller. In general, CAN peripherals/drivers implement the signaling of a subset of these errors only. If you are lucky, you could be able to subscribe (see 4.1.2) for notifications and react accordingly.

Fusho
  • 1,469
  • 1
  • 10
  • 22
  • 1
    Most CAN controllers support a one-shot mode that skips the retransmission. I can see no reason for SocketCan to not be able to support this. In fact, the `ip link set can0 type can help` lists "one-shot" as an available option. However, at least on my hardware this gives me an `Operation not supported` response. – matli Sep 28 '18 at 11:30
  • 1
    `Operation not supported` probably menas "your driver and/or hw does not have that option". Anyway, I think you are right and the OP was asking about "one-shot" at the peripheral level, just seems to be confusing comparing OP question against accepted answer. Also, I was not aware of the `one-shot` option in `ip`, thx! – Fusho Sep 28 '18 at 12:13
  • Thanks @oxuf, I expected this behavior, but couldn't find proof anywhere else. – phylib Jun 03 '19 at 20:00