1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
# vhost-device-can - CAN emulation backend daemon
## Description
This program is a vhost-user backend that emulates a VirtIO CAN device.
The device's binary takes two (2) parameters: a socket, a 'can-devices' list.
The socket is commonly used across all vhost-devices to communicate with
the vhost-user frontend device. The 'can-devices' represents a list of
CAN/FD devices appears in the host system which vhost-device-can will
forward messages to and from the frontend side.
This program is tested with QEMU's `vhost-user-device-pci` device.
Examples' section below.
## Synopsis
```
**vhost-device-can** [*OPTIONS*]
````
## Options
.. program:: vhost-device-can
.. option:: -h, --help
Print help.
.. option:: -s, --socket-path=PATH
Location of vhost-user Unix domain sockets, this path will be suffixed with
0,1,2..socket_count-1.
.. option:: -c, --socket-count=INT
Number of guests (sockets) to attach to, default set to 1.
.. option:: -d, --can-devices='CAN/FD interfaces'
CAN/FD device list at the host OS in the format:
<can-_X_0> [<can_in_X_1>] ... [<can_in_X_N-1>]
Note 1: Where N (the number of CAN/FD interfaces) is equal with the number
provided via *socket_count* parameter.
Example: --can-devices "can0 can1 can2"
## Features
This device is still work-in-progress (WIP) and on [virtio-spec v1.4](https://github.com/oasis-tcs/virtio-spec/blob/virtio-1.4/device-types/can/) is based
on virtio-can Linux's driver and QEMU's device presented in the following RFC:
- https://lwn.net/Articles/934187/
Vhost-device-can have be been tested in scenarios with multiple QEMU's VMs using
host's *CAN/FD* devices.
## Limitations
1) The transmission of a CAN/FD frame to a host interface always is done
synchronously. This means that regardless the negotiation or not of the
feature *VIRTIO_CAN_F_LATE_TX_ACK*, the backend will always wait for the
transmission of the frame and after will mark the transmission request
as used.
2) Does not check for undefined flags in CAN/FD frame when send and receive
a CAN/FD frame from the frontend (QEMU device).
3) The host's CAN/FD devices should be already in *UP* state before staring
the vhost-device-can (by using `ip link set can0 [up,down]`).
- The control messages does not actually change host's device state
4) Current version of the device has been tested only with *vcan* device.
## Examples
### Dependencies
For testing the device the required dependencies are:
- Linux:
- Integrate *virtio-can* driver implemented by OpenSynergy:
- https://lwn.net/Articles/934187/
- Set `CONFIG_VIRTIO_CAN=y`
- QEMU
- Integrate *virtio-can* device implemented by OpenSynergy:
- https://lwn.net/Articles/934187/
- Clone vhost-user-can QEMU device (optional):
- A new vhost-user-can device has been implemented in the following repo:
- https://github.com/virtualopensystems/qemu/tree/vhu-can-rfc
### Test the device
The daemon should be started first:
```shell
host# vhost-device-can --socket-path=can.sock --can-devices="vcan0"
```
The QEMU invocation needs to create a chardev socket the device can
use to communicate as well as share the guests memory over a memfd.
There are two option for running QEMU with vhost-device-can:
1) Using `vhost-user-device-pci` available upstream since QEMU `v8.2.0`:
```text
host# qemu-system \
-m 4096 \
-numa node,memdev=mem \
-object memory-backend-memfd,id=mem,size=4G,share=on \
-chardev socket,id=can0,path=/tmp/can.sock \
-device vhost-user-device-pci,chardev=can0,virtio-id=36,num_vqs=3,config_size=16 \
...
```
2) Using `vhost-user-can-pci`:
```text
host# qemu-system \
-m 4096 \
-numa node,memdev=mem \
-object memory-backend-memfd,id=mem,size=4G,share=on \
-chardev socket,path=/tmp/can.sock,id=can0 \
-device vhost-user-can-pci,chardev=can0,id=can \
...
```
> Note: For testing this scenario the reader needs to clone the QEMU version
> from the following repo which implements `vhost-user-can` device:
> - https://github.com/virtualopensystems/qemu/tree/vhu-can-rfc
### Multi-Guest case
Run vhost-device-can as:
```text
./vhost-device-can --socket-path /tmp/can.sock --socket-count 2 --can-devices "vcan0 vcan1"
```
This command will start the device and create two new sockets: */tmp/can.sock0* and */tmp/can.sock1*.
From the other side we run two QEMU instances (VMs) with vhost-user-can:
```text
host# qemu-system \
-m 4096 \
-numa node,memdev=mem \
-object memory-backend-memfd,id=mem,size=4G,share=on \
-chardev socket,path=<SOCKET_PATH>,id=can0 \
-device vhost-user-can-pci,chardev=can0,id=can \
...
```
In the first instance of QEMU *SOCKET_PATH* would be: */tmp/can.sock0*,
and will use *can0* (host interface) as sender and receiver. The second
QEMU VM would have: *SOCKET_PATH* = */tmp/can.sock1*, and will use *can1*
as receiver and *can2* as sender.
## License
This project is licensed under either of
- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0
- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
|