专栏
天翼云开发者社区

VPP概要

2024-04-17 14:28:59 21阅读

前言

通信本质是信号的传递,如声音、烽火狼烟、电话电报、数据网络等;具备信息源、信息通道、信息接受者;可以是实时的或跨时空的;可以是单向的或双向的或多向的;可以是定向的或无向的。但通信离不开介质,那怕量子纠缠,也跳不过物质;毕竟一切在物质世界的显化都需要以物质作为主导,同时需要能量参与其中。

这一过程可以称之为“编程”(自从GPT、Sora诞生,貌似整个世界的活动都可程序化/数字化),即通信编程。将物质或能量按照一定的规则进行编码、解码,可以理解为对物质和能量的雕刻-Coding。

这里Coding泛指硬件的或软件的,大多数时候两者是相辅相成的,硬件好比建设公路桥梁,软件好比在其上运行的车辆。但对通信而言,通信线缆、基站、网卡、网桥、路由交换是基础硬件;软件则是在其上运行的包协议栈。但自从网络IP化之后, 这种通用通信模型加速了网络的互联,协议栈基本被TCP/IP所替代。

VPP是来自于FDIO社区的一种高性能TCP/IP协议栈,由Cisco主导,其聚焦L2/L3转发,富含包括BD、ACL、NAT、PBR等功能。VPP基于指令级和调度级批处理机制、结合用户态IO技术,使用通用服务器即可实现网络数据包的线速转发。

矢量框架

报文处理不中断,且流速线型可谓之矢量。VPP如何保证处理的矢量性?针对VPP代码分析,个人认为主要从这些点:

  • 用户态IO Polling技术: VPP使用DPDK库,直接在用户态轮询网卡数据,绕过了内核及网卡中断。Polling实现了报文的批量接收,是报文批量处理的前提。
  • Node级批量调度: VPP在于业务组织逻辑,相同的业务Frame置于同一个Node,并在调度层面展开Node级调度,实现了业务的批量处理。使L3 Cache得到了最大化利用,这是框架级优化。
  • Node内指令级批量:Node内逻辑使用了多个包的同质化处理,即并行编程,使L1-L2 Cache得到最大化利用。
  • CPU指令流水线利用:指令级访存预取优化,对未来数据进行并行预取,缩短访存时间。
  • 多队列多线程:VPP基于网卡多队列实现了多Worker并行无锁转发。
  • 快慢分离:基于核间无损包Handoff技术,实现快任务和慢任务分离。
  • 快转加速:部分业务实现了基于flow的快转支持。

DPDK

DPDK,数据面开发套件,支持包括UIO、VirtIO、MemIF、mbuf等工具库,覆盖了大多数网卡的UIO及零拷贝实现。可见,DPDK具备了丰富手IO开发套件,但其在协议处理上较弱,而VPP的协议处理为其强项,故而VPP+DPDK的组合仍是当前最优的数据面处理引擎。

VPP通过实现DPDK Plugin的方式将DPDK引入到VPP中。在DPDK Plugin中注册Node为INPUT、Polling类型,并挂载DPDK通用报文收发函数,DPDK通用收发函数集中自动为所有IO进行了适配,使用者VPP仅需要告知DPDK关联的网卡pci地址即可。VPP仅需要调用DPDK收包函数实现报文批量接收,并进行二次加工处理后,调用DPDK发包函数实现批量发送即可。整个过程聚焦协议处理本身。

Plugin

VPP采用插件框架,将数据面不同的业务功能置于不同的插件中,如ACL、ABF、NAT等,故而支持灵活裁剪。现有业务插件基于满足大多数应用场景,如有新业务需求,可基于现有插件架构新增。业务插件具备以统一的方式注册到VPP中,通常包括:

  • 插件名及初始化顺序,由VLIB_INIT_FUNCTION定义
  • 插件初始化及运行参数,由VLIB_CONFIG_FUNCTION定义
  • 插件私有数据,与业务逻辑相关
  • 插件直调API,即动态函数导出(如ACL)
  • 插件配置vapi,支持能力开放
  • 插件配置CLI,支持调测与运维
  • 插件报文node,注册到转发图上,处理数据面报文
  • 插件运行数据stateseg,实时处理的共享数据

Node

根据标议标准,TCP/IP协议栈涉及多层多类业务报文的处理,如ARP、IP、ICMP报文在转发面涉及多次修改。VPP将报文处理划分为多个阶段,每个阶段可注册不同的业务处理函数,这类函数统称为Node。VPP报文处理阶段由arc_name定义,有:

  • arp
  • nsh-output
  • mpls-output
  • mpls-input
  • ip6-drop
  • ip6-punt
  • ip6-local
  • ip6-output
  • ip6-multicast
  • ip6-unicast
  • ip4-drop
  • ip4-punt
  • ip4-local
  • ip4-output
  • ip4-multicast
  • ip4-unicast
  • l2-output-nonip
  • l2-input-nonip
  • l2-output-ip6
  • l2-input-ip6
  • l2-output-ip4
  • l2-input-ip4
  • ethernet-output
  • interface-output
  • device-input
  • l2-input
  • l2-output

上述arc根据TCP/IP协议栈处理顺序划分,大的如L2/L3/L4阶段,每个阶段包括Input,Forwarding,Local,Output几种子阶段,业务Node根据处理需求注册到相同阶段即可,报文将按标准处理阶段依次调度。如BD业务注册在L2-input阶段; 如ACL业务通常注册在Ip4-unicast下,即L3/Input阶段;如NAT业务通常注册在Ip4-output阶段,即L3/Output阶段。

业务Node在注册到VPP时,除声明其调度阶段外,还需要声明其调度顺序及调度方式,调度顺序用于控制同一个ARC下不同node的处理顺序,由VNET_FEATURE_INIT声明并在VPP初始化时迭代出node graph;调度方式用于控制node的调度行为,包括:

  •   VLIB_NODE_TYPE_INTERNAL #中间业务Node主要类型
  •   VLIB_NODE_TYPE_INPUT #input node,通常为IO Node,即产生报文的Node
  •   VLIB_NODE_TYPE_PRE_INPUT #预处理node, 用于Sworker清理工作,如Nat Session
  •   VLIB_NODE_TYPE_PROCESS #协程node, 运行于Mworker,用于外部事件或周期事件

参见Nat out2in node注册:

Frame

Frame是VPP调度数据包的一种方式。试想VPP如何决定哪些包在哪些Node进行展开调度? 并同时要求矢量化? 这即是Frame调度需要考虑的。

传统数据包处理通常是单线函数栈方式,即逐一处理数据包,这种处理方式在专用芯片或特定指令集的CPU上性能仍然较好,但在通用服务器上性能极速拉低。通用服务器加速计算的有效方式是介于CPU和内存之间的Cache,无论是数据还是指令,VPP在这方面做到了极致。

如何实现数据包的批量调度? 这依赖于Frame的调度方式:

如Input Node产生数据包(如调用DPDK rx burst函数从Nic获取),最大数量为256。产生的数据包会递交给下一个Node处理,每一个Node都存在若干后续Node,但第一个Node为Input Node。在Node注册时,已经决定了Node的前后继关系。在当前Node中,会根据业务类型处理数据包,并将数据包分类。分类的结果决定了下一个Node,如当前Node处理了100个数据包,并将其分为4类,分别为A,B,C,D, 对应个数为:1,10,70,19。4类数据包会分别投递给4个不同的Node,重要的是形成Pending_frame,产生4个新的Pending_frame加入VPP调度序列中,Pending_frame中记录了其关联的Node,Node中挂载了相应的处理函数。

经过上述处理相同的业务报文被聚合,由于相同的业务报文处理逻辑基本是相同的,方便了VPP展开并行指令处理,最大化利用了CPU Cache。重要的Frame函数为:

  • vlib_get_next_frame
  • vlib_validate_buffer_enqueue_x1
  • vlib_put_next_frame

 

Feature

上述讲到,Frame在Node中进行分类,那么如何进行分类呢?这里有两种方式:

  • 默认调度 - 静态调度,在Node注册时已确定调度顺序
  • 指定调度 - 动态调度,由代码根据具体业务子类决定

默认调度,通用的业务模型调度方式,即同一个arc下的调度顺序;指定调度,特定业务处理的动态调度方式,如:

ip4-unicast:

udping4-out2in

ip4-sv-reassembly-feature

nat44-out2in-worker-handoff

报文在ip4-unicast阶段,会默认逐一被udping,reassembly,nat-out2in处理,如在udping中处理时,默认调用vnet_feature_next设置next为reassembly; 但如果存在需要drop或其它业务处理的特定报文,则会修改next node。见上述Node注册时,已声明的处理的顺序,包括其业务可能的next node。

Others

  • VPP针对配置数据的保护采用类似于调度锁方式,即将SWorker挂起后展开配置应用
  • VPP trace提供了基于报文粒度的跟踪方式,并支持filter过滤
  • VPP提供基于vapi的北向能力开放,并支持声明为mp_safe,针对非写数据的无锁访问
  • 2
  • 1
  • 0
0 评论
0/1000
评论(0) 发表评论
l****n

l****n

6 篇文章 0 粉丝
关注

VPP概要

2024-04-17 14:28:59 21阅读

前言

通信本质是信号的传递,如声音、烽火狼烟、电话电报、数据网络等;具备信息源、信息通道、信息接受者;可以是实时的或跨时空的;可以是单向的或双向的或多向的;可以是定向的或无向的。但通信离不开介质,那怕量子纠缠,也跳不过物质;毕竟一切在物质世界的显化都需要以物质作为主导,同时需要能量参与其中。

这一过程可以称之为“编程”(自从GPT、Sora诞生,貌似整个世界的活动都可程序化/数字化),即通信编程。将物质或能量按照一定的规则进行编码、解码,可以理解为对物质和能量的雕刻-Coding。

这里Coding泛指硬件的或软件的,大多数时候两者是相辅相成的,硬件好比建设公路桥梁,软件好比在其上运行的车辆。但对通信而言,通信线缆、基站、网卡、网桥、路由交换是基础硬件;软件则是在其上运行的包协议栈。但自从网络IP化之后, 这种通用通信模型加速了网络的互联,协议栈基本被TCP/IP所替代。

VPP是来自于FDIO社区的一种高性能TCP/IP协议栈,由Cisco主导,其聚焦L2/L3转发,富含包括BD、ACL、NAT、PBR等功能。VPP基于指令级和调度级批处理机制、结合用户态IO技术,使用通用服务器即可实现网络数据包的线速转发。

矢量框架

报文处理不中断,且流速线型可谓之矢量。VPP如何保证处理的矢量性?针对VPP代码分析,个人认为主要从这些点:

  • 用户态IO Polling技术: VPP使用DPDK库,直接在用户态轮询网卡数据,绕过了内核及网卡中断。Polling实现了报文的批量接收,是报文批量处理的前提。
  • Node级批量调度: VPP在于业务组织逻辑,相同的业务Frame置于同一个Node,并在调度层面展开Node级调度,实现了业务的批量处理。使L3 Cache得到了最大化利用,这是框架级优化。
  • Node内指令级批量:Node内逻辑使用了多个包的同质化处理,即并行编程,使L1-L2 Cache得到最大化利用。
  • CPU指令流水线利用:指令级访存预取优化,对未来数据进行并行预取,缩短访存时间。
  • 多队列多线程:VPP基于网卡多队列实现了多Worker并行无锁转发。
  • 快慢分离:基于核间无损包Handoff技术,实现快任务和慢任务分离。
  • 快转加速:部分业务实现了基于flow的快转支持。

DPDK

DPDK,数据面开发套件,支持包括UIO、VirtIO、MemIF、mbuf等工具库,覆盖了大多数网卡的UIO及零拷贝实现。可见,DPDK具备了丰富手IO开发套件,但其在协议处理上较弱,而VPP的协议处理为其强项,故而VPP+DPDK的组合仍是当前最优的数据面处理引擎。

VPP通过实现DPDK Plugin的方式将DPDK引入到VPP中。在DPDK Plugin中注册Node为INPUT、Polling类型,并挂载DPDK通用报文收发函数,DPDK通用收发函数集中自动为所有IO进行了适配,使用者VPP仅需要告知DPDK关联的网卡pci地址即可。VPP仅需要调用DPDK收包函数实现报文批量接收,并进行二次加工处理后,调用DPDK发包函数实现批量发送即可。整个过程聚焦协议处理本身。

Plugin

VPP采用插件框架,将数据面不同的业务功能置于不同的插件中,如ACL、ABF、NAT等,故而支持灵活裁剪。现有业务插件基于满足大多数应用场景,如有新业务需求,可基于现有插件架构新增。业务插件具备以统一的方式注册到VPP中,通常包括:

  • 插件名及初始化顺序,由VLIB_INIT_FUNCTION定义
  • 插件初始化及运行参数,由VLIB_CONFIG_FUNCTION定义
  • 插件私有数据,与业务逻辑相关
  • 插件直调API,即动态函数导出(如ACL)
  • 插件配置vapi,支持能力开放
  • 插件配置CLI,支持调测与运维
  • 插件报文node,注册到转发图上,处理数据面报文
  • 插件运行数据stateseg,实时处理的共享数据

Node

根据标议标准,TCP/IP协议栈涉及多层多类业务报文的处理,如ARP、IP、ICMP报文在转发面涉及多次修改。VPP将报文处理划分为多个阶段,每个阶段可注册不同的业务处理函数,这类函数统称为Node。VPP报文处理阶段由arc_name定义,有:

  • arp
  • nsh-output
  • mpls-output
  • mpls-input
  • ip6-drop
  • ip6-punt
  • ip6-local
  • ip6-output
  • ip6-multicast
  • ip6-unicast
  • ip4-drop
  • ip4-punt
  • ip4-local
  • ip4-output
  • ip4-multicast
  • ip4-unicast
  • l2-output-nonip
  • l2-input-nonip
  • l2-output-ip6
  • l2-input-ip6
  • l2-output-ip4
  • l2-input-ip4
  • ethernet-output
  • interface-output
  • device-input
  • l2-input
  • l2-output

上述arc根据TCP/IP协议栈处理顺序划分,大的如L2/L3/L4阶段,每个阶段包括Input,Forwarding,Local,Output几种子阶段,业务Node根据处理需求注册到相同阶段即可,报文将按标准处理阶段依次调度。如BD业务注册在L2-input阶段; 如ACL业务通常注册在Ip4-unicast下,即L3/Input阶段;如NAT业务通常注册在Ip4-output阶段,即L3/Output阶段。

业务Node在注册到VPP时,除声明其调度阶段外,还需要声明其调度顺序及调度方式,调度顺序用于控制同一个ARC下不同node的处理顺序,由VNET_FEATURE_INIT声明并在VPP初始化时迭代出node graph;调度方式用于控制node的调度行为,包括:

  •   VLIB_NODE_TYPE_INTERNAL #中间业务Node主要类型
  •   VLIB_NODE_TYPE_INPUT #input node,通常为IO Node,即产生报文的Node
  •   VLIB_NODE_TYPE_PRE_INPUT #预处理node, 用于Sworker清理工作,如Nat Session
  •   VLIB_NODE_TYPE_PROCESS #协程node, 运行于Mworker,用于外部事件或周期事件

参见Nat out2in node注册:

Frame

Frame是VPP调度数据包的一种方式。试想VPP如何决定哪些包在哪些Node进行展开调度? 并同时要求矢量化? 这即是Frame调度需要考虑的。

传统数据包处理通常是单线函数栈方式,即逐一处理数据包,这种处理方式在专用芯片或特定指令集的CPU上性能仍然较好,但在通用服务器上性能极速拉低。通用服务器加速计算的有效方式是介于CPU和内存之间的Cache,无论是数据还是指令,VPP在这方面做到了极致。

如何实现数据包的批量调度? 这依赖于Frame的调度方式:

如Input Node产生数据包(如调用DPDK rx burst函数从Nic获取),最大数量为256。产生的数据包会递交给下一个Node处理,每一个Node都存在若干后续Node,但第一个Node为Input Node。在Node注册时,已经决定了Node的前后继关系。在当前Node中,会根据业务类型处理数据包,并将数据包分类。分类的结果决定了下一个Node,如当前Node处理了100个数据包,并将其分为4类,分别为A,B,C,D, 对应个数为:1,10,70,19。4类数据包会分别投递给4个不同的Node,重要的是形成Pending_frame,产生4个新的Pending_frame加入VPP调度序列中,Pending_frame中记录了其关联的Node,Node中挂载了相应的处理函数。

经过上述处理相同的业务报文被聚合,由于相同的业务报文处理逻辑基本是相同的,方便了VPP展开并行指令处理,最大化利用了CPU Cache。重要的Frame函数为:

  • vlib_get_next_frame
  • vlib_validate_buffer_enqueue_x1
  • vlib_put_next_frame

 

Feature

上述讲到,Frame在Node中进行分类,那么如何进行分类呢?这里有两种方式:

  • 默认调度 - 静态调度,在Node注册时已确定调度顺序
  • 指定调度 - 动态调度,由代码根据具体业务子类决定

默认调度,通用的业务模型调度方式,即同一个arc下的调度顺序;指定调度,特定业务处理的动态调度方式,如:

ip4-unicast:

udping4-out2in

ip4-sv-reassembly-feature

nat44-out2in-worker-handoff

报文在ip4-unicast阶段,会默认逐一被udping,reassembly,nat-out2in处理,如在udping中处理时,默认调用vnet_feature_next设置next为reassembly; 但如果存在需要drop或其它业务处理的特定报文,则会修改next node。见上述Node注册时,已声明的处理的顺序,包括其业务可能的next node。

Others

  • VPP针对配置数据的保护采用类似于调度锁方式,即将SWorker挂起后展开配置应用
  • VPP trace提供了基于报文粒度的跟踪方式,并支持filter过滤
  • VPP提供基于vapi的北向能力开放,并支持声明为mp_safe,针对非写数据的无锁访问
文章来自专栏

畅说云网

6 篇文章 1 订阅
0 评论
0/1000
评论(0) 发表评论
  • 2
    点赞
  • 1
    收藏
  • 0
    评论