libe131 icon indicating copy to clipboard operation
libe131 copied to clipboard

Multicasting on a computer with multiple network adapters

Open eshkrab opened this issue 6 years ago • 8 comments

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!

eshkrab avatar Sep 20 '18 23:09 eshkrab

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:

  1. You have computer A (with two interfaces, wired and wireless) and device B (with one wireless interface).
  2. You join device B to a multicast group using the function e131_multicast_join() configured to some universe.
  3. From computer A you try to send packets to a multicast destination using the function e131_multicast_dest(), configured to the universe of B. Please note that the computer A doesn't need to join the multicast universe, sending to a multicast address should be enough.
  4. The packets from A don't reach device B because they are transmitted to the wired network instead of wireless.

Is this the case you are experiencing?

hhromic avatar Sep 22 '18 11:09 hhromic

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

hhromic avatar Sep 22 '18 11:09 hhromic

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).

hhromic avatar Sep 22 '18 14:09 hhromic

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;
}

eshkrab avatar Sep 23 '18 03:09 eshkrab

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.

hhromic avatar Sep 23 '18 07:09 hhromic

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!

hhromic avatar Oct 08 '18 10:10 hhromic

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.

eshkrab avatar Oct 08 '18 17:10 eshkrab

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!

hhromic avatar Oct 10 '18 12:10 hhromic

I now implemented an API for this in cfa0da7be0f770dfa2c1f021bf657d653db58d61. Will be available in the next release.

hhromic avatar Sep 03 '23 21:09 hhromic