2
votes

My server will receive UDP multicast packets at a certain period during workday. I wrote a c socket application to receive these UDP multicast packets. As my server can only receive packets at a certain period, for testing, I captured the packets with tcpdump.

tcpdump -i enp0s25 -s 1600 -w /home/user/log/capture.pcap

and then, I replay the captured packets with tcpreplay.

tcpreplay -i p1p2 --pktlen /home/user/log/capture.pcap

this is the 'ifconfig' output.

 enp0s25: flags=4163<UP,BROADCAST,RUNNING,MULTICAST mtu 1500

    inet 192.168.3.6  netmask 255.255.255.0  broadcast 192.168.3.255
    inet6 2400:2410:2a41:2e00:1d6f:2fde:2436:608f  prefixlen 64  scopeid 0x0<global
    inet6 fe80::555d:f7f2:a114:51df  prefixlen 64  scopeid 0x20<link
    ether 98:90:96:a7:6f:f3  txqueuelen 1000  (Ethernet)
    RX packets 45031  bytes 50053845 (47.7 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 14129  bytes 1784865 (1.7 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    device interrupt 20  memory 0xf9100000-f9120000  

 lo: flags=73<UP,LOOPBACK,RUNNING mtu 65536

    inet 127.0.0.1  netmask 255.0.0.0
    inet6 ::1  prefixlen 128  scopeid 0x10<host
    loop  txqueuelen 1  (Local Loopback)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 p1p1: flags=4099<UP,BROADCAST,MULTICAST mtu 1500

    ether 00:02:c9:5a:77:62  txqueuelen 1000  (Ethernet)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 218  dropped 207  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 p1p2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST mtu 1500

    inet6 fe80::2acf:23a9:3c1a:89a0  prefixlen 64  scopeid 0x20<link
    ether 00:02:c9:5a:77:63  txqueuelen 1000  (Ethernet)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 329583  bytes 50655424 (48.3 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 p4p1: flags=4099<UP,BROADCAST,MULTICAST mtu 1500

    ether 00:0f:53:29:e9:30  txqueuelen 1000  (Ethernet)
    RX packets 0  bytes 0 (0.0 B)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    device interrupt 26  

 p4p2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST mtu 1500

    ether 00:0f:53:29:e9:31  txqueuelen 1000  (Ethernet)
    RX packets 329583  bytes 51973756 (49.5 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 0  bytes 0 (0.0 B)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    device interrupt 35

three NICs was installed in my server. two of them are Fibre Channel NIC. and each of them has two ports. p1p1 and p1p2 are the same physical NIC, p4p1 and p4p2 are the same physical NIC. I connect fiber cable from p1p2 to p4p2, so tcpreplay should send packets from p1p2 to p4p2.

then, I checked whether there's packets comming into p4p2.

tcpdump -i p4p2 -nnn

part of the output:

18:05:21.062023 IP 10.10.31.31.3131 > 239.239.31.31.3131: UDP, length 97
18:05:21.062035 IP 10.10.31.31.3131 > 239.239.31.31.3131: UDP, length 97

it seems that tcpreplay do resend the captured packets to p4p2. but the problem is my sock application cannot receive these packets. following are part of my C socket application.

 #pragma  pack(1)

 #include <stdio.h>
 #include <string.h>
 #include <float.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <signal.h>
 #include <unistd.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/types.h>
 #include <sys/socket.h>


 #define MAXBUFSIZE 65536 // Max UDP Packet size is 64 Kbyte

 int main() {
     int sock, status, socklen;
     uint8_t buffer[MAXBUFSIZE];
     struct sockaddr_in saddr;
     struct ip_mreq imreq;

     memset(&saddr, 0x00, sizeof(saddr));
     memset(&imreq, 0x00, sizeof(imreq));
     memset(buffer, 0x00, MAXBUFSIZE);

     // open a UDP socket
     sock = socket(PF_INET, SOCK_DGRAM, 0);
     if ( sock < 0 ) {
         perror("Error creating socket"); 
         return(0);
     }

     imreq.imr_multiaddr.s_addr = inet_addr("239.239.31.31");
     imreq.imr_interface.s_addr = htonl(INADDR_ANY); // use DEFAULT interface

     // JOIN multicast group on default interface
     setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&imreq, sizeof(struct ip_mreq));

     saddr.sin_family = AF_INET;
     saddr.sin_port = htons(3131); 
     saddr.sin_addr.s_addr = htonl(INADDR_ANY); 
     status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));

     if ( status < 0 ) {
         perror("Error binding socket to interface");
         return(0);
     }

     socklen = sizeof(struct sockaddr_in);

     // receive 500 packets from socket
     int m = 0;
     for (; m < 500; m++) {
         status = recvfrom(sock, buffer, MAXBUFSIZE, 0, (struct sockaddr *)&saddr, &socklen);
         if(status < 0) {
             perror("receive error!\n");
         } else if (status > 0) {
             // DO sth usefully here.
         }              
     }

     // shutdown socket
     shutdown(sock, 2);
     // close socket
     close(sock);

     return 0;
 }

when I run the application above, it will stop at recvfrom function. Can anyone tell me why my application cannot receive these packets?

1
Unrelated to your problem, and just to nitpick, but saddr.sin_family is an address family, and should be AF_INET. The PF in PF_INET stands for protocol family. Fortunately AF_INET and PF_INET both expands to the same value.Some programmer dude
Also, if (status 0)?Some programmer dude
@Someprogrammerdude thanks, modified.Luis
After you "fixed" the condition, it's still wrong. If the recvfrom call succeeds then it will return a value larger than zero. It will be the size of the packet you received.Some programmer dude
@Someprogrammerdude thanks againLuis

1 Answers

1
votes

According to tcpreplay documentation, it's not possible to send packets on the same computer: packets are injected between the TCP/IP stack and the device driver of the network card, so the TCP/IP stack running tcpreplay never sees the packets. try to run tcpreplay in a virtualized environment on the same machine, the host OS should then see the packets.

ref: http://tcpreplay.synfin.net/wiki/FAQ