背景
以前在一次DNS压力测试中,尝试用DPDK撰写了一个DNS的压力测试工具,难度不大,直接用DPDK的SAMPLE 和一个DNS发包程序的源码糅合在一起即可,测试效果还行,代码写的很渣,但是能用,可以把被测试设备的性能打到极限。
如何搭建DPDK编译环境可以在dpdk官网可以找到,本文完整的linux源码在下面的github地址,包含eclipse环境配置
[https://github.com/Linjian139/dpdk_dns_flood/blob/master/main.c]
关键点
由于dpdk直接使用底层发包,从mac->ip->udp,需要自己构造每一层次的报文头和报文体,代码包含若干结构体和构造方法,关键结构体包含:
struct DNS_HEADER
struct QUESTION
struct R_DATA
struct RES_RECORD
struct ADD_RECORDS
主要的数据包构造方法:
void build_udp_mac_header
void build_dns_header
另外checksum也要自己做(根据文档DKDP似乎是可以直接用硬件功能进行checksum的,不过我没弄成功)
代码要点
主要函数包含main函数和循环发送数据包的main_loop
static int main_loop(__attribute__((unused)) void *arg)
{
const unsigned lcore_id = rte_lcore_id();
char argv_2[] ="172.16.1.252"; //目标被测试设备的入口IP地址
const char *question=arg_query;//查询的域名
char argv_1[] ="10.128.10.";//本机地址段,该程序从这个段然后根据lcore id生成的真实ip地址
......
if (unlikely(udphdr_ptr->source>=65534))
{
iphdr_ptr->ip_src.s_addr++;
iphdr_ptr->ip_sum=0;
iphdr_ptr->ip_sum=cksum(iphdr_ptr,20);
udphdr_ptr->source= base_port;
}else
{
udphdr_ptr->source++;//此处会变换端口
}
.....
}
main_loop中构造数据包
main.c中初始化RTE环境参数,检查对应dev,这些都可以用dpdk官方sample代码中找到,最后调用main_loop执行死循环发送DNS数据包
rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER);
如何执行
Usage 信息是准的:
PRINT_INFO("\nUsage: %s [EAL options] -- -p PORTMASK -i IN_CORES -o OUT_CORES\n"
" -p PORTMASK: hex bitmask of ports to use\n"
" -o OUT_CORES: hex bitmask of cores which write to NIC",
prgname);
在DKDP环境中使用bitmask的方式指定使用那张网卡执行,可以使用DPDK的自带的工具查看哪些网卡可用,用网卡在dpdk的序号映射为bitmask进行指定。
效果和感想
坏处:
DPDK使用感想是三个字:”真费电“,一启动啥都不干,cpu直接原地爆炸到100%,DPDK 2.1版本中只能通过intel的cpu节能技术把频率降低,达到业务闲时降低能耗的效果,不知道新版本会不会好点,但是感觉从poll mode driver的实现角度说,也只有这样。
好处:
用DPDK没有soft irq的瓶颈,不会像nginx一样数据包多的时候会造成大量的soft irq,nginx还是依赖linux本身的协议栈,哪怕是走了epoll,数据包的后半处理还是要用软中断通知cpu执行TCP部分的后半,然后从TCP再走epoll的callback直接调用挂在socket的nginx方法
因为直接从net dev的buff拿数据到userspace,又是死循环模式,处理延迟很低,可以适配一些低延迟场景
现在也有用dpdk直接实现多核tcp协议的,比如mTCP,国内也有一些实现,不过17年后国内那个项目没有在更新了,感觉mTCP 14年开始兴起,17年慢慢就冷了,大约在14年普林斯顿大学有一篇相关的论文:
mTCP: A Highly Scalable User-level TCP Stack for Multicore Systems
里面有过一些测试,在高压力场景下,可以看到内核消耗了大量的资源,通过dpdk可以把cpu cycle更多的给到应用,而不是消耗在软中断和从kernel space 到user space的memcpy:
测试效果
在使用F5 5200V ,wideip进行解析,round robin算法下,一台服务器使用两个core,一个千兆网卡,可以打出100万RPS并成功解析,此时F5 5200V CPU为100%,解析率100%:
DNS RPS 1M+:
每秒新建1M+:
F5 5200 CPU 100%:
感觉帮客户省了一笔租IXIA的钱,但也没到我兜里 :P
下一篇写源进源出在linux kernel中如何通过魔改实现
魔改一时爽,一直魔改一直爽