OSError 92: Protocol not available inside `SocketcanBus.__init__`
Describe the bug
The bug occurs directly on instantiation of a SocketcanBus on a virtual channel. Every socket.setsockop() operation fails, even the SO_TIMESTAMPNS option.
However, using linux can-utils, can messages can be send and received on the interface. Both regular CAN and CAN-FD messages.
To Reproduce
This is kept simple, more context is shared under additiinal context.
- Start a Podman pod inside a Fedora CoreOS system with
vcankernel modules active. - Create the
vcaninterface inside theinitContainerof the Pod. A sampleContainerfileis included. - Add a Python container to the Pod.
- Try initialising the
SocketcanBusinside the python container.
Expected behavior
The SocketcanBus is initialised correctly and can be used without issues.
Additional context
OS and version: Host is macOS 13.2.1, Podman machine is running Fedora CoreOS 37.20230303.2.0
Python version: 3.11.2
python-can version: 4.1.0
python-can interface/s (if applicable): SocketcanBus
Detailed explanation of the setup
The error occurs inside of a container based on amd64/python:3.11.2-bullseye. The container itself runs inside a Kubernetes Pod managed by Podman. Since I'm developing on a mac, podman machine must be used. My podman machine is running an Fedora Core OS on aarch64 via qemu, so macOS should not play any role here. The Fedora CoreOS has the modules can, can_raw and vcan activated. The actual vcan0 network interface is generated by the initContainer of the Pod, thus creating it directly inside the network namespace of the Pod. The vcan0 interface cannot be accessed outside the Pod, neither by the host, nor by the Podman machine. Inside the Pod, every container has access to the network interface. This was also validated by having two separate containers with one always sending messages (via cangen or cansend) and one listening on the interface (via candump) with the linux can-utils package. A command to add a container with can-utils installed is provided below.
Traceback and logs
Minimal working podfile
apiVersion: v1
kind: Pod
metadata:
name: can-error
spec:
initContainers:
- name: can-setup
image: docker.io/alpine:latest
command:
- sh
- -c
- |
set -x
apk add linux-headers
ip link add dev vcan0 type vcan
ip link set up vcan0
securityContext:
capabilities:
add:
- NET_ADMIN
containers:
- name: keep-up
image: alpine
command:
- sh
- -c
- |
sleep 1000000
This file can be started with podman play kube file_name.yml.
A container with can-utils can be started via podman run -it --entrypoint /bin/bash --pod can-error docker.io/marcosnils/can-utils:latest. If two containers are created, they can send and receive messages via cangen vcan0 and candump vcan0 respectively.
The python container in a similar fashion: podman run -it --entrypoint /bin/bash --pod can-error docker.io/amd64/python:3.11.2-bullseye
Python code producing the error
from can.interfaces.socketcan.socketcan import SocketcanBus
bus = SocketcanBus(channel="vcan0")
Error log
Could not set local loopback flag([Errno 92] Protocol not available)
Could not receive own messages ([Errno 92] Protocol not available)
Could not enable error frames ([Errno 92] Protocol not available)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.11/site-packages/can/interface.py", line 127, in __new__
bus = cls(channel, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/can/interfaces/socketcan/socketcan.py", line 700, in __init__
self.socket.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1)
OSError: [Errno 92] Protocol not available
Hi @Stausssi , did you find a solution to your issue since you reported it above?
I'm encountering the same kind of problem when trying to use a slcand-based socketcan interface.
I was wondering: could adding a try/catch around the setsockop for the SO_TIMESTAMPNS in
https://github.com/hardbyte/python-can/blob/main/can/interfaces/socketcan/socketcan.py#L711 be a solution ?
In my case, at least, the other self.socket.setsockopt calls in the same SocketcanBus.__init__ do also fail with [Errno 92] Protocol not available, but the errors there are just ignored:
Could not set local loopback flag([Errno 92] Protocol not available)
Could not receive own messages ([Errno 92] Protocol not available)
Could not enable error frames ([Errno 92] Protocol not available)
Traceback (most recent call last):
File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.10/dist-packages/can/viewer.py", line 563, in <module>
main()
File "/usr/local/lib/python3.10/dist-packages/can/viewer.py", line 555, in main
bus = _create_bus(parsed_args, **additional_config)
File "/usr/local/lib/python3.10/dist-packages/can/logger.py", line 104, in _create_bus
return Bus(parsed_args.channel, **config)
File "/usr/local/lib/python3.10/dist-packages/can/util.py", line 378, in wrapper
return f(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/can/interface.py", line 135, in Bus
bus = cls(channel, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/can/interfaces/socketcan/socketcan.py", line 704, in __init__
self.socket.setsockopt(socket.SOL_SOCKET, constants.SO_TIMESTAMPNS, 1)
OSError: [Errno 92] Protocol not available
What would be the consequences of ignoring it also for the SO_TIMESTAMPNS?
Hi @milidam, I did find a solution, but unfortunately I don't remember exactly what solved it. In the end it could've actually just been an update of the base OS. I'm sorry!
What's currently working for me is:
- Install kernel modules (if not already). For me it's
can,vcanandcan_raw - Enable them with
modprobe - Set them to auto-load on startup
- Reboot the machine