Virtual CAN on Linux
Virtual CAN (vcan) allows you to create software-only CAN buses for testing and development without physical hardware.
Setting Up Virtual CAN
Prerequisites
Ensure the vcan kernel module is loaded:
Creating a Virtual Interface
Create a virtual CAN interface named vcan0:
Verifying the Setup
Check that the interface was created:
You should see output similar to:
Using Virtual CAN with Sockcan
Standalone Mode
Create a virtual CAN network with multiple applications:
# app1.py - Receiver
from sockcan import SocketcanConfig, connect_to_socketcan, build_recv_func
config = SocketcanConfig(channel="vcan0")
sock = connect_to_socketcan(config)
recv = build_recv_func(sock)
print("Waiting for messages on vcan0...")
msg = recv()
print(f"Received: ID={msg.arbitration_id:#x}, Data={msg.data.hex()}")
# app2.py - Sender
from sockcan import SocketcanConfig, connect_to_socketcan, build_send_func
config = SocketcanConfig(channel="vcan0")
sock = connect_to_socketcan(config)
send = build_send_func(sock, expects_msg_cls=False)
send(0x123, b'\xde\xad\xbe\xef', False)
print("Message sent!")
Run both applications in separate terminals - messages will be transmitted between them.
python-can Interoperability Layer
Use virtual CAN with python-can's interface:
import can
from sockcan.interop import hijack_python_can
hijack_python_can()
bus = can.Bus(interface="socketcan", channel="vcan0")
# Send a message
msg = can.Message(
arbitration_id=0x456,
data=[1, 2, 3, 4],
is_extended_id=False,
)
bus.send(msg)
# Receive a message
received = bus.recv(timeout=1.0)
print(f"Received: {received}")
Using Real CAN Hardware
When you have real CAN hardware connected (e.g., on interface can0), simply change the channel name:
Standalone Mode
from sockcan import SocketcanConfig, connect_to_socketcan, build_send_func
config = SocketcanConfig(channel="can0") # Use real interface
sock = connect_to_socketcan(config)
send = build_send_func(sock, expects_msg_cls=False)
send(0x100, b'\x01\x02\x03\x04', False)
print("Message sent to real CAN bus!")
python-can Interoperability Layer
import can
from sockcan.interop import hijack_python_can
hijack_python_can()
bus = can.Bus(interface="socketcan", channel="can0")
msg = can.Message(arbitration_id=0x789, data=[0x11, 0x22, 0x33])
bus.send(msg)
Multiple Virtual CAN Interfaces
Create multiple virtual interfaces for complex testing scenarios:
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0
sudo ip link add dev vcan1 type vcan
sudo ip link set up vcan1
Isolated Testing
Applications on different vcan interfaces are isolated from each other:
# app_on_vcan0.py
config = SocketcanConfig(channel="vcan0")
sock = connect_to_socketcan(config)
# app_on_vcan1.py
config = SocketcanConfig(channel="vcan1")
sock = connect_to_socketcan(config)
Bridging Virtual and Physical CAN
Use can-utils cangw or the SocketcanServer to bridge virtual and physical CAN:
from sockcan.daemon import SocketcanServer, BusParameters
from sockcan import build_send_func, build_recv_func
# Bridge vcan0 to real CAN hardware on can0
with SocketcanServer.factory(
BusParameters(channel="can0", interface="socketcan")
) as server:
vcan_sock = server.subscribe()
recv = build_recv_func(vcan_sock)
send = build_send_func(vcan_sock, expects_msg_cls=False)
# Messages from can0 appear on vcan_sock
msg = recv()
Cleanup
Remove a virtual CAN interface when no longer needed:
Or remove all vcan interfaces:
Troubleshooting
Interface Not Found
Solution: Create the virtual interface first:
Permission Denied
Solution: Run with sudo or add your user to the can group:
Messages Not Received
Possible causes:
1. Interface not in UP state
2. Loopback mode is OFF
3. Different channel names
Solution: Verify interface state: