我正在尝试使用 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 报告 none。对于第二个命令,CentOS 报告 66% 的数据包丢失,但 CentOS 7 没有报告。
请注意,两台机器都运行从源代码编译的 tshark 1.12.7。
不,但它有两个功能可以大大降低丢包的可能性:
TPACKET_V3
的内核版本;PF_PACKET
TPACKET_V3
的libpcap 版本。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,因为缓冲区不保存一个数据包,它可以包含多个数据包。这可以更好地利用内存进行捕获,并且丢弃的数据包更少。