Fedora下集成PF_RING的详细过程(配图)

在千兆网环境下,tcpdump丢包率相当高。网上搜了很多制标不治本的方法,比如增大缓冲区,然而缓冲区再大也有塞满的时候,只能从驱动和硬件下手。好在有“零拷贝(Zero Copy)”这个东西(说白了也就是通过DMA等方式,省掉从NPF驱动到用户程序内存空间的一次复制,给CPU减少负担),而PF_RING正是一个通过给Linux内核打补丁来实现zero copy的强大工具,于是想给Fedora集成个PF_RING。

没接触过Linux内核,网上这方面资料都是Ubuntu的,和Fedora下有点不同。摸了近2周才把PF_RING给补上,记录一下详细编译过程,以免以后又走弯路。
另一篇关于Fedora 9下编译的文章:http://guotie.blogbus.com/logs/29668826.html

 

本文中的编译过程, 在Fedora 7和Fedora 9下(实机和虚拟机)均测试通过(来来回回编译了内核5遍,不熟也熟了...)
文章中没有需要单独下载的压缩包,内核源码也建议使用PF_RING自带的mkpatch.sh来下载(或者下完放到workspace目录中)


首先,按照正常步骤,下载PF_RING(粗体是要输入的命令,我的PF_RING存放目录是 /home/kernel)
cd /home/kernel
svn co https://svn.ntop.org/svn/ntop/trunk/PF_RING/

 

等下载完成后,/home/kernel 下多了一个PF_RING的目录。
cd PF_RING
# ll
total 36
drwxr-xr-x 3 root root  4096 2009-03-17 16:26 doc
drwxr-xr-x 5 root root  4096 2009-03-17 16:26 kernel
-rwxr-xr-x 1 root root 14678 2009-03-20 22:48 mkpatch.sh
-rw-r--r-- 1 root root   643 2009-03-17 16:26 README
drwxr-xr-x 8 root root  4096 2009-03-17 16:26 userland

 

uname -a 或者 uname -r 确定内核版本(建议使用一样的内核源文件编译,这样配置起来方便点)
vi mkpatch.sh 修改内核版本号
SUBLEVEL=${SUBLEVEL:-24.7}

默认是-24.7,这里用你 uname -r 获取的版本来代替,例如
# uname -r 显示2.6.25-14.fc9.i686则改成 SUBLEVEL=25

 

 

./mkpatch.sh
下载内核到workspace中,生成目录linux-2.6.25-1-686-smp-PF_RING和补丁文件linux-2.6.25-1-686-smp-PF_RING.patch.gz,如下

# ll
total 60220
drwxr-xr-x 22 root root     4096 2009-03-21 20:43 linux-2.6.25
drwxr-xr-x 21 root root     4096 2008-04-17 10:49 linux-2.6.25-1-686-smp-PF_RING
-rw-r--r--  1 root root    63254 2009-03-20 22:50 linux-2.6.25-1-686-smp-PF_RING.patch.gz
-rw-rw-r--  1 zhou zhou 61517918 2009-03-20 22:45 linux-2.6.25.tar.gz
lrwxrwxrwx  1 root root       25 2009-03-20 22:49 PF_RING -> /home/zhou/kernel/PF_RING

 

这里不建议直接用生成的linux-2.6.25-1-686-smp-PF_RING这个源码,之前出问题都是在这个上面,还是按PF_RING手册上说得给干净内核打补丁来得稳妥。另外,没有特殊需要,不建议使用其他教程里提及的Fedora RPM源码包kernel-2.6.25-14.fc9.src.rpm,make时会出现些莫名奇妙的错误。

按下面操作把这个目录给改名掉,然后手动给原始内核打补丁
mv linux-2.6.25-1-686-smp-PF_RING/ linux-2.6.25-1-686-smp-PF_RING.bak/
zcat linux-2.6.25-1-686-smp-PF_RING.patch.gz | patch -p0                # 给 linux-2.6.25/ 下的源码打补丁

然后显示一串被补丁的文件,OK。(注意,如果是干净内核,应该不会提示任何是否覆盖已有patch之类的信息。如果出现这个,建议重新解压内核打补丁)
这是关键一步,建议仔细检查一下打补丁的目录是否是linux-2.6.25/下的文件!

 

 

下面准备编译内核,首先给内核加个后缀名,以便标识:
cd linux-2.6.25
# vi Makefile 在这个地方加上一个自定义的后缀(比如-PF_RING)
EXTRAVERSION = -PF_RING

 

配置并编译内核!(灰色指令是可选的)
make mrproper        # (不建议)清除以前编译的内核文件。因为是新解压的,保持原始状态就好,不建议用这个

make oldconfig     # 读取当前内核的配置(相当重要,这步能省好多配置工作,而且保证生成的.config能直接使用)
                     # 其间会提示 PF_RING xxxx [N/y/m/?] (NEW) ,注意按y选择把PF_RING给加进去,其他的选择按回车默认即可
                     # 不过注意,如果编译的内核版本较当前的新,会有很多(NEW)标记的提示,此时要是找不到PF_RING,建议先全部回车跳过

make menuconfig    # 如果之前把PF_RING也跳过了,这里可以进去重新选上

Networking --->

Networking options --->

PF_RING sockets (NEW)

这里按y选上PF_RING,然后保存修改到.config退出。
(PF_RING手册上说还要选上其他几个,不过我没找到... 应该默认是选上了)

6. Configure your kernel (2.4 and 2.6 are slightly different)
   - Enable RTIRQ (if you use it)
   - Enable 'Code maturity level options' 
             -
> ' Prompt for development and/or incomplete code/drivers'
   - Enable 'Networking options'
         -
> 'Socket Filtering'
         -
> 'PF_RING'
   - Change any other option you like
.

   NOTE: 
if you have a network card (e.g. Intel 1000) that supports NAPI, make
   sure you enable it as this will result in great performance
.

 

 

下面可以开始漫长的内核编译了(最好完整编译一次,直接make就行)
make                    # 相当于 make bzImage modules

(其间会提示几个警告,忽略之... 只要他还在继续往下编译,就放着不管好了

 

make modules_install  # 安装编译好的modules

make install           # 将bzImage添加到grub中,以便用新内核启动(注意,新添加的内核不是默认启动项)
(用 make install 可以免去手动复制bzImage并生成initrd的繁琐过程,推荐!)

 

等安装完成(不用重启),然后编译PF_RING自带的程序。首先复制 linux/ring.h 到include中

cd ../..                                                                        # 回到 PF_RING/ 下
cp kernel/include/linux/ring.h /usr/include/linux/
cp kernel/include/linux/ring.h /usr/include/                        # 有些地方说这里也要复制一个,感觉不需要

编译附带的源码和libpcap:

cd userland
make                             # 直接在userland下make,会自动编译子目录里的所有文件

安装pf_ring的 lib 和 libpcap-ring:
cd lib/
make install
=*= making library libpfring.so =*=
gcc -shared pfring.o -lpthread -o libpfring.so
cp libpfring.a /usr/local/lib/
cp libpfring.so /usr/local/lib/
cp pfring.h /usr/local/include/

cd ../libpcap-0.9.7-ring/
make install

 

OK,重启机器选新内核启动,就可以使用PF_RING来抓包了。


注意,刚启动机器时,ls /proc/net/pf_ring/ 是看不到这个目录的,只有当需要PF_RING的程序第一次运行时,才会生成这个目录以及一个info文件。之前因为死活找不到这个目录,还以为自己编的内核有问题又来了一次...

重启后这样测试 PF_RING:
cd /home/kernel/PF_RING/userland/examples

./pfcount                                          # 对应的还有一个 pcount,可以比较丢包率

注意运行 pfcount 和 pf_test 需要root权限,不然会提示 pfring_open error

 

另外查看dmesg或/var/log/messages,可以看到PF_RING的信息:

# dmesg | grep RING
[PF_RING] Welcome to PF_RING 3.9.3                              # 这一部分是PF_RING初始化时输出的
[PF_RING]  Ring slots       4096
[PF_RING]  Slot version     9
[PF_RING]  Capture TX       Yes [RX+TX]
[PF_RING]  IP Defragment    No
[PF_RING]  Initialized correctly
[PF_RING]  registered /proc/net/pf_ring/

[PF_RING]  successfully allocated 815104 bytes at 0xd0ad4000    # 以后每次运行PF_RING程序,会输出这样的调试信息
[PF_RING]  allocated 4115 slots [slot_len=198][tot_mem=815104]
[PF_RING]  removed /proc/net/pf_ring/2849-eth0.0

posted @ 2009-03-25 10:52  bits  阅读(4128)  评论(0编辑  收藏  举报