DPDK丢包那些事,如何解决?

摘要:本文来自博客园,作者:T-BARBARIANS,博文严禁转载,转载必究! 一、前言 DPDK技术原理相关的文章不胜枚举,但从实战出发,针对DPDK丢包这一类问题进行系统分析的文章还是凤毛麟角。 刚好最近几个月一直在做DPDK的相关性能优化,
本文来自博客园,作者:T-BARBARIANS,博文严禁转载,转载必究! 一、前言   DPDK技术原理相关的文章不胜枚举,但从实战出发,针对DPDK丢包这一类问题进行系统分析的文章还是凤毛麟角。   刚好最近几个月一直在做DPDK的相关性能优化,x86和arm平台都在做。在完整经历了发现问题、分析问题、解决问题的所有阶段后,回顾过去这段时间的来龙去脉,觉得可以将其将形成一篇技术文章,并予以分享。   优化目的只有一个:DPDK零丢包!   零丢包,谈何容易!在整个性能优化期间,查阅过大量资料;调整过大量参数;尝试过多种优化手段。相关的不相关的招都使过,很多时候都是无功而返,优化过程简直就是一个每天都想放弃的过程。   但是俗话说得好:只要功夫深,铁棒磨成针。对任何事物的认知必然是一个由浅入深的过程,DPDK也不例外。通过持续的尝试和总结,x86和国产化平台最后都收到了很好的效果。   接下来就吐血奉献过去一段时间的经历和思考,希望可以为大家提供一些参考和相关问题的解决思路。   篇幅较长,而且信息量有些大,完整阅读加理解大概需要30分钟。 二、背景与问题   与使用DPDK的大多数同行一样,我们也是通过DPDK获取数据面的大规模网络流量,在用户态将流量直接传递给某个应用,最终体现业务价值。   愿景很美好,现实很残酷,DPDK丢包了。 图1   在时间点 [18:02:48.073,18:02:48.100] 之间发生了丢包,丢包个数为:5867636 -5867597 = 39。这是在很短时间内的丢包数,情况严重时每秒成千上万个包被丢弃,应用层收到的报文残缺不全,这就没法玩了。 ··················上 篇·················· 一、x86平台优化经历   10Gbps线速网卡,流量也才在2Gbps---3Gbps之间,这也能丢包? (1)ring环长度尽可能大   各大平台搜索一通,公开的秘籍就是:给我把ring环加大!   ring环就是大家耳熟能详的DPDK无锁队列,收包ring环是DPDK收包流程里最底层的一个队列,直接与DMA打交道,用于存储DMA从网卡搬运至此的网络报文。   在我看来,加大ring环有两个作用,一是增加储存网络报文的容量;二是抗流量突发。   我们把ring环长度由1024干到了16384,同时增加了DPDK队列统计函数:rte_eth_rx_queue_count(uint16_t port_id, uint16_t queue_id),用于实时统计当前环形队列已使用的描述符个数,即ring环里当前驻留了有多少个未消费的数据包。 图2   加大ring环就不丢包了吗?把队列统计信息通过日志实时打印,继续观察。 图3   很明显,DPDK继续丢包。还丢包那我就继续加,但是DPDK收包ring环的设置是有上限的,uint16_t nb_rx_desc(The number of receive descriptors to allocate for the receive ring),表明DPDK最大可以将收包ring环设置为65535。 图4   还真设置过最大值,但是无济于事,继续丢包。说明在我们环境上增大ring环容量并不能解决全部问题。这时候陷入了僵局,是什么问题导致了丢包呢?   从图3我们可以看到一个现象,当ring环被打满时,才出现了imissed统计值增长。DMA往ring环里放数据,收包线程从ring环里取数据,现在ring环保持高水位,这充分说明了是上层收包线程未及时的将ring环里的数据包取走呀!根据这个重要线索,我们重新审视了与收包相关的应用层代码。 (2)线程任务尽可能轻量   业务流程逻辑可简化如下图所示。 图5   1、网络数据包通过DMA拷贝到ring1;   2、thread1负责从ring1里接收数据包,同时还要做一些其它任务,例如限速、过滤、数据包初始化等工作,最后将初始化后的描述符传递至ring2;   3、thread2从ring2里获取描述符,进行数据预取,协议解析(eth、ip、tcp、udp等等)等相关工作,最后通过hash算法将描述符散列到对应work线程的接收队列;   4、各work线程从对应的ring环里获取描述符,进行业务处理。   流程结构很清晰,各个线程被安排得明明白白。但是问题恰恰出现在看似没有问题的地方。
阅读全文