本文转自http://eslxf.blog.51cto.com/918801/269489
过滤器性能的重要性不言而喻,假设在百兆网络中的每个数据包大小平均为100字节,那么过滤器每秒钟处理的数据包数目可达到十万个。而且同一时刻系统中可能会有多个过滤器正在进行过滤工作,这对过滤器的性能提出了更高要求。BPF虽然在性能方面较之前出现的过滤器要快很多,但随着现代网络的不断发展,BPF的性能受到了严重的挑战。为了提高过滤器性能,必须解决虚拟机指令生成器在处理多个过滤条件组合时存在的指令冗余问题。
问题描述
BPF
提供了一系列的
API
用以完成从高级语言的谓词判断语句到过滤器虚拟机指令的生成过程。它可以帮助用户在不需要了解虚拟机指令的前提下,进行包过滤工作。例如当用户提出需要获取网络中的
ip
数据包时,指令生成器将用户的需求编译成的虚拟机指令如下
:
$ tcpdump -dO ip //
无优化
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 3
//
检查是否为IP协议
(002) ret #96
(003) ret #0
$ tcpdump -d ip //
优化
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 3
//
检查是否为IP协议
(002) ret #96
(003) ret #0
可见,BPF
的指令生成器在处理这样简单的过滤条件时不会出现问题,但是当多个过滤条件组合时,如果在无优化的条件下,它仅仅是将多个条件进行简单的
AND
及
OR
组合,并没有进行相应的优化工作。例如,当用户需要获取协议类型为
TCP
并且源地址为
192.168.10.23
数据时,在无优化的条件下,
BPF
指令生成器将此编译成获取
TCP
数据和获取源地址为
192.168.10.23
这
两个过滤条件
的
AND
操作,其中会出现多条冗余指令,具体描述如下:
$ tcpdump -Od tcp and src 192.168.10.23
(000) ldh [12]
(001) jeq #0x86dd jt 2 jf 4
(002) ldb [20]
(003) jeq #0x6 jt 8 jf 4
(004) ldh [12]
(005) jeq #0x800 jt 6 jf 21
(006) ldb [23]
(007) jeq #0x6 jt 8 jf 21
(008) ldh [12]
(009) jeq #0x800 jt 10 jf 12
(010) ld [26]
(011) jeq #0xc0a80a17 jt 20 jf 12
(012) ldh [12]
(013) jeq #0x806 jt 14 jf 16
(014) ld [28]
(015) jeq #0xc0a80a17 jt 20 jf 16
(016) ldh [12]
(017) jeq #0x8035 jt 18 jf 21
(018) ld [28]
(019) jeq #0xc0a80a17 jt 20 jf 21
(020) ret #96
(021) ret #0
而以上指令完全可以优化为如下所示的指令:
$ tcpdump -d tcp and src 192.168.10.23
(000) ldh [12]
(001) jeq #0x86dd jt 8 jf 2
(002) jeq #0x800 jt 3 jf 8
(003) ldb [23]
(004) jeq #0x6 jt 5 jf 8
(005) ld [26]
(006) jeq #0xc0a80a17 jt 7 jf 8
(007) ret #96
(008) ret #0