我正在开发一个使用原始套接字嗅探网络数据包的程序(AF_PACKET、SOCK_RAW)并以某种方式处理它们。
我不确定我的程序是否运行得足够快并成功捕获套接字上的所有数据包。我担心此套接字的接收缓冲区有时会变满(由于流量突发)并且某些数据包被丢弃。
我如何知道数据包是否由于套接字接收缓冲区空间不足而被丢弃?
我尝试过跑步ss -f link -nlp
。
这输出当前存储在该套接字的设备缓冲区中的字节数,但我无法判断是否有任何数据包被丢弃。
我在用Ubuntu 14.04.2 LTS(GNU/Linux 3.13.0-52-通用 x86_64)。
答案1
丢弃的数据包可以从 netstat、ethtool 输出中看到。对于 UDP 数据包丢失,请检查'netstat -us'
.数据包也会在 NIC 层本身丢弃,这可以通过以下方式看到'ethtool -S <device_name>'
示例输出:
$ netstat -us
IcmpMsg:
InType3: 44
InType8: 5
InType13: 1
InType17: 3
InType37: 1
OutType0: 5
OutType3: 599
OutType8: 4
OutType14: 1
Udp:
86942 packets received
209 packets to unknown port received.
**0 packet receive errors** <== This indicates packets dropped due to socket buffer full
213901 packets sent
UdpLite:
IpExt:
InOctets: 38683476091
OutOctets: 959938111
尝试使用更大的缓冲区空间(SO_RCVBUF)并通过 sysctl 控制 net.core.rmem_max 增加系统范围的最大值
在 NIC 层,您也可以尝试增加环形缓冲区来处理突发流量(通过检查设置ethtool -g
)
答案2
您可以使用 PACKET_STATISTICS 套接字选项检索程序中接收到的数据包总数和丢弃的数据包数,如包(7)联机帮助页。
#include <linux/if_packet.h>
#include <sys/socket.h>
#include <sys/types.h>
...
struct tpacket_stats lStats = {};
socklen_t lStatsLength = sizeof( lStats );
if ( getsockopt( mRawSocket, SOL_PACKET, PACKET_STATISTICS, &lStats, &lStatsLength ) == 0 )
{
printf( "Total Packets: %u\nDropped Packets: %u\n", lStats.tp_packets, lStats.tp_drops );
}
else
{
perror( "Failed to get network receive statistics" );
}