Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interface bind on Linux doesn't really work for listening #47

Open
andrewyager opened this issue Apr 17, 2024 · 4 comments
Open

Interface bind on Linux doesn't really work for listening #47

andrewyager opened this issue Apr 17, 2024 · 4 comments

Comments

@andrewyager
Copy link
Contributor

As the notes indicate, the interface bind on Linux doesn't work, particularly when we are dealing with multicast traffic. There are a range of reasons for this, but the socket implementation doesn't really lend itself to being used in this way.

The fix for this is to do something like:

import socket

...

interface_to_listen_on = b"eth0"
receiver._handler.socket._socket.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, interface_to_listen_on)

It would be nice to simply extend sACNreceiver to allow this to be set without requiring a bit of internal digging to find that interface name. This is obviously a Linux only implementation; and I'm not sure that it is quite the same to implement in Windows - I have specifically not tested this in this environment.

I have tested this in Python 3.9+ on a range of 5 series kernels without issue.

@Hundemeier
Copy link
Owner

Hundemeier commented Apr 22, 2024

Implementing a bind_interface parameter for sACNreceiver should not be any problem.
However, did you encounter any issues on Linux when trying to receive multicast sACN packets? #42 suggests that it should now be possible by providing an IP (maybe even 0.0.0.0).
Is this potentially related to #45 ?

@andrewyager
Copy link
Contributor Author

I think this may in fact be true; let me keep testing!

@andrewyager
Copy link
Contributor Author

Closing issue as this seems to have been a product of #45

@andrewyager
Copy link
Contributor Author

Coming back to this issue and re-opening it as I've now had to properly triage what is causing it.

I've done a fresh install of Ubuntu 22.04 with Python 3.10.2 and 5.15.0-112-generic.

The host has two IP interfaces:

ens3: 192.168.1.211/24
ens4: 192.168.5.17/24

I have started sACNView on another host and told it to broadcast onto Universe 1 on the the ens4 network.

I confirmed that tcpDump can see the packets on the ens4 network.

The following does not receive any incoming packets on the ens4 interface as far as the code is concerned.

  • receiver = sacn.sACNreceiver(bind_address="192.168.5.17")
  • receiver = sacn.sACNreceiver()
  • receiver = sacn.sACNreceiver(bind_address="0.0.0.0")

So having tested that, I checked out a local copy of the sacn package and started tinkering.

The following change does, however, make everything work:

diff --git a/sacn/receiving/receiver_socket_udp.py b/sacn/receiving/receiver_socket_udp.py
index ab1fad0..d3935c4 100644
--- a/sacn/receiving/receiver_socket_udp.py
+++ b/sacn/receiving/receiver_socket_udp.py
@@ -26,7 +26,7 @@ class ReceiverSocketUDP(ReceiverSocketBase):
             self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         except socket.error:  # Not all systems support multiple sockets on the same port and interface
             pass
-        self._socket.bind((self._bind_address, self._bind_port))
+        self._socket.bind(('', self._bind_port))
         self._logger.info(f'Bind receiver socket to IP: {self._bind_address} port: {self._bind_port}')
 
     def start(self):

After making this change, I checked the following:

The following receives packets (as expected):

  • receiver = sacn.sACNreceiver(bind_address="192.168.5.17")

The following does not receive packets (probably as expected?)

  • receiver = sacn.sACNreceiver(bind_address="0.0.0.0")
  • receiver = sacn.sACNreceiver()

Changing the source to be on the other interface (facing 192.168.1.211) will cause the host to receive packets in the second scenario (because ens3 is the first interface on the host).

This also reflects the multicast membership joins.

Interestingly, in all cases, specifying the correct interface always resulted in the ip maddr show command showing that the group memberships were correct; but obviously something about the 'bind' operation meant that it would not pick up the packets when they came in on the second interface.

andrewyager added a commit to andrewyager/sacn that referenced this issue Jun 13, 2024
Proposed fix for Hundemeier#47 - allowing for differences between Windows and Linux.

Noting that I'm not clear that the Windows implementation is needed; but I don't have the ability to test that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants