DPDK 报文调度/保序 终极解决方案 Event Dev 简介(硬件加速也很可能是鸿蒙微内核IPC性能的钥匙)...
01
背景介绍
网络报文的分发以及保序一直以来是让人头痛的问题, 为了完整的解释Event Dev的背景,我们可以从两个基本概念的定义开始:
报文分发是指针对网络通信报文的某种特征(例如 5 tuples)对网络报文进行分类以及对这个分类进行对应的特定处理。这种分类通常称为是flow, 例如 src ip, src port, dest ip, dest port, 一致的报文被认为是一个flow, 还可以更进一步提取特征来加强判断同一flow的条件, 例如协议类型, tunnel id 等等。
保序, 是指在包文处理过程中不改变原有的顺序, 大多数情况下可以弱化为在同一flow内的包文顺序不变。这里和协议倒不是非常相关。
首先最常见的包文分发技术是基于NIC 多队列的 Receive Side Scaling, NIC 首先根据算法对包文进行分类,然后尽可能平均的把不同flow放置到不同的接受队列中。RSS虽然解决了包文分发到多个cpu core的问题, 但是RSS并不了解哪个flow应该到哪个cpu core, 也无法通过配置解决, 同时RSS只能分发没有其它选择, 为了解决这个问题 Intel 引入了更进一步的方案 Flow Director, 通过Flow Director, NIC 不但可以分发包文还可以指定特定的flow到特定的cpu core,同时除了分发也可以选择drop 包文。要更加精准和灵活, 更多细节请参考 Flow Director Ref。
无论RSS/Flow Director 都可以分发/同一flow保序 但是很难满足更复杂的应用场景。在PIPELINE 处理模型中, 除了接受端分发以外, 每个节点处理后还会 二次, 三次, N次分发包文, 这下该怎么办 ?
如下图所示, 同一flow 4个包文开始分发, 1,3 进入一个路径, 2,4 进入一个路径, 因为没有任何锁来控制同步(性能考量) 所以在处理结束的时候包文的顺序以及打乱, 原因是在两个完全并行的路径上顺序是无法保证的, 最直接的想法就是引入一个reordering的功能节点, 当然代价是昂贵的, 同时在CPU core之间做包文的分发也是代价昂贵的操作。
02
CPU软件包调度
通过网卡来分发调度只能在接收端进行一次, 在更加复杂的PIPELINE模型中无法进一步进行调度, 所以非常直接的解决方案就是通过CPU 来对报文进行调度/保序, 一个高效的实现方案并不是显而易见的, 主要的困难在于两个方面:
如何高效的分发
如何高效的保序
DPDK的 组件 Packet Distributor 在这方面进行了有益的探索。
调度报文, 本质上就是CPU core之间的通信, X86的架构下 , CPU core 之间最高效的通信方式就是通过 L3 cache-line, 一个 cache-line 是64Byte, 也就是说 在一个cache-line中最多可以包含8个64bits指针,恰恰8个指针可以代表8个报文。Distributor Core 和 Worker Core 通过cache-line来通信, Distributor/Worker Core 通过首个报文的最低4位来判断读写的状态 (mbuf 默认都是 64Bytes 对齐, 所以低6位都是空余的可以用来表示状态), 如下图所示:
以下是状态位的定义(可左右滑动):
#define RTE_DISTRIB_NO_BUF 0 /**< empty flags: no buffer requested */
#define RTE_DISTRIB_GET_BUF (1) /**< worker requests a buffer, returns old */
#define RTE_DISTRIB_RETURN_BUF (2) /**< worker returns a buffer, no request */
其工作流程如下(引自dpdk.org), 不再赘述:
Distributor 作为纯软件报文分发确实做到了比较极致, 但是却没有完美的解决保序的要求, 依然需要引入 reorder buffer来重建报文顺序。同时如果worker core 是处理异步业务 Distributor core 也需要引入更加复杂的逻辑来应对。大家可以参考源代码: example/distributor/
03
终极形态
报文分发/保序的最终形态终于演化至Hardware实现 (i e基于CPU的软件方案在灵活性,性能上都遭遇了瓶颈)。当前的Hardware主要有两家厂商, NXP 和Cavium, 我们今天的讨论主要基于后者, 主要的原因是因为公开的资料比较全面。 Cavium eventdev HW 介绍
对于HW实现来说, 显而易见的是把分发/保序的工作分担给HW,从而节省CPU的计算资源。
核心的HW框架如下(引用自Cavium的资料):
蓝色的队列/粉色的调度器都是基于HW实现
每一个硬件的队列中包含若干的基于flow 划分的子队列, 每一个event会根据其相关flow最终插入到其中一个子队列
在event enqueue阶段, event的发送源需要显式地指定队列号,亦即,该event应该进入那个队列
之后调度器会根据 event 类型, event优先级, 队列类型等参数进行调度
在event dequeue 阶段 每一个worker cpu core 会polling对应的port, 获取event, 处理结束后需要指定下一阶段的queue id 等信息再enqueue回对应队列
有两个特殊的阶段是NIC RX/TX, RX 只有enqueue, 而TX 只有dequeue。理想情况下 RX/TX 可以做成inline 形式, 免去CPU 还需要polling NIC Ring
以下是简化的event定义, 前64位是 meta data, 后64位是mbuf的地址。Meta data中包含各种控制信息可以参考代码,这里不再赘述。(可左右滑动)
struct rte_event {
/** WORD0 */
union {
uint64_t event;
/** Event attributes for dequeue or enqueue operation */
};
/** WORD1 */
union {
struct rte_mbuf *mbuf;
/**< mbuf pointer if dequeued event is associated with mbuf */
};
};
报文调度主要有两种类型:
Atomic: 在特定时间点, 每一个flow 只有一个报文被调度到一个CPU进行处理, 从而保证处理过程中相关数据结构的原子性, 达到无锁处理的目标,可以简化应用设计.
Ordered: 在特定时间点, 每一个flow可以有多个报文被调度到多个CPU进行处理, 但是处理结束后报文的顺序没有变化.
下面结合EventDev HW 设计来描述一下一个报文的生命周期。首先来看下图:
网卡收到报文,填写好flowid ,queue id从而enqueue到queue 0
调度器HW根据入队的event flow id 和queue id将其分配至queue 0的flow0子队列
调度器根据Queue0和 Dequeue port 0 的链接状态, 将其分发到port0 出队
CPU 0 从port0 取出event 进行相关处理, 业务逻辑代码根据配置信息将event 转发到queue1, 填写好queue id后, 从port0 入队
调度器硬件根据queue id 这次将event分配到queue 1的flow0子队列
调度器根据queue 1和 port1 链接的状态, 将其分发到port1出队
CPU 1 从 port1 取出event 进行加密处理, 之后依旧从por1入队到队列, 但是指定event 类型为TX
调度器这次将根据事件类型将event分发至TX出队port, 从而发送
影响调度器行为的参数有:
flow id: event 所属的flow
queue id: event 入队时指定的队列id
event type: event的类型
queue type: 队列的分发属性
op type: event 是new/forward/release主要是指这个事件是新引入事件(例如RX),还是转发(node节点之间),还是释放(含异常处理)
结合下图可以更好的理解一下队列类型的影响:
Atomic 类型队列:
首先一个flow的event会保序进入queue 0的flow0 子队列, 调度器只会分发该flow的一个event到一个出队port, 在这个event被重新入队以前不会分发下一个event。
例如 e0 被分发到port0, 在e0被重新入队之前, e1,e2,e3都要等待。
Ordered 类型队列:
首先一个flow的event会保序进入queue 0 的flow0 子队列, 调度器会同时分发e0, e1, e2, e3 到多个port上。例如 e3 被分发到port0, e0 被分发到port1, e1被分发到port2, e2被分发到port3。
当e0,e1,e2,e3重新入队的时刻, HW会对其顺序重整。 保证对下一个阶段的处理是保序的。
在目录/driver/event/sw下, Intel 公司贡献了基于软件实现的eventdev-sw PMD。eventdev-sw PMD 和基于硬件实现的 eventdev PMD 在api 级别兼容, 功能上也基本一致。在/example/eventdev_pipeline_sw_pmd 目录下有基于eventdev-sw PMD的例子程序。这也是目前唯一upstream的 eventdev 例子程序, 非常有参考价值。
到这里, eventdev 的前世今生基本上已经讨论完毕。虽然event dev还是dpdk家族中相对新的组件, 但是我相信event dev最终会成为包处理业务的中流砥柱,不可或缺的一环。希望大家多提宝贵意见。
相关链接:
Receive Side Scaling (RSS):
https://docs.microsoft.com/en-us/windows-hardware/drivers/network/rss-with-hardware-queuing
Flow Director Ref:
https://www.intel.com/content/www/us/en/ethernet-products/converged-network-adapters/ethernet-flow-director.html
Cavium eventdev HW 介绍:
https://dpdksummit.com/Archive/pdf/2016USA/Day01-Session04-JerinJacob-DPDKUSASummit2016.pdf
作者简介:
马良,现为Intel工程师。毕业于中国科学技术大学,主要从事高速包处理,虚拟化以及应用密码学等领域的研究。
DPDK 报文调度/保序 终极解决方案 Event Dev 简介(硬件加速也很可能是鸿蒙微内核IPC性能的钥匙)...相关推荐
- DPDK报文转发(四)
基本的网络包处理主要包含: Packet input:报文输入. Pre-processing:对报文进行比较粗粒度的处理. Input classification:对报文进行较细粒度的分流. In ...
- Android大图片裁剪终极解决方案 原理分析
约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏 ...
- 依托北斗的同步终极解决方案
术语 1.1北斗卫星导航系统BeiDou navigation satellite system,BDS 中国正在实施的自主发展.独立运行的卫星导航系统(简称北斗),由空间段.地面段和用户段组成,具有 ...
- VPP线程之间报文调度
线程之间报文调度,首先需要初始化一个报文队列,如下调用函数vlib_frame_queue_main_init,返回值为新创建队列的索引值.首个参数为队列报文的接收节点索引,这里为:nat44-ed- ...
- 多项式回归、分位数回归(Quantile Regression)、保序回归(Isotonic Regression)、RANSAC回归、核岭回归、基准回归模型(baseline)
多项式回归.分位数回归(Quantile Regression).保序回归(Isotonic Regression).RANSAC回归.核岭回归.基准回归模型(baseline) 目录
- Pytorch 训练与测试时爆显存(cuda out of memory)的终极解决方案,使用cpu(勿喷)
Pytorch 训练与测试时爆显存(cuda out of memory)的终极解决方案,使用cpu(勿喷) 参见了很多方法,都没有用. 简单点,直接把gpu设成-1
- 分布式事务终极解决方案探讨
2019独角兽企业重金招聘Python工程师标准>>> 分布式事务终极解决方案探讨 转载于:https://my.oschina.net/dslcode/blog/1606115
- 静态页转换平台(StaticPol)-静态页生成终极解决方案
我本身非常不喜欢写文字材料,但是这个东西相信是很多人都需要的,把心得写出来和大家分享一下,也好让大家都努力PP,以助于尽快完善这个东东,早日贴出来供大家下载使用. 为什么要生成静态页? 这个问题咱们就 ...
- Flash中文字体嵌入终极解决方案
Flash中文字体嵌入终极解决方案 http://www.xiumu.org/technology/flash-chinese-characters-embedded-in-the-ultimate- ...
最新文章
- oracle rowid mysql_相当于Oracle的RowID在MySQL中
- 关于h5py的使用及数据封装实例
- linux 内存取证_【取证流程】电子数据证据远程勘验
- 【opencv】双目视觉下空间坐标计算/双目测距 6/13更新(转载)
- 【前端后端运维】Web开发人员学习路线,汇总整理
- 二维数组指针,指针数组与数组指针的区别,一看就懂
- 动态库和静态库的区别
- 构建自己企业的邮箱验证服务
- DELL电脑耳机插入没反应的解决办法
- SpringBoot 3.0最低版本要求的JDK 17,这几个新特性不能不知道
- Mac OS X: FileVault 2在美洲狮10.8上的扩展
- 图学习——04.HAN(异构图注意力网络)
- 一种基于深度学习的遥感图像分类及农田识别方法
- android可拖拽九宫格,微信小程序实现九宫格图片拖拽
- 武汉大学 计算机学院 曹瑀,武大计算机青协
- jmeter模拟需验签的请求时注意参数中含有特殊字符要特别处理
- ubuntu20.04如何安装搜狗输入法
- ClickHouse 分布式表创建细节
- Xilinx XCKU115 FPGA 加速卡
- ElGamal算法加解密