[原创]FreeBSD下千兆双口数据包捕获的性能分析(SMP Kernel)

    首先说一下测试环境:Intel Xeon 5130(2GHz,双核)、4G内存,外加一块Intel Expi9402PF(82571EB)千兆光纤双口网卡。由于手边没有smartbit,只好将真实流量的镜像作为测试源。在9402PF上插上两个电口的模块,将镜像得到的两个相同的1G流量作为输入源。由于是镜像得到的流量,所以稍微有些波动,大约稳定在950M左右,测试时以BPF实际收到的数据包数为准。

    一直想测试下FreeBSD的libpcap千兆网数据包捕获效率,之前零零散散的记录过Fedora 6在2G流量(TX+RX流量各1G)输入下的抓包情况。虽然空转时Fedora 6也能抓到接近1900M的流量,不过双网卡抓包时CPU消耗惊人。这是题外话了,这次测试的内容是FreeBSD 6.4下em-6.7.3驱动的表现,以及在何种配置下能够抓到接近100%的数据包,且CPU消耗较小!测试程序是自己写的一个累计数据包个数和长度的小工具(类似PF_RING中自带的pcount),就是在pcap_loop的回调里把数据包的len加一下,然后每隔一定时间输出统计得到的包数和流量大小。唯一不同的是这个程序能够同时累计两个网卡上的流量,方便测量TX/RX两个方向同时抓包的效率。

    测试用例设计如下:

用例名称

内核

DEVICE_POLLING

驱动版本

驱动特性1

驱动特性2

BPF缓冲

GEN_01

普通内核

 

em-6.7.3

 

 

默认

GEN_02

普通内核

 

em-6.7.3

 

 

10M

GEN_03

普通内核

 

em-6.7.3

 

EM_FAST_IRQ

10M

GEN_POLL_01

普通内核

HZ=1000

em-6.7.3

DEVICE_POLLING

 

默认

GEN_POLL_01n

普通内核

polling disable

em-6.7.3

DEVICE_POLLING

 

默认

GEN_POLL_02

普通内核

HZ=1000

em-6.7.3

DEVICE_POLLING

 

10M

GEN_POLL_03

普通内核

HZ=1000

em-6.7.3

DEVICE_POLLING

EM_FAST_IRQ

默认

GEN_POLL_03n

普通内核

polling disable

em-6.7.3

DEVICE_POLLING

EM_FAST_IRQ

默认

GEN_POLL_04

普通内核

HZ=1000

em-6.7.3

DEVICE_POLLING

EM_FAST_IRQ

10M

SMP_01

SMP内核

 

em-6.7.3

 

 

默认

SMP_02

SMP内核

 

em-6.7.3

 

EM_FAST_IRQ

默认

SMP_03

SMP内核

 

em-6.7.3

 

 

10M

SMP_04

SMP内核

 

em-6.7.3

 

EM_FAST_IRQ

10M

SMP_POLL_01

SMP内核

HZ=1000

em-6.7.3

DEVICE_POLLING

 

默认

SMP_POLL_02

SMP内核

HZ=1000

em-6.7.3

DEVICE_POLLING

 

10M

SMP_POLL_03

SMP内核

HZ=1000

em-6.7.3

DEVICE_POLLING

EM_FAST_IRQ

默认

SMP_POLL_04

SMP内核

HZ=1000

em-6.7.3

DEVICE_POLLING

EM_FAST_IRQ

10M

 

 

    首先说一下SMP内核。SMP是 Symmetric MultiProcessor Kernel 的缩写,即对称多处理器。从FreeBSD 3.x开始就有这个特性了,只不过直到6.0之后 FreeBSD SMPng project 才标上“complete”。在FreeBSD 6.x下,打开SMP特性的内核能给双网卡抓包带来难以想象的性能提升!(前提是你有多处理器或者多核),通过下面实际的性能对比你可以看到和普通内核的明显差异。而且开启SMP也很简单,按照 SMP - using more than one CPU 的介绍,在内核配置中加入以下两行即可:

# To make an SMP kernel, the next two are needed
options SMP # Symmetric MultiProcessor Kernel
# options APIC_IO # Symmetric (APIC) I/O
(options APIC_IO我6.4下config说没有这个选项,可能是7以后才加的,于是给注释掉了)

    关于SMP和DEVICE_POLLING不能并存的说法,实际上在FreeBSD 6.x上并不存在此问题,放心大胆的加上轮询支持吧:

options DEVICE_POLLING # 打开 Polling
options HZ=1000

    加完这个不要忘了在 /etc/sysctl.conf 中加入kern.polling.enable=1 

 

    另一个需要说明的是e1000驱动em-6.7.3的两个特性:DEVICE_POLLING(轮询) 和EM_FAST_IRQ。这个驱动的源码是FreeBSD 6.4自带的,可以到 /usr/src/sys/dev/em 下翻出来自己编译。因为网上没有找到关于开启DEVICE_POLLING和EM_FAST_IRQ时,e1000的抓包性能到底有多大的改善,于是自己动手测试了一下。需要注意的是,内核中没有加入options DEVICE_POLLING的话,就算你驱动 -DDEVICE_POLLING,kldload也是不认的。试图在一个没有轮询的内核中加载轮询驱动,你会得到一个非常悲惨的提示:

# kldload if_em.ko
kldload: can't load if_em.ko: No such file or directory

ps:就是这个提示害得我尝试了几个路径都没加载成功,换个清楚点的错误提示啊!

 

    最后是BPF的缓冲区大小,默认是:

# sysctl -a | grep bpf
net.bpf.bufsize: 4096
net.bpf.maxbufsize: 524288 // 最大512K
net.bpf.maxinsns: 512

    这512K的缓冲区,千兆下机器稍微卡一卡估计就塞满了… 一般优化的话建议改成10M:

# sysctl -w net.bpf.bufsize=10485760
# sysctl -w net.bpf.maxbufsize=10485760

    不过改成10M就看不出丢包情况了(这里丢包以BPF的计数为准,BPF的缓冲区一天不塞满,丢包计数就一直是0),所以测试时仍然保留默认BPF缓冲区大小的组合。

 

 

    测试结果如下:

 

 

    上表中的捕获效率是根据BPF提供的recv和drop数据包数计算而来的,由于em0/em1上有细微差异,这里使用两个网卡收到数据包的平均值作为依据。流量信息是单条链路上的平均捕获流量,由于使用真实流量的镜像作为测试源,所以稍微有些波动,不过可以认为流量在950Mbps上下。

 

    普通内核中单网卡抓包还算良好(大约能抓到940M的样子),不过一旦双网卡同时进行数据包捕获,libpcap的效率就会急剧下降,经常是一个网卡抓到300M~400M,另一个100M都不到。从GEN_01、GEN_02两组数据看,不管BPF缓冲区设多大,没有开启轮询的普通内核抓包效率大约只有20%。而且一旦开始抓包,CPU就没有一点空闲时间,几乎都忙于中断处理。开启轮询后的普通内核性能也一般,每块网卡抓到400M就是最好情况了。不过换上SMP内核,情况就大不相同了。

在没有开启轮询的SMP_01、SMP_02两个例子中,可以看到没有轮询的SMP内核在默认BPF缓冲区大小下,抓包性能都能达到98% 且CPU空闲大约有35%~38% 的样子。SMP_02是开启EM_FAST_IRQ后的em-6.7.3测试结果,不过从结果上来看这个更像轮询,直接屏蔽了中断(CPU中断处理时间0%)。由于没仔细看过em-6.7.3中的轮询部分,也不好说他这个怎么实现的,反正感觉开不开DEVICE_POLLING,CPU的占用都是那么多(可以对比SMP_01 和SMP_POLL_01)。

 

    最后说一下多核系统下千兆双口数据包捕获的最佳配置:SMP_POLL_04。首先用附件中的SMP_lite配置编译一个SMP+轮询的6.4内核。然后ee /etc/sysctl.conf,在末尾添加以下三句:

# enable Kernel polling!
kern.polling.enable=1
# increase BPF buffer to 10M
net.bpf.bufsize=10485760
net.bpf.maxbufsize=10485760

    接着在em-6.7.3驱动的Makefile中加上:

# DEVICE_POLLING gives you Legacy interrupt handling
CFLAGS += -DDEVICE_POLLING -DEM_FAST_IRQ

(注:如果想把em驱动集成到内核中,可以修改 /usr/src/sys/modules/em中的Makefile)

 

    附带精简过的SMP内核配置文件:SMP_lite.rar

 

    转载请勿只转载数据。以上结果均在libpcap空转的情况下得出的,也就说没有加任何处理过程,只能作为libpcap千兆网下最佳数据包捕获性能的参考,因为一旦使用nProbe类似需要处理数据包的程序,其捕获性能应该会比这个要低,并且性能的下降程度和CPU的繁忙程度密切相关。另外,由于使用真实流量数据作为测试源,不同时段捕获到的流量多少有些波动,所以捕获的流量大小只供参考,应该以BPF实际接收的数据包个数为准。

    看来6.4的多核支持还是有点问题.... 换了一个四核的机器,也是Xeno 2GHz的CPU,拿自带的bce抓包还好点,不过换上9402PF后,两个链路一共抓到的流量只有1060M,接近50%的包都丢了。而且此时CPU还有60%是空闲的,systat看有2个核闲着没事做,网上找了半天也没个说法。6.4上Quad Core的抓包性能还不如Dual Core,这个结果实在是令人失望...

posted @ 2009-12-15 11:08  bits  阅读(2700)  评论(3编辑  收藏  举报