4

If I run:

iperf -s -u -B 224.0.31.155

and run

sudo tcpdump -ni any 'host 224.0.31.155'

tcpdump is able to capture something:

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
15:49:15.334484 IP [some ip].14386 > 224.0.31.155.14386: UDP, length 1364
15:49:15.334728 IP [some ip].14386 > 224.0.31.155.14386: UDP, length 1374
15:49:15.375026 IP [some ip].14386 > 224.0.31.155.14386: UDP, length 1058
15:49:15.375184 IP [some ip].14386 > 224.0.31.155.14386: UDP, length 832

However, if I kill my iperf process above, and then start my C++ application that also joins the same group and binds the same port, tcpdump no longer sees the traffic.

Here is the snippet:

struct sockaddr_in mc_addr; /* socket address structure */
struct ip_mreq mc_req; /* multicast request structure */
unsigned int from_len = sizeof(mc_addr); /* source addr length */

/* construct a multicast address structure */
memset(&mc_addr, 0, from_len);
mc_addr.sin_family = AF_INET;
inet_aton(mcastGroup.c_str(), &mc_addr.sin_addr);
mc_addr.sin_port = htons(port);

/* bind to multicast address to socket */
if (bind(s, (struct sockaddr *) &mc_addr, sizeof(mc_addr)) < 0) {
    std::cerr << "failed to bind to the port " << port << "|error="
            << strerror(errno) << std::endl;
    throw;
}
/* construct an IGMP join request structure */
mc_req.imr_multiaddr.s_addr = inet_addr(mcastGroup.c_str());
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);

/* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &mc_req,
        sizeof(mc_req))) < 0) {
    std::cerr << "failed to set socket option to request for membership"
            << std::endl;
    throw;
}

tcpdump details:

$ tcpdump --version
tcpdump version 4.1-PRE-CVS_2012_03_26
libpcap version 1.4.0

I just checked it on one of my production servers and it shows the same behavior but I see that my C++ application is processing data properly.

Any idea what's going on?

Ajay
  • 18,086
  • 12
  • 59
  • 105
Hei
  • 1,844
  • 3
  • 21
  • 35
  • I'm not sure what `IP_ADD_MEMBERSHIP` would do, but probably you also need to `listen` – Ajay Jun 08 '16 at 07:16
  • I use epoll to monitor the file descriptor and so listen() isn't required. – Hei Jun 08 '16 at 09:33
  • You can capture data just by running "iperf -s -u -B 224.0.31.155"? It seems that you just start a server which is listening.Your code is to generate multicast traffic, it seems have different function from your iperf command. Can you give more details ? – sel-fish Jun 09 '16 at 10:18
  • "iperf -s -u" means "server mode" with UDP support. It doesn't capture packet. It just joins the multicast group so is my code -- it joins the multicast group without capturing. – Hei Jun 09 '16 at 13:32
  • @Hei you code works for me, as I add sleep for a while after your snippet, and produce some traffic from other node ```iperf -c 224.0.31.155 -u -T 32 -t 1 -i 1 -p 14386```, maybe you can add some code to read data after your snippet and see what you will get ? – sel-fish Jun 14 '16 at 04:06
  • @sel-fish yes, my C++ code above works in a sense that it does join the group and I am able to read the data from the socket. Just that while I am reading data from the socket through my C++ code, tcpdump doesn't sniff anything. That's the original question here. – Hei Jun 14 '16 at 13:44
  • @Hei In my case, tcpdump could sniff, but can only sniff the content you read, not as much as you can sniff when run 'iperf -s -u -B 224.0.31.155', maybe just one line or two will be printed on the screen. – sel-fish Jun 14 '16 at 14:49
  • maybe you weren't sniffing the actual traffic when not using iperf because I ran into a case awhile back that a router in the office was sending traffic to a mcast group my C++ could join, and that traffic wasn't what I expected... – Hei Jun 14 '16 at 14:53
  • @Hei When I said that I only sniff one or two lines, that's because my previous code just read 64 bytes and exit. I double checked and pretty sure that what I sniffed was produced by 'iperf -c 224.0.31.155 -u -T 32 -t 1 -i 1 -p 14386'. I can show you the steps I took to get that if you need, btw, I'm using CentOS release 6.5 (Final)/iperf-2.0.5, and tcpdump version as same as yours. – sel-fish Jun 15 '16 at 05:27
  • @sel-fish argh, I think there was a confusion. If I use iperf to publish data and tcpdump to sniff, it looks good (my C++ code above has no involvement). If I don't use iperf but try to use my C++ code above to join (and add a bit more code to read), tcpdump sniffs nothing. – Hei Jun 15 '16 at 09:10
  • @Hei I knew the problem. My experiment goes that way : 1st, I ran ''iperf -s -u -B 224.0.31.155 -i 1 -p 14386" at nodeA, ran tcpdump as nodeA too, then ran "iperf -c 224.0.31.155 -u -T 32 -t 1 -i 1 -p 14386" to generate data from nodeB, then the tcpdump process sniff; 2nd, I shutdown iperf at nodeA, and run c++ application, keep the tcpdump process run at nodeA, run iperf to generate data again from nodeB, tcpdump still sniff data. I see no confusion here. – sel-fish Jun 15 '16 at 09:14
  • @Ajay No. This is multicast. UDP. Not TCP. – user207421 Sep 24 '17 at 05:20

2 Answers2

0

One potential problem in your code is that you bind your socket to the multicast address. This is not required and may cause all kinds of weird behaviors.

If you only want to send UDP packets you do not need to bind your socket at all. The OS will do it for you.

If you want to send and receive multicast traffic you most likely want to bind to INADDR_ANY on Linux. This is almost an idiom. bind() on UDP sockets has very non-intuitive semantics on Linux. The IP address just has a filtering role. It neither binds to the specified IP address, nor does it bind to the interface associated with that IP address.

Another odd thing is that you assign to mc_req.imr_interface which should not be a member of ip_mreq. I think this should read mc_req.imr_address, but of course if this compiles then I shall stay silent.

Johannes Overmann
  • 4,914
  • 22
  • 38
  • Thanks for your comment. I just wanted to receive mcast messages. And yes, it complied fine. – Hei Sep 26 '17 at 09:15
0

IGMP messages are conserved. If the host is already a member of the group, it won't send out a new IGMP membership report message when another application joins. If you're receiving multicasts, be happy.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I raised this question because once awhile I need to use tcpdump to diagnose issues on production. Thanks. – Hei Sep 26 '17 at 09:15