如何利用 mTCP 和 dpdk tcp协议栈构造千万百万并发TCP连接

8856人阅读
开发(166)
linux 相关(186)
网络(254)
http://www.dpdk.org/
Intel开源的x86平台上的报文处理套件。
Kernel &= 2.6.33
glibc &= 2.7
Kernel需要支持UIO、HUGETLBFS、PROC_PAGE_MONITOR
如果使用HPET支持, Kernel需要支持HPET和HPET_MMAP
如果使用HPET timer和电源管理(power management)功能, 需要设置BIOS
HUGETLBFS是指通过使用大的内存页, 减少TLB条目的数量, 提高TLB缓存的命中率, 提高了内存地址转换的效率,从而提高了内存的操作效率。
dpdk中用来存放报文的内存使用的就是HUGEPAGE
下载源码解压。按照doc/build-sdk-quick.txt指示编译,安装。
make config T=x86_64-default-linuxapp-gcc
DESTDIR=/opt/dpdk/
//编译过程中发现有个别结构体重复定义,注释掉就可以了
make install
T=x86_64-default-linuxapp-gcc DESTDIR=/opt/dpdk/
在另一个目录中编译:
make config T=x86_64-default-linuxapp-gcc
O=my_sdk_build_dir
然后在my_sdk_build_dir中直接make, 就在新的目录中完成了dpdk的编译
安装后在安装目录下生成两个目录:
//dpdk开发框架的的全套makefile
x86_64-default-linuxapp-gcc
//dpdk的头文件和对应架构下的链接库
到安装目录下找到kmod/igb_uio.ko kmod/rte_kni.ko
modprobe uio
insmod igb_uio.ko
运行前准备
在运行dpdk应用时需要准备的事项。
设置hugepages
系统启动前,通过内核参数分配内存:
// 分配1024个2M的页
hugepages=1024
// 分配4个1G的页, 64位应用推荐使用1G的页
default_hugepages=1G hugepagesz=1G hugepages=4
在系统运行的情况,通过修改/proc中参数分配:
// 分配24个2MB的页
echo 24 &/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
在系统运行时,直接mount挂载hugepages:
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
或者添加到添加到/etc/fstab中,启动时自动挂载:
nodev /mnt/huge hugetlbfs defaults 0 0
1GB的页需要指定页的大小
nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
加载内核模块
dpdk依赖uio, 提供了igb_uio.ko, 需要将这两个内核模块加载:
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
在dpdk编译后的目录中可以看到dpdk提供的驱动:
[root@localhost kmod]# ls
igb_uio.ko
rte_kni.ko
替换网卡的驱动
在dpdk对网卡的称呼是port, 就是网口。
dpdk的应用程序要使用某块网卡是,需要使用tools/pci_unbind.py将网卡绑定到驱动igb_uio。
依赖lspci命令
使用pci_unbind.py查看网卡状态:
[root@localhost tools]# ./pci_unbind.py --status
//查看网卡状态
Network devices using IGB_UIO driver
====================================
Network devices using kernel driver
===================================
.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth1 drv=e1000 unused=igb_uio *Active*
.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio
Other network devices
=====================
设置eth2使用igb_uio:
[root@localhost tools]# ./pci_unbind.py --bind=igb_uio eth2
//eth2绑定到驱动igb_uio
查看绑定后的网卡状态:
[root@localhost tools]# ./pci_unbind.py --status
//绑定后的网卡状态
Network devices using IGB_UIO driver
====================================
.0 '82545EM Gigabit Ethernet Controller (Copper)' drv=igb_uio unused=e1000
Network devices using kernel driver
===================================
.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth1 drv=e1000 unused=igb_uio *Active*
Other network devices
=====================
自动化工具
dpdk中提供了一个脚本(tools/setup.sh), 用于方便的编译以及设置运行环境.
[root@localhost dpdk-1.5.0r1]# source tools/setup.sh
------------------------------------------------------------------------------
RTE_SDK exported as /export/App/ads/dpdk/dpdk-1.5.0r1
------------------------------------------------------------------------------
----------------------------------------------------------
Step 1: Select the DPDK environment to build
----------------------------------------------------------
[1] i686-default-linuxapp-gcc
[2] i686-default-linuxapp-icc
[3] x86_64-default-linuxapp-gcc
[4] x86_64-default-linuxapp-icc
----------------------------------------------------------
Step 2: Setup linuxapp environment
----------------------------------------------------------
[5] Insert IGB UIO module
[6] Insert KNI module
[7] Setup hugepage mappings for non-NUMA systems
[8] Setup hugepage mappings for NUMA systems
[9] Display current Ethernet device settings
[10] Bind Ethernet device to IGB UIO module
使用其它特性
HPET需要BIOS支持:
Advanced-&PCH-IO Configuration -& High Precision Timer
可以从/proc/timer_list中查看HPET是否已经开启:
grep hpet /proc/timer_list
内核选项需要勾选HPET_MMAP
在Fedora、Ubuntu等发行版中, HPET_MMAP默认是disable的, 需要重新编译内核。
dpdk默认是不使用HPET的,因此还需要在dpdk的配置文件(源码config目录下)中设置支持HPET:
CONFIG_RTE_LIBEAL_USE_HPET=n
使用非Root身份运行
dpdk可以使用非root身份运行,需要设置好一下的目录或文件的所属:
hugepage挂在点:
userspace-io设备文件:
/dev/uio0 ...
如果使用HPET:
使用电源管理功能
需要在BIOS中启用Enhanced Intel SpeedStep Technology
Advanced-&Processor Configuration-&Enhanced Intel SpeedStep(R) Tech
还需要在BIOS中启用C3、C6
Advanced-&Processor Configuration-&Processor C3
Advanced-&Processor Configuration-& Processor C6
core isolation – 独占CPU核心
将dpdk应用绑定到特定的CPU上后, 这些CPU还是参与系统调度,承担系统的其它的任务。
可以通过配置Linux的内核参数使dpdk占用的CPU不参与调度,从而使dpdk应用独占CPU。
isolcpus=2,4,6
//核2, 4, 6不参与任务调度
Kernel NIC Interface
dpdk的示例程序中给出了一个KNI(Kernel NIC Interface)示例, 要使用该示例, 需要加载kni模块:
#insmod kmod/rte_kni.ko
这个模块和igb_uio.ko在一个目录,前面已经见过。
使用利用Intel VT-d的IOMMU Pass-Through
TODO: 对IOMMU不了解,这里是猜测
经查Passthrough I/O模型是指在客户机内部能够直接对硬件进行操作, Intel的支持技术叫做VT-d(Virtualization Technology for Directed I/O),AMD的支持技术叫做IOMMU(I/O Memory Management Unit)。这里涉及的应当是dpdk应用运行在虚拟机中的情形, 在虚拟机中的dpdk应用需要能够透过虚拟机直接访问设备硬件。
首先要启用Intel VT技术, 需要设置内核的编译选项:
IOMMU_SUPPORT
INTEL_IOMMU
运行时需要指定内核参数:
iommu = pt
如果编译的内核中没有设置INTEL_IOMMU_DEFAULT_ON, 还需要指定内核参数:
intel_iommu=on
TODO:这一节的内容还需要继续深挖, 特别是虚拟化相关的内容。
dpdk提供了一个统一的环境抽象层(EAL, Environmental Abstraction Layer), 这一层为dpdk应用提供了通用的统一的选项。
./rte-app -c COREMASK -n NUM [-b &domain:bus:devid.func&] [--socket-mem=MB,...]
[-m MB] [-r NUM] [-v] [--file-prefix] [--proc-type &primary|secondary|auto&] [--xen-dom0]
-c: coremask, 指定使用的CPU
-n: Num of memory channels per processor socket
-b: blacklisting of port
--use-device: 只是用指定的网卡, 与-b互斥
--socket-mem: 从每个socket上申请的hugepage内存的大小
-m: 从hugepage申请的内存的大小, 注意如果使用这个选项, 每个socket贡献的内存大小是不确定的
-r: Num of memory ranks
--huge-dir: hugetlbfs挂载位置
--file-prefix: the prefix text used for hugepage filenames
--proc-type: 进程类型
--xen-dom0: 在没有hugetlbfs的Xen Domain0上运行
--vmware-tsc-map: 使用vmware的TSC map代替native RDSTC
--base-virtaddr: 指定虚拟基址
这里涉及到两个内存相关的指标: channels和ranks, 含义不明!!TODO:
rte_eal是核心的基础库, rte_eal+libc是dpdk中其它的lib库的根基。
eal通过dpdk提供的igb_uio.ko或的设备信息,igb_uio是使用了内核的UIO特性, 可以在用户空间访问操作设备.
关于UIO: 参考
eal通过mmap将hugetlbfs映射到进程地址中, ring、buf等使用的内存都来自hugetlbfs
dpdk使用run-to-completion模式进行报文的处理。在进入Data Plane之前,事先将相关资源准备好, 然后作为一个执行单元直接在core上执行。
dpdk还提供了一种pipeline模式作为对run-to-completion模式的补充。pipleline模式中,cores之间通过ring传递报文或者消息,从而可以控制任务的执行阶段, 提高cores的利用率。
dpdk提供的编程的模型是并发的, 并发的数量与CPU的核数相关, 每个核上的执行单元是最小的并发单位。
使用dpdk开发的应用可以看做是多个单独的执行单元分别依附在各自的核心默默的跑着。
dpdk提供了ring等内存结构, 执行单元借助这些数据结构互相传递信息。
dpdk开发环境使用相当简单, 只需要指定两个环境变量RTE_SDK和RTE_TARGET, 和撰写一个dpdk的makefile即可。
通过环境变量指定SDK的路径和系统类型:
export RTE_SDK=/home/user/DPDK
//DPDK安装路径
export RTE_TARGET=x86_64-default-linuxapp-gcc
//系统类型
dpdk提供了一套的Makefile, 正是得益于这套Makefile, 开发环境才得以如此简单。在dpdk项目中需要撰写一个符合dpdk要求的Makefile。
dpdk的Makefile的详细可以使用参考《intel-dpdk-programmers-guide.pdf》 Part2 Development Environment
Hello World
这是dpdk自带的一个示例。
export RTE_SDK=/opt/dpdk-1.5
export RTE_TARGET=x86_64-default-linuxapp-gcc
也可以在Makefile中重置RTE_SDK, 例如在文件开始出添加一行:
export RTE_SDK=/export/App/ads/dpdk/dpdk-1.6.0r1
/root/dpdk-1.6.0r1/examples/helloworld
[root@localhost helloworld]# ls
项目的Makefile:
include $(RTE_SDK)/mk/DPDK.vars.mk
# binary name
APP = helloworld
#指定应用名称,编译得到的程序将会使用这个名字
# all source are stored in SRCS-y
SRCS-y := main.c
#指定源文件
CFLAGS += -O3
CFLAGS += $(WERROR_FLAGS)
include $(RTE_SDK)/mk/DPDK.extapp.mk
#include &main.h&
/***************** lcore_hello是每个执行单元的工作内容
******************/
static int
lcore_hello(__attribute__((unused)) void *arg)
unsigned lcore_
lcore_id = rte_lcore_id();
printf(&hello from core %u\n&, lcore_id);
MAIN(int argc, char **argv)
unsigned lcore_
ret = rte_eal_init(argc, argv);
if (ret & 0)
rte_panic(&Cannot init EAL\n&);
/*** 将工作内容下发到其它的执行单元 ***/
/* call lcore_hello() on every slave lcore */
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
rte_eal_remote_launch(lcore_hello, NULL, lcore_id);
/*** 当前执行单元的工作内容 ***/
/* call it on master lcore too */
lcore_hello(NULL);
/*** 等待所有的执行单元结束 ***/
rte_eal_mp_wait_lcore();
make O=`pwd`/../out
O=指定输出路径, 如果不指定默认是当前路径下的build目录
[root@localhost build]# ls -R
helloworld
helloworld.map
_postbuild
_postinstall
_preinstall
helloworld
helloworld.map
echo 24 &/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
sudo modprobe uio
sudo insmod kmod/igb_uio.ko
./helloworld -c 3 -n 1
[root@localhost build]# ./helloworld -c 7 -n 1
EAL: Detected lcore 0 as core 0 on socket 0
//CPU核心检测
EAL: Detected lcore 1 as core 1 on socket 0
EAL: Detected lcore 2 as core 2 on socket 0
EAL: Skip lcore 3 (not detected)
EAL: Skip lcore 63 (not detected)
EAL: Setting up memory...
EAL: Ask a virtual area of 0x2097152 bytes
EAL: Virtual area found at 0x7f056fe00000 (size = 0x200000)
EAL: Ask a virtual area of 0x2097152 bytes
EAL: Virtual area found at 0x7f056fa00000 (size = 0x200000)
EAL: Ask a virtual area of 0x bytes
EAL: Virtual area found at 0x7f056ec00000 (size = 0xc00000)
EAL: Ask a virtual area of 0x2097152 bytes
EAL: Virtual area found at 0x7f056e800000 (size = 0x200000)
EAL: Ask a virtual area of 0x2097152 bytes
EAL: Virtual area found at 0x7f056e400000 (size = 0x200000)
EAL: Requesting 10 pages of size 2MB from socket 0
EAL: TSC frequency is ~2459655 KHz
EAL: WARNING: cpu flags constant_tsc=yes nonstop_tsc=no -& using unreliable clock cycles !
EAL: Master core 0 is ready (tid=)
EAL: Core 2 is ready (tid=6d3fd700)
EAL: Core 1 is ready (tid=6dbfe700)
hello from core 1
//执行单元的工作结果
hello from core 0
hello from core 2
从运行结果的输出可以看到,启动时首先会检测设备的CPU核心数(检测0-63,如果存在就显示Core的位置), 然后申请内存等, Core就位后开始执行单元的执行。
首先到dpdk的安装目录下查看一下dpdk提供的内容:
[root@localhost dpdk-1.5]# ls
x86_64-default-linuxapp-gcc
其中mk目录下dpdk提供的一套makefile, 在这些makefile的辅助下, 项目的顶层Makefile变得非常整洁。
x86_64-default-linuxapp-gcc对应平台上的开发接口。
[root@localhost x86_64-default-linuxapp-gcc]# ls
编译得到dpdk的应用程序
include: dpdk对外提供的接口文件(.h文件)
dpdk的相关内核模块
dpdk的静态库文件(.a)
这里关心的是include目录中的.h文件中都提供了哪些接口, 分别作什么用途。intel-dpdk-programmers-guide.pdf做了分类说明。
详细内容可以查看
dpdk提供了对网卡进行操作的接口, 关于网卡的知识可以从这里获取Intel官网上获取。
rte_eal_init(int argc, char **argv)
//EAL的初始化,在master core上运行
rte_pmd_init_all
rte_eal_pci_probe
rte_lcore_count
rte_eth_dev_count
rte_eth_macaddr_get
rte_eth_dev_configure
//设置网卡的接收队列和发送队列数目, 以及硬件特性
rte_lcore_is_enabled
rte_lcore_to_socket_id
rte_mempool_create
rte_eth_tx_queue_setup
rte_eth_rx_queue_setup
rte_eth_dev_start
rte_eth_promiscuous_enable
rte_eth_link_get_nowait
rte_ring_create
rte_eal_mp_remote_launch
rte_lcore_id
rte_ring_dequeue_burst
rte_pktmbuf_mtod
rte_eth_rx_burst
rte_prefetch0
rte_be_to_cpu_16
rte_jhash_2words
rte_ring_enqueue
RTE_PER_LCORE
《intel-dpdk-programmers-guide.pdf》给出了一些性能优化建议
在data plane操作内存的时候, 使用dpdk的api, 不要使用libc
例如: rte_memcpy – memcpy rte_malloc – malloc
降低cache miss
通过使用RTE_PER_LCORE
均衡Memory Channels
使用dpdk ring进行核间通信
Poll Mode Driver (PMD)
低延迟与高吞吐之间的延迟
控制每次轮询网卡时处理的报文的数量
锁和原子操作
在data plane避免使用锁
使用per-lcore variables 使用RCU算法替代rwlocks
使用inline函数
使用分支预测
if (likely(x&1)) XXXX;
设置CPU类型
dpdk支持对特定的CPU架构进行优化
通过CONFIG_RTE_MACHINE指定CPU特性
对虚拟化的支持
DPDK对虚拟化提供了比较全面的支持。可以用于虚拟机中。
对比pf_ring
直观感觉,dpdk的定位是sdk, 提供了更多的支持库, 自成体系, 绑定在intel平台上。pf_ring定位是高效的抓包工具, 支持的硬件更多一些。
intel-dpdk-programmers-guide.pdfintel-dpdk-getting-started-guide.pdf
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:588324次
积分:7630
积分:7630
排名:第2006名
原创:61篇
转载:806篇
评论:24条
(1)(1)(4)(1)(4)(1)(1)(10)(1)(1)(4)(2)(3)(5)(16)(16)(11)(38)(12)(21)(18)(7)(18)(6)(8)(2)(4)(10)(4)(9)(11)(4)(8)(7)(55)(51)(23)(69)(49)(74)(42)(59)(51)(23)(40)(3)(3)(2)(12)(7)(36)博客访问: 77579
博文数量: 28
博客积分: 66
博客等级: 民兵
技术积分: 142
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 网络与安全
原文地址: 作者:
是一个基于Intel DPDK 和LuaJIT开源技术,高度灵活的高速网络包生成器, 在一个单一CPU上运行用户编写的Lua script,
对于64 byte大小的网络包,可达到10 Gbit/s线速。 下面分享一下MoonGen 用户Lua script编写运行实列如SYN
flooding, DNS flooding。
MoonGen 设计原理
1 五百万线速DNS flooding
MoonGen Master script 负责初始化DPDK传输网络端口, 源地址,线速。调用slave script LoadSlave.
7&function&master(txPorts,&minIp,&numIps,&rate)
&&8&&&&&&&&&if&not&txPorts&then
&&9&&&&&&&&&&&&&&&&&printf("usage:&txPort1[,txPort2[,...]]&[minIP&numIPs&rate]")
&10&&&&&&&&&&&&&&&&&return
&11&&&&&&&&&end
&12&&&&&&&&&txPorts&=&tostring(txPorts)
&13&&&&&&&&&minIp&=&minIp&or&"10.0.0.1"
&14&&&&&&&&&numIps&=&numIps&or&100
&15&&&&&&&&&rate&=&rate&or&0
&16&&&&&&&&&for&currentTxPort&in&txPorts:gmatch("(%d+),?")&do
&17&&&&&&&&&&&&&&&&&currentTxPort&=&tonumber(currentTxPort)
&18&&&&&&&&&&&&&&&&&local&txDev&=&device.config({&port&=&currentTxPort&})
&19&&&&&&&&&&&&&&&&&txDev:wait()
&20&&&&&&&&&&&&&&&&&txDev:getTxQueue(0):setRate(rate)
&21&&&&&&&&&&&&&&&&&dpdk.launchLua("loadSlave",&currentTxPort,&0,&minIp,&numIps)
&22&&&&&&&&&end
&23&&&&&&&&&dpdk.waitForSlaves()
LoadSlave script 可初始化目标地址,hard code DNS协议包,也可在while 主循环里随机DNS
26&function&loadSlave(port,&queue,&minA,&numIPs)
&27&&&&&&&&&---&parse&and&check&ip&addresses
&29&&&&&&&&&local&minIP,&ipv4&=&parseIPAddress(minA)
&30&&&&&&&&&if&minIP&then
&31&&&&&&&&&&&&&&&&&printf("INFO:&Detected&an&%s&address.",&minIP&and&"IPv4"&or&"IPv6")
&32&&&&&&&&&else
&33&&&&&&&&&&&&&&&&&errorf("ERROR:&Invalid&minIP:&%s",&minA)
&34&&&&&&&&&end
&36&&&&&&&&&--&min&TCP&packet&size&for&IPv6&is&74&bytes&(+&CRC)
&37&&&&&&&&&--local&packetLen&=&ipv4&and&60&or&74
&38&&&&&&&&&local&packetLen&=&ipv4&and&86&or&60
&40&&&&&&&&&--continue&normally
&41&&&&&&&&&local&queue&=&device.get(port):getTxQueue(queue)
&42&&&&&&&&&local&mem&=&memory.createMemPool(function(buf)
&43&&&&&&&&&&&&&&&&&buf:getUdpPacket(ipv4):fill{
&44&&&&&&&&&&&&&&&&&&&&&&&&&ethSrc="a0:36:9f:a1:4d:6d",&ethDst="52:54:00:2E:62:A2",
&45&&&&&&&&&&&&&&&&&&&&&&&&&ip4Dst="10.9.3.6",
&46&&&&&&&&&&&&&&&&&&&&&&&&&ip6Dst="fd06::1",
&47&&&&&&&&&&&&&&&&&&&&&&&&&udpDst="53",
&48&&&&&&&&&&&&&&&&&&&&&&&&&udpSrc="1029",
&49&&&&&&&&&&&&&&&&&&&&&&&&&pktLength=packetLen&}
&51&&&&&&&&&&&&&&&&&local&pkt&=&buf:getUdpPacket(ipv4)
&53&&&&&&&&&&&&&&&&&pkt.payload.uint16[1]&=&8193
&55&&&&&&&&&&&&&&&&&pkt.payload.uint16[2]&=&256
&58&&&&&&&&&&&&&&&&&pkt.payload.uint16[3]&=&0
&60&&&&&&&&&&&&&&&&&pkt.payload.uint16[4]&=&0
&62&&&&&&&&&&&&&&&&&pkt.payload.uint16[5]&=&256
&64&&&&&&&&&&&&&&&&&pkt.payload.uint16[6]&=&30467
&66&&&&&&&&&&&&&&&&&pkt.payload.uint16[7]&=&30583
&68&&&&&&&&&&&&&&&&&pkt.payload.uint16[8]&=&25863
&70&&&&&&&&&&&&&&&&&pkt.payload.uint16[9]&=&24952
&73&&&&&&&&&&&&&&&&&pkt.payload.uint16[10]&=&28781
&76&&&&&&&&&&&&&&&&&pkt.payload.uint16[11]&=&25964
&78&&&&&&&&&&&&&&&&&pkt.payload.uint16[12]&=&25347
&80&&&&&&&&&&&&&&&&&pkt.payload.uint16[13]&=&28015
&82&&&&&&&&&&&&&&&&&pkt.payload.uint16[14]&=&0
&84&&&&&&&&&&&&&&&&&pkt.payload.uint16[15]&=&1
&86&&&&&&&&&&&&&&&&&pkt.payload.uint16[16]&=&1
&88&&&&&&&&&&&&&&&&&pkt.payload.uint16[17]&=&10496
&90&&&&&&&&&&&&&&&&&pkt.payload.uint16[18]&=&16
&91&&&&&&&&&&&&&&&&&pkt.payload.uint16[19]&=&0
&92&&&&&&&&&&&&&&&&&pkt.payload.uint16[20]&=&0
&93&&&&&&&&&&&&&&&&&pkt.payload.uint16[21]&=&0
&95&&&&&&&&&end)
&97&&&&&&&&&local&lastPrint&=&dpdk.getTime()
&98&&&&&&&&&local&totalSent&=&0
&99&&&&&&&&&local&lastTotal&=&0
100&&&&&&&&&local&lastSent&=&0
101&&&&&&&&&local&bufs&=&mem:bufArray(128)
102&&&&&&&&&local&counter&=&0
103&&&&&&&&&local&c&=&0
105&&&&&&&&&local&txStats&=&stats:newDevTxCounter(queue,&"plain")
106&&&&&&&&&while&dpdk.running()&do
107&&&&&&&&&&&&&&&&&--&faill&packets&and&set&their&size
108&&&&&&&&&&&&&&&&&bufs:alloc(packetLen)
109&&&&&&&&&&&&&&&&&for&i,&buf&in&ipairs(bufs)&do
110&&&&&&&&&&&&&&&&&&&&&&&&&local&pkt&=&buf:getUdpPacket(ipv4)
112&&&&&&&&&&&&&&&&&&&&&&&&&--increment&IP
113&&&&&&&&&&&&&&&&&&&&&&&&&if&ipv4&then
114&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip4.src:set(minIP)
115&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip4.src:add(counter)
116&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--random&udp&source&port
117&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.udp.src&=&math.random(0,&2^16&-&1)
118&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--&random&dns&query&id
119&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.payload.uint16[0]&=&math.random(0,&2^16&-&1)
163&&&&&&&&&&&&&&&&&&&&&&&&&else
164&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip6.src:set(minIP)
165&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip6.src:add(counter)
166&&&&&&&&&&&&&&&&&&&&&&&&&end
167&&&&&&&&&&&&&&&&&&&&&&&&&counter&=&incAndWrap(counter,&numIPs)
169&&&&&&&&&&&&&&&&&&&&&&&&&--&dump&first&3&packets
170&&&&&&&&&&&&&&&&&&&&&&&&&if&c&<&3&then
171&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&buf:dump()
172&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&c&=&c&+&1
173&&&&&&&&&&&&&&&&&&&&&&&&&end
174&&&&&&&&&&&&&&&&&end
175&&&&&&&&&&&&&&&&&--offload&checksums&to&NIC
176&&&&&&&&&&&&&&&&&bufs:offloadUdpChecksums(ipv4)
178&&&&&&&&&&&&&&&&&totalSent&=&totalSent&+&queue:send(bufs)
179&&&&&&&&&&&&&&&&&txStats:update()
180&&&&&&&&&end
181&&&&&&&&&txStats:finalize()
运行实列:
#build/MoonGen examples/dns-flood-victoria.lua 0 10.0.0.1 00
4.5百万线速包
Device: id=0] Sent
packets, current rate 4.51 Mpps, 3246.01 MBit/s, 3967.35 MBit/s wire rate.&
测试目标CPU使用状况
没有硬件加速情况下的CPU使用状况 (~100%)
top - 12:07:02 up 1 day, 20:38, &1 user, &load average: 5.22, 7.46, 9.27
&Tasks: 777 total, &19 running, 758 sleeping, & 0 stopped, & 0 zombie
&Cpu(s): 50.6%us, 40.2%sy, &0.0%ni, &9.2%id, &0.0%wa, &0.0%hi, &0.0%si, &0.0%st
&Mem: &k total, k used, & 357644k free, & 108700k buffers
&Swap: &5242872k total, & & & &0k used, &5242872k free, &4048612k cached
& &PID USER & & &PR &NI &VIRT &RES &SHR S %CPU %MEM & &TIME+ &COMMAND
&17859 root & & & 1 -19 57.9g 145m 123m R 100.8 &0.2 &56:44.33 tmm.0 -T 10 --tmid
硬件加速情况下的CPU使用状况 (~12%)
top - 14:51:05 up &3:30, &1 user, &load average: 0.12, 0.05, 0.01
Tasks: 771 total, & 1 running, 770 sleeping, & 0 stopped, & 0 zombie
Cpu(s): &4.2%us, &0.5%sy, &0.0%ni, 95.2%id, &0.0%wa, &0.1%hi, &0.0%si, &0.0%st
Mem: &k total, k used, &2985784k free, & &61152k buffers
Swap: &5242876k total, & & & &0k used, &5242876k free, &1352852k cached
& PID USER & & &PR &NI &VIRT &RES &SHR S %CPU %MEM & &TIME+ &COMMAND
&6428 root & & & 1 -19 58.4g 151m 122m S 12.6 &0.2 & 3:19.62 tmm.0
由此可以看出,没有硬件加速的DNS 服务器是不能处理这样每秒千百万网络包的DNS flooding 的
2 七百万线速SYN& flooding
用户Lua script如下
&26&function&loadSlave(port,&queue,&minA,&numIPs)
&29&&&&&&&&&local&minIP,&ipv4&=&parseIPAddress(minA)
&30&&&&&&&&&if&minIP&then
&31&&&&&&&&&&&&&&&&&printf("INFO:&Detected&an&%s&address.",&minIP&and&"IPv4"&or&"IPv6")
&32&&&&&&&&&else
&33&&&&&&&&&&&&&&&&&errorf("ERROR:&Invalid&minIP:&%s",&minA)
&34&&&&&&&&&end
&37&&&&&&&&&local&packetLen&=&ipv4&and&60&or&74
&40&&&&&&&&&local&queue&=&device.get(port):getTxQueue(queue)
&42&&&&&&&&&local&mem&=&memory.createMemPool(function(buf)
&43&&&&&&&&&&&&&&&&&buf:getTcpPacket(ipv4):fill{
&45&&&&&&&&&&&&&&&&&&&&&&&&&ethSrc="a0:36:9f:a1:4d:6d",&ethDst="00:50:DA:CA:CB:17",
&47&&&&&&&&&&&&&&&&&&&&&&&&&ip4Dst="10.9.3.6",
&48&&&&&&&&&&&&&&&&&&&&&&&&&ip6Dst="fd06::1",
&49&&&&&&&&&&&&&&&&&&&&&&&&&tcpDst="80",
&51&&&&&&&&&&&&&&&&&&&&&&&&&tcpSyn=1,
&53&&&&&&&&&&&&&&&&&&&&&&&&&tcpSeqNumber=1,
&54&&&&&&&&&&&&&&&&&&&&&&&&&tcpWindow=10,
&55&&&&&&&&&&&&&&&&&&&&&&&&&pktLength=packetLen&}
&56&&&&&&&&&end)
&58&&&&&&&&&local&lastPrint&=&dpdk.getTime()
&59&&&&&&&&&local&totalSent&=&0
&60&&&&&&&&&local&lastTotal&=&0
&61&&&&&&&&&local&lastSent&=&0
&62&&&&&&&&&local&bufs&=&mem:bufArray(128)
&63&&&&&&&&&local&counter&=&0
&64&&&&&&&&&local&c&=&0
&66&&&&&&&&&local&txStats&=&stats:newDevTxCounter(queue,&"plain")
&67&&&&&&&&&while&dpdk.running()&do
&68&&&&&&&&&&&&&&&&&--&faill&packets&and&set&their&size
&69&&&&&&&&&&&&&&&&&bufs:alloc(packetLen)
&70&&&&&&&&&&&&&&&&&for&i,&buf&in&ipairs(bufs)&do
&71&&&&&&&&&&&&&&&&&&&&&&&&&local&pkt&=&buf:getTcpPacket(ipv4)
&74&&&&&&&&&&&&&&&&&&&&&&&&&if&ipv4&then
&75&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip4.src:set(minIP)
&76&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip4.src:add(counter)
&77&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&--random&source&port
&78&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.tcp.src&=&math.random(0,&2^16&-&1)
&79&&&&&&&&&&&&&&&&&&&&&&&&&else
&80&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip6.src:set(minIP)
&81&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pkt.ip6.src:add(counter)
&82&&&&&&&&&&&&&&&&&&&&&&&&&end
&83&&&&&&&&&&&&&&&&&&&&&&&&&counter&=&incAndWrap(counter,&numIPs)
&86&&&&&&&&&&&&&&&&&&&&&&&&&if&c&<&3&then
&87&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&buf:dump()
&88&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&c&=&c&+&1
&89&&&&&&&&&&&&&&&&&&&&&&&&&end
&90&&&&&&&&&&&&&&&&&end
&92&&&&&&&&&&&&&&&&&bufs:offloadTcpChecksums(ipv4)
&94&&&&&&&&&&&&&&&&&totalSent&=&totalSent&+&queue:send(bufs)
&95&&&&&&&&&&&&&&&&&txStats:update()
&96&&&&&&&&&end
&97&&&&&&&&&txStats:finalize()
#build/MoonGen examples/l3-tcp-syn-flood.lua 0 10.0.0.1 00
~每秒七百万网络包
&[Device: id=0] Sent 7061632 packets, current rate 7.06 Mpps, 3615.47 MBit/s, 4745.31 MBit/s wire rate
测试目标CPU 使用状态
无硬件加速的syncookie 处理时CPU使用 (~70%)
top - 10:53:51 up 42 min, &1 user, &load average: 0.24, 0.23, 0.65
769 total, &10 running, 759 sleeping, & 0 stopped, & 0 zombie Cpu(s):
35.4%us, &1.7%sy, &0.1%ni, 62.9%id, &0.0%wa, &0.0%hi, &0.0%si, &0.0%st
Mem: &k total, k used, &3339676k free, & &45784k buffers
Swap: &5242872k total, & & & &0k used, &5242872k free, &1199508k cached
& PID USER & & &PR &NI &VIRT &RES &SHR S %CPU %MEM & &TIME+ &COMMAND
19290 root & & & 1 -19 57.9g 145m 123m R 71.5 &0.2 & 0:14.38 tmm.0 -T 10 --tmid&
硬件加速的syncookie 处理时CPU使用 (~3%)
&top - 10:50:08 up 38 min, &1 user, &load average: 0.06, 0.36, 0.81
&Tasks: 769 total, & 1 running, 768 sleeping, & 0 stopped, & 0 zombie
&Cpu(s): &0.8%us, &0.2%sy, &0.0%ni, 98.5%id, &0.5%wa, &0.0%hi, &0.0%si, &0.0%st
&Mem: &k total, k used, &3339824k free, & &45324k buffers
&Swap: &5242872k total, & & & &0k used, &5242872k free, &1199492k cached
& &PID USER & & &PR &NI &VIRT &RES &SHR S %CPU %MEM & &TIME+ &COMMAND
&19267 root & & & 1 -19 57.9g 145m 123m S &3.6 &0.2 & 0:11.87 tmm
由此,没有硬件加速的syncookie处理,一般的服务器很难处理千百万极的syn flooding
阅读(729) | 评论(0) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。

我要回帖

更多关于 mtcp dpdk 的文章

 

随机推荐