我试图用 tshark 连续捕获大约 20mbit/sec 的流量。如果我在 CentOS 6.5 上使用 tshark 捕获数据包,我会发现大约 4% 到 66% 的数据包被丢弃。如果我在 CentOS 7 上做同样的事情,它永远不会报告任何丢弃的数据包。我实际上曾尝试通过做一些疯狂的事情(例如将大量流量输出到 xml)来让它丢弃数据包。据我所知,它并没有丢弃数据包。我的问题是,CentOS 7 是否有某种功能使丢弃数据包成为不可能?或者它只是丢弃数据包而不告诉我?
作为示例,我执行如下命令:
tshark -i ens224 -c 100000 -w /tmp/delme.pcap
tshark -i ens224 -c 100000 -T pdml > /tmp/delme.pcap
对于第一个命令,CentOS 6 报告 4% 的数据包丢失,而 CentOS 7 则报告无。对于第二个命令,CentOS 报告 66% 的数据包丢失,而 CentOS 7 则报告无。
请注意,两台机器都运行从源代码编译的 tshark 1.12.7。
答案1
我的问题是,CentOS 7 是否具有某种可以防止丢弃数据包的功能?
不是,但是它有两个特性可以大大降低丢包的可能性:
TPACKET_V3
包含套接字的内核版本PF_PACKET
;- libpcap 版本用途
TPACKET_V3
用于PF_PACKET
插座。
Libpcap 使用PF_PACKET
套接字在 Linux 2.2 及更高版本上进行捕获(Linux 1.x 和 2.0 没有PF_PACKET
套接字)。原始PF_PACKET
套接字使用常规套接字机制传递数据包,这意味着 libpcap(或任何其他捕获流量的程序)必须为recvmsg()
每个数据包在该套接字上进行一次调用。这比 *BSD 和 OS X 上的 BPF 机制的工作方式更昂贵,其中多种的每次读取时都会传送数据包,因此,在流量较高的情况下,进行的系统调用较少。
我认为 Linux 2.4 引入了“turbopacket”机制(“TPACKET”中的“T”代表“turbo”),它提供了内核和用户空间共享的内存映射缓冲区。这样,在传送数据包时需要的副本就更少了,并且用户空间中的数据包读取循环可以在每次唤醒时处理多个数据包(为了等待数据包到达,用户空间会进行select()
、poll()
或epoll()
调用)。不幸的是,该机制提供了一圈固定大小的缓冲区,而 libpcap 必须选择一个足够大的大小来容纳最大的数据包。早期版本选择的数据包大小与提供的快照长度相同,即对于您使用的 Wireshark 版本来说,可能是 64K-1,这是相当浪费 - 缓冲区最终没有足够的插槽来容纳数据包以避免溢出。一些后续版本尝试使用 MTU 来确定插槽大小,但它并不总是能做到这一点,即使可以,也可能造成浪费。
在某个 3.x 版本(3.6?)中,TPACKET_V3
添加了一个截然不同的 turbopacket 机制。它更像 BPF,因为缓冲区不保存一个数据包,它可以将多个数据包打包到其中。这可以更好地利用内存进行捕获,并且丢弃的数据包更少。