OpenCyphal / pycyphal

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

UDP Transport couples node ID with IP address #315

Closed jrrutlan-amazon closed 6 months ago

jrrutlan-amazon commented 9 months ago

When I invoke yakut

yakut -vv --transport "UDP('145.16.2.100',42)" call ...

I see in the verbose log (and on inspection of the source) that Pycyphal attempts to bind 145.16.2.42

2023-10-06 10:54:59 2193007 DEB pycyphal.transport.udp._udp: UDPTransport('145.16.2.42', local_node_id=42, service_transfer_multiplier=1, mtu=1200): Initialized with local node-ID 42

Reading the spec 4.3.2.1 "The IP address of a node bears no relevance for the protocol — multiple nodes may share the same IP address;" - it this an assumption/bug in Pycyphal?

maksimdrachov commented 9 months ago

I think you're conflating two different IP addresses: one that relates to the node itself; and one that relates to specific Messages/Services.

A subscriber to certain Cyphal subjects will join the IP multicast groups corresponding to said subjects. Likewise, a node that provides at least one RPC-service will join the IP multicast group corresponding to its own node-ID

jrrutlan-amazon commented 9 months ago

Maybe, but at least in practise, if I try to yakut -vv --transport "UDP('145.16.2.100',42)" call ... I get an ENODEV because it attempts to bind to 145.16.2.42 which isn't available.

InvalidMediaConfigurationError: Could not register multicast group membership 239.16.29.77 via 145.16.2.42 using <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=17> [ENODEV]
maksimdrachov commented 9 months ago
image

Ok, I think I've managed to reproduce what you're talking about, will try to see if I can help.

maksimdrachov commented 9 months ago

Ok, so from what I understand you need to provide an actual "working" IP address, the reason why it gives the error above is that that particular IP address is not connected to anything on my computer, so therefore has no way to join any multicast network.

If I do the same command using the loopback address it works without any issues.

The error happens here, when trying to setup the input socket:

https://github.com/OpenCyphal/pycyphal/blob/4846761a20dba7c23efd403c0a5c053ee9196f6c/pycyphal/transport/udp/_ip/_v4.py#L88-L133

I took a look at the unit tests for that particular function here:

https://github.com/OpenCyphal/pycyphal/blob/4846761a20dba7c23efd403c0a5c053ee9196f6c/tests/transport/udp/ip/v4.py#L21-L112

You can see it tests to make sure that 1.2.3.4 (an address that most likely won't be associated with any network interface) gives the expected error (the one we're discussing). -> From line 86 onwards.

pavel-kirienko commented 9 months ago

I see in the verbose log (and on inspection of the source) that Pycyphal attempts to bind 145.16.2.42

This is expected to happen if you're using an old version of PyCyphal with your Yakut installation that was released before the migration to the pre-final Cyphal/UDP specification. You need at least v1.13, see the changelog here: https://github.com/OpenCyphal/pycyphal/blob/master/CHANGELOG.rst. The latest version is preferred because it contains other UDP-related fixes.

pavel-kirienko commented 6 months ago

Closing because this is suspected to be caused by a version issue. Please re-open if upgrading didn't help.