libe131
libe131 copied to clipboard
Multicasting on a computer with multiple network adapters
Hello! I need to multicast sACN to a device from a computer that's connected to two networks, wifi and ethernet, where the device is only on the wifi network. Both the device and the computer are using this library for sACN. There doesn't seem to be API to select with network interface to use, and I'm happy to implement whatever's necessary myself, but I was wondering if you possibly have any tips/ideas on how to go about doing that.
Thank you!
hi @eshkrab ! I'm glad to see the library is being useful to you.
Regarding the issue you are seeing, indeed I didn't think of multicast interface selection in the API originally. This is a requested feature, even in my NodeJS port of the library, however I haven't had time to see it myself. If you are willing to create a PR to address this issue, I'm more than happy to review it and get it in shape to merge it. I highly appreciate the testing scenario you are proposing!
For a starting point, I would like to understand your exact problem:
- You have computer
A
(with two interfaces, wired and wireless) and deviceB
(with one wireless interface). - You join device
B
to a multicast group using the functione131_multicast_join()
configured to some universe. - From computer
A
you try to send packets to a multicast destination using the functione131_multicast_dest()
, configured to the universe ofB
. Please note that the computerA
doesn't need to join the multicast universe, sending to a multicast address should be enough. - The packets from
A
don't reach deviceB
because they are transmitted to the wired network instead of wireless.
Is this the case you are experiencing?
Note: it might be necessary to implement a new function to set the the IP_MULTICAST_IF
option in the outgoing datagram socket. In the same vein and for completeness, it might be necessary to add a new interface parameter to e131_multicast_join()
for when setting the IP_ADD_MEMBERSHIP
socket option.
Ref: https://www.tldp.org/HOWTO/Multicast-HOWTO-6.html
Hello again, it turned out this was relatively simple to implement :)
Please check the multicast
branch of this repository. Can you test it using your setup?
To select an interface for multicast, you can use ip link
in your system to find its index. For example:
$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
link/ether ((anonymised)) brd ff:ff:ff:ff:ff:ff
3: enp2s0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
link/ether ((anonymised)) brd ff:ff:ff:ff:ff:ff
Then you can use the shown numeric index (on the left side) with the e131_multicast_join()
(for a server sACN application) or the new e131_multicast_iface()
(for a client sACN application). Check the updated examples for their usage.
An index of 0
means to use an interface chosen by the system (the old behaviour).
Hello!
Thank you so very much! I ended up implementing a similar function right before you posted this and I'm getting the same result from both. Currently, whichever function I use, the data is streamed correctly for a long while but then the device stops receiving it. Considering I still see the packets being streamed, I'd call this a wonderful success and I'm sure my new problem is rooted elsewhere.
Thanks again for the help and such quick implementation, and here's mine just for kicks:
int e131_bind_interface(int sockfd, const char *interface) {
struct ifaddrs* pList = NULL;
struct ifaddrs* pAdapter = NULL;
struct ifaddrs* pAdapterFound = NULL;
int bindresult = -1;
int result = getifaddrs(&pList);
if (result < 0)
return -1;
pAdapter = pList;
printf(" Trying to bind to :%s\n", interface);
printf("Interfaces\n");
while (pAdapter) {
if ((pAdapter->ifa_addr != NULL) && (pAdapter->ifa_name != NULL) && (AF_INET == pAdapter->ifa_addr->sa_family)) {
//if ((pAdapter->ifa_addr != NULL) && (pAdapter->ifa_name != NULL)) {
printf("%s\n",pAdapter->ifa_name);
if (strcmp(pAdapter->ifa_name, interface) == 0) {
pAdapterFound = pAdapter;
break;
}
}
pAdapter = pAdapter->ifa_next;
}
if (pAdapterFound != NULL) {
//assuming AF_INT
e131_addr_t addr;
bindresult = bind(sockfd, pAdapterFound->ifa_addr, sizeof(addr));
}
freeifaddrs(pList);
return bindresult;
}
Um that's weird to happen. Multicasting can be a bit tricky, specially over wireless. Some things to try:
- Try unicasting and see if you don't loose packets after a while too.
- If you are getting packets out over the right interface but they stop being received on the other side, it might be a router problem.
- Did you try over ethernet and also selecting an interface in the code?
- Can you try over a direct ethernet connection, e.g. no router in-between?
- Is the receiving device a standard linux computer/rpi or is an embedded device e.g. ESP?
Can you confirm you used my code in the multicast
branch and that also fails after a while? Using bind is relevant for receiving sockets, not for sending. My code uses a sockopt instead.
Hi @eshkrab , any updates on this issue? Did you try with the code I supplied in the multicast
branch?
I would like to check if we need more debugging or this can be merged. Thanks for your help testing!
Hey @hhromic,
I had to temporarily step away from that specific part of the project for a little bit but the problem only occurs when I use the router. Using a switch or direct connection works perfectly and I am definitely able to send packets over the right interface. The receiving device is embedded but works with multicasting from a different implementation (Touchdesigner).
I haven't tried a different router or unicasting yet and I'll get post when I get back to working on this but I'm pretty confident it's most likely a router issue and not the code.
Thanks for the heads-up! I will test once more to ensure transmission is selectively directed to different interfaces and the same for receiving, then I will merge the code for future multi-interface users. Thanks for the help and hope this library is useful for you!
I now implemented an API for this in cfa0da7be0f770dfa2c1f021bf657d653db58d61. Will be available in the next release.