Skip to content

Conversation

@oko256
Copy link
Contributor

@oko256 oko256 commented Sep 10, 2025

I didn't manage to get zbeacon IPv4 multicast to work on Linux (debian), and took a look at it and now I don't know how (if at all) this could've worked to begin with? In original code, setsockopt IP_MULTICAST_IF passed interface as an index, but looking at Linux docs it should only accept ip_mreq, ip_mreqn or in_addr structs, and indeed in my testing the multicast always fails on this setsockopt call. To further complicate things, on OSX only in_addr struct is accepted, and on Windows it can only be a DWORD containing interface index or IP address.

To make this work on Linux, OSX and Windows, I changed it to use interface index only on Windows and use in_addr struct on other platforms. At least tested this on those three platforms and now IPv4 multicast beacon worked on all of them.

Then I noticed another problem that the original code always bound the listening socket to INADDR_ANY on *NIX platform, which causes that any beacons in any multicast group will be heard by the socket, which in turn makes using multicast meaningless compared to broadcast (beacons in different multicast groups hear each other). This was fixed by binding the listening socket on *NIX to the multicast address instead when we are using multicast, after which the beacons in one multicast group were only heard by beacons that are members in that specific group. I assume this is the way this was intended to work, please correct me if I'm wrong?

On Windows, the original code already bound to the host address instead, and for some reason that already also works correctly with multicast and only the beacon in the specific multicast group is heard. Honestly, I don't know why that works, but I guess Windows handles the IPv4 membership for the socket differently?

zbeacon selftest also had a similarly broken check for determining if IPv4 multicast was available. I actually just removed the check and relied on the zbeacon CONFIGURE output instead to determine if multicast is there.

zhash/zhashx cache dir fix

Another commit makes a small fix to zhash/zhashx selftests that used .cache as a temporary file for testing. The problem is that if you have clangd static analysis running, it creates .cache directory for the analysis which annoyingly breaks the tests. I replaced this according to the convention from other tests that RW data from tests should go to selftest-rw directory instead.

Clangd uses `.cache` directory which conflicts with the directory used
by the selftests of zhash and zhashx, which caused the tests to fail
unnecessarily. Changed those to use `src/selftest-rw` like other tests.
zbeacon multicast always fails at `setsockopt` for IP_MULTICAST_IF on
Linux, because Linux expects the parameter type to be either `ip_mreqn`,
`ip_mreq`, or `in_addr` structure instead of interface index. On the
other hand, Windows does not support those structures, but instead
supports a DWORD of IPv4 address or an interface index. OSX seems to
support `in_addr`. Modified the parameter type to be interface index
for Windows and `in_addr` for others.

Multicast beacons were also received from all multicast groups instead
of just the one we join to. This is because the code bound the listening
UDP socket to `INADDR_ANY` when using multicast. Modified to bind the
listening UDP socket only to the specified multicast address.
@sphaero sphaero merged commit f22f657 into zeromq:master Sep 16, 2025
9 of 11 checks passed
@sphaero
Copy link
Contributor

sphaero commented Sep 16, 2025

thanks, this really needed attention 👍

@oko256 oko256 deleted the fix-cache-and-zbeacon-multicast branch September 20, 2025 20:11
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

Successfully merging this pull request may close these issues.

2 participants