OpenCyphal / pycyphal

Python implementation of the Cyphal protocol stack.
https://pycyphal.readthedocs.io/
MIT License
117 stars 106 forks source link

UDP: presence of network interfaces that do not support Berkeley packet filters breaks packet capture for all interfaces #193

Closed pavel-kirienko closed 2 years ago

pavel-kirienko commented 2 years ago
2021-12-05 04:03:08,689 0439860 DEB: pyuavcan.presentation._presentation: Presentation(UDPTransport('127.42.0.2', local_node_id=2, service_transfer_multiplier=1, mtu=1200), num_publishers=2, num_subscribers=2, num_clients=0, num_servers=4): Constructing new publisher for <class 'org_uavcan_yukon.io.frame.Capture_0_1.Capture_0_1'> at subject-ID 2
2021-12-05 04:03:08,690 0439860 DEB: pyuavcan.transport.udp._ip._v4: IPv4SocketFactory(local_ip_address=127.42.0.2): Constructing new output socket for remote node None and MessageDataSpecifier(subject_id=2)
2021-12-05 04:03:08,690 0439860 DEB: pyuavcan.transport.udp._ip._v4: IPv4SocketFactory(local_ip_address=127.42.0.2): New output <socket.socket fd=26, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=17, laddr=('127.42.0.2', 36958), raddr=('239.42.0.2', 16383)> connected to remote node None
2021-12-05 04:03:08,690 0439860 DEB: pyuavcan.presentation._port._publisher: PublisherImpl(dtype=org_uavcan_yukon.io.frame.Capture.0.1, transport_session=UDPOutputSession(OutputSessionSpecifier(data_specifier=MessageDataSpecifier(subject_id=2), remote_node_id=None), PayloadMetadata(extent_bytes=9256)), proxy_count=1) got a new proxy, new count 1
2021-12-05 04:03:08,690 0439860 DEB: pyuavcan.transport.udp._udp: UDPTransport('127.33.0.0', local_node_id=None, service_transfer_multiplier=2, mtu=1200): Starting UDP/IP packet capture (hope you have permissions)
2021-12-05 04:03:08,690 0439860 DEB: pyuavcan.transport.udp._ip._v4: Constructed BPF filter expression: 'udp and src net 127.33.0.0/16'
2021-12-05 04:03:08,731 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Synthetic device 'any' does not support promiscuous mode, skipping
2021-12-05 04:03:08,731 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Capturable network devices: ['enp4s0', 'lo', 'enp6s0', 'wlp8s0', 'bluetooth-monitor', 'nflog', 'nfqueue', 'dbus-system', 'dbus-session']
2021-12-05 04:03:08,770 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Device 'enp4s0' is configured to use the data link type 1
2021-12-05 04:03:08,810 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Device 'lo' is configured to use the data link type 1
2021-12-05 04:03:08,840 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Device 'enp6s0' is configured to use the data link type 1
2021-12-05 04:03:08,919 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Device 'wlp8s0' is not capturable because the iface is not up. That device is not up
2021-12-05 04:03:08,919 0439860 INF: pyuavcan.transport.udp._ip._link_layer: Could not set up capture on 'wlp8s0'
DiagnosticPublisher(Publisher(dtype=uavcan.diagnostic.Record.1.1, transport_session=UDPOutputSession(OutputSessionSpecifier(data_specifier=MessageDataSpecifier(subject_id=8184), remote_node_id=None), PayloadMetadata(extent_bytes=300)))) DROPPED uavcan.diagnostic.Record.1.1(timestamp=uavcan.time.SynchronizedTimestamp.1.0(microsecond=1638669788919709), severity=uavcan.diagnostic.Severity.1.0(value=2), text="pyuavcan.transport.udp._ip._link_layer: Could not set up capture on 'wlp8s0'")
2021-12-05 04:03:08,920 0439860 DEB: pyuavcan.transport.udp._ip._link_layer: Device 'bluetooth-monitor' supports none of the following data link types: [1, 108, 0]. Last error was: NULL is not one of the DLTs supported by this device
2021-12-05 04:03:09,073 0439860 DEB: pyuavcan.transport.udp._socket_reader: SocketReader(id=0x7f396102df30, original_fd=6, socket=<socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=17, laddr=('239.42.29.85', 16383)>, remote_node_ids=[None]): Received UDP packet of 31 bytes from ('127.42.0.2', 43061) containing frame: UDPFrame(priority=NOMINAL, transfer_id=0, index=0, end_of_transfer=True, payload=00000000000000)
{"8184":{"_metadata_":{"timestamp":{"system":1638669789.073762,"monotonic":491140.332256},"priority":"optional","transfer_id":0,"source_node_id":2},"timestamp":{"microsecond":1638669788661381},"severity":{"value":2},"text":"yukon.io.udp: Constructed transport: UDPTransport('127.33.0.0', local_node_id=None, service_transfer_multiplier=2, mtu=1200)"}}
2021-12-05 04:03:09,074 0439860 CRI: yukon.io.udp: Process failed: Could not compile filter expression 'udp and src net 127.33.0.0/16': Generic error; Bluetooth Linux Monitor link-layer type filtering not implemented
Traceback (most recent call last):
  File "/home/pavel/uavcan/yukon/yukon/io/udp.py", line 130, in main
    result = asyncio.get_event_loop_policy().get_event_loop().run_until_complete(run(node, tran))
  File "/home/pavel/.pyenv/versions/3.10.0/lib/python3.10/asyncio/base_events.py", line 641, in run_until_complete
    return future.result()
  File "/home/pavel/uavcan/yukon/yukon/io/udp.py", line 50, in run
    begin_capture(
  File "/home/pavel/uavcan/yukon/yukon/io/udp.py", line 113, in begin_capture
    tran.begin_capture(handle_capture)
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_udp.py", line 292, in begin_capture
    self._sniffer = self._sock_factory.make_sniffer(self._process_capture)
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_ip/_v4.py", line 142, in make_sniffer
    return SnifferIPv4(self._local, handler)
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_ip/_v4.py", line 151, in __init__
    self._link_layer = LinkLayerSniffer(filter_expression, handler)
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_ip/_link_layer.py", line 124, in __init__
    caps = _capture_all(dev_names, filter_expression)
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_ip/_link_layer.py", line 384, in _capture_all
    pd = _capture_single_device(name, filter_expression, list(codecs.keys()))
  File "/home/pavel/uavcan/pyuavcan/pyuavcan/transport/udp/_ip/_link_layer.py", line 490, in _capture_single_device
    raise LinkLayerCaptureError(
pyuavcan.transport.udp._ip._link_layer.LinkLayerCaptureError: Could not compile filter expression 'udp and src net 127.33.0.0/16': Generic error; Bluetooth Linux Monitor link-layer type filtering not implemented

EDIT: the root cause is the forgotten return statement here (this branch is not covered by tests):

https://github.com/UAVCAN/pyuavcan/blob/9da3cf579b65cae4067b16c621cc3321156f17d4/pyuavcan/transport/udp/_ip/_link_layer.py#L478-L484