python-can icon indicating copy to clipboard operation
python-can copied to clipboard

OSError 92: Protocol not available inside `SocketcanBus.__init__`

Open Stausssi opened this issue 2 years ago • 2 comments

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.

  1. Start a Podman pod inside a Fedora CoreOS system with vcan kernel modules active.
  2. Create the vcan interface inside the initContainer of the Pod. A sample Containerfile is included.
  3. Add a Python container to the Pod.
  4. Try initialising the SocketcanBus inside 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

Stausssi avatar Mar 10 '23 15:03 Stausssi

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?

milidam avatar Feb 11 '25 17:02 milidam

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, vcan and can_raw
  • Enable them with modprobe
  • Set them to auto-load on startup
  • Reboot the machine

Stausssi avatar Feb 12 '25 13:02 Stausssi