Tcpreplay replays the packets caught by tcpdump, which the socket application cannot see.

  linux, question

The problem is a little complicated, please be patient.
My host will receive UDP broadcast packets at a certain time during the workday. I made a simple application program in C language to receive these UDP broadcast packets.
Because packets can only be received at a certain time, in order to test the program, I first use tcpdump to save the packets and then use tcpreplay tool to replay the captured packets. A summary of each section is as follows:

# 1. Grab the bag with tcpdump
 tcpdump -i enp0s25 -s 1600 -w /home/user/log/capture.pcap
 
 # 2. Replay these captured packets with tcpreplay
 tcpreplay -i p1p2 --pktlen /home/user/log/capture.pcap

The output of the ifconfig command is as follows:

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

My machine is equipped with three network cards, two of which are optical cards. Each optical card has two port. p1p1 and p1p2 belong to the same card, and p4p1 and p4p2 belong to the same card. My connection method is:
The optical fiber of p1p2 is connected to p4p2, so the data packet can be sent to p4p2 through p1p2.

When you shed tears, use the tcpdump command to check the data packet on p4p2 and find that there is indeed data output.

tcpdump -i p4p2 -nnn

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

The problem is that my application is unable to listen to the data packet. Some codes of my application are as follows:

#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(AF_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 = 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;

}

After running the program, the program will stop on the recvfrom method. Why can tcpdump see, but my application can’t?
Please advise.

You can use the -e parameter of tcpdump to look at the source and destination mac address of the data packet. I don’t use multicast. I’m not sure if the destination mac address is the broadcast address in this case. if the destination mac address is your enp0s25 mac address, you can’t do this. p4p2 will discard the packet when it finds out that the destination mac address is not itself after receiving the data packet.

You here tcpdump can see the data packet on p4p2 because tcpdump will turn on the promiscuous mode of the network card and thus can see all the data packets received by the network card. However, since the destination mac address of the data packet is not the current network card, the protocol stack will discard the data packet after receiving the data packet driven by the network card.

It is recommended to try tcpreplay on other machines on the same network segment as enp0s25 to see if enp0s25 can receive the corresponding data packet, or try -i enp0s25 on the current machine to see if it can be sent back by the switch after exiting this network card.

In addition, you have not filtered the data packets here. capture.pcap should contain all the data packets received and sent by this network card. I have not used tcpreplay, and I am not sure whether tcpreplay distinguishes between request and response packets. it is recommended to filter it and only contain the data packets you need to avoid unnecessary troubles.