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性能的钥匙)...相关推荐

  1. DPDK报文转发(四)

    基本的网络包处理主要包含: Packet input:报文输入. Pre-processing:对报文进行比较粗粒度的处理. Input classification:对报文进行较细粒度的分流. In ...

  2. Android大图片裁剪终极解决方案 原理分析

    约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏 ...

  3. 依托北斗的同步终极解决方案

    术语 1.1北斗卫星导航系统BeiDou navigation satellite system,BDS 中国正在实施的自主发展.独立运行的卫星导航系统(简称北斗),由空间段.地面段和用户段组成,具有 ...

  4. VPP线程之间报文调度

    线程之间报文调度,首先需要初始化一个报文队列,如下调用函数vlib_frame_queue_main_init,返回值为新创建队列的索引值.首个参数为队列报文的接收节点索引,这里为:nat44-ed- ...

  5. 多项式回归、分位数回归(Quantile Regression)、保序回归(Isotonic Regression)、RANSAC回归、核岭回归、基准回归模型(baseline)

    多项式回归.分位数回归(Quantile Regression).保序回归(Isotonic Regression).RANSAC回归.核岭回归.基准回归模型(baseline) 目录

  6. Pytorch 训练与测试时爆显存(cuda out of memory)的终极解决方案,使用cpu(勿喷)

    Pytorch 训练与测试时爆显存(cuda out of memory)的终极解决方案,使用cpu(勿喷) 参见了很多方法,都没有用. 简单点,直接把gpu设成-1

  7. 分布式事务终极解决方案探讨

    2019独角兽企业重金招聘Python工程师标准>>> 分布式事务终极解决方案探讨 转载于:https://my.oschina.net/dslcode/blog/1606115

  8. 静态页转换平台(StaticPol)-静态页生成终极解决方案

    我本身非常不喜欢写文字材料,但是这个东西相信是很多人都需要的,把心得写出来和大家分享一下,也好让大家都努力PP,以助于尽快完善这个东东,早日贴出来供大家下载使用. 为什么要生成静态页? 这个问题咱们就 ...

  9. Flash中文字体嵌入终极解决方案

    Flash中文字体嵌入终极解决方案 http://www.xiumu.org/technology/flash-chinese-characters-embedded-in-the-ultimate- ...

最新文章

  1. oracle rowid mysql_相当于Oracle的RowID在MySQL中
  2. 关于h5py的使用及数据封装实例
  3. linux 内存取证_【取证流程】电子数据证据远程勘验
  4. 【opencv】双目视觉下空间坐标计算/双目测距 6/13更新(转载)
  5. 【前端后端运维】Web开发人员学习路线,汇总整理
  6. 二维数组指针,指针数组与数组指针的区别,一看就懂
  7. 动态库和静态库的区别
  8. 构建自己企业的邮箱验证服务
  9. DELL电脑耳机插入没反应的解决办法
  10. SpringBoot 3.0最低版本要求的JDK 17,这几个新特性不能不知道
  11. Mac OS X: FileVault 2在美洲狮10.8上的扩展
  12. 图学习——04.HAN(异构图注意力网络)
  13. 一种基于深度学习的遥感图像分类及农田识别方法
  14. android可拖拽九宫格,微信小程序实现九宫格图片拖拽
  15. 武汉大学 计算机学院 曹瑀,武大计算机青协
  16. jmeter模拟需验签的请求时注意参数中含有特殊字符要特别处理
  17. ubuntu20.04如何安装搜狗输入法
  18. ClickHouse 分布式表创建细节
  19. Xilinx XCKU115 FPGA 加速卡
  20. ElGamal算法加解密

热门文章

  1. 阿里巴巴Java开发手册个人总结
  2. citra 图形设置_「图形化编程」前导知识-数组(四)
  3. 【数智化人物展】鸿翼CTO罗永秀:以ECM企业内容管理点燃数智未来
  4. 解读《阿里巴巴 Java 开发手册》背后的思考
  5. BSGS(基础篇,题目+详解)
  6. unity飞行模拟游戏源码,支持安卓+IOS双端 unity2019 C#语言开发
  7. jQuery设置网页全屏功能
  8. 卷积物理意义的超强解释
  9. MATLAB图像二值化
  10. java -p_说说javap命令