原项目位于:https://github.com/simula/P4-OvS/tree/p4/tests
配置步骤见:基于P4的OpenVSwitch环境配置 - 镇鱼 - 博客园 (cnblogs.com)
本文翻译其项目设计架构与原理。
P4-OvS是开放式虚拟交换机的一个新版本,它支持用户可配置的、独立于协议的(P4)数据路径。
P4操作系统主要基于OVS。出于以下原因,项目决定利用开放式虚拟交换机作为新P4软件交换机的基础:
-
开放式虚拟交换机已经支持快速内核旁路解决方案,如DPDK或AF_XDP。因此,这部分代码可以重复使用。
-
Open vSwitch实现了一个轻量级的成熟数据库,叫做OVSDB。同样,OVSDB可以重新用于存储和同步P4软件交换机的状态。
-
经社区验证的使用模式。
一个悬而未决的问题是,P4开放源码软件应该成为开放软件项目的一部分,还是发展成为一个新的开源项目。在做出这个决定之前,P4-OVS被认为是一个混合(OpenFlow + P4Runtime)解决方案,影响本文档中描述的设计选择。
预备知识
如果您不熟悉开放式虚拟交换机的设计和实现,强烈建议您阅读OVS文档。https://docs.openvswitch.org/en/latest/
设计假设
-
向后兼容和与OpenFlow的无缝集成——用户应该仍然能够使用开放虚拟交换机的众所周知的现有功能。P4的支持应该是一种选择。
-
每个桥的P4程序——开放的虚拟交换机允许运行由同一个OVS实例创建的多个OVS桥。P4桥引入了一种新的桥型,叫做“P4桥”。每个P4桥都有自己的P4程序,描述大桥的数据平面特征。
-
保持OVS的模块化——开放虚拟交换机的架构是模块化的,允许轻松集成新的开放流数据路径。P4操作系统的设计和实施也应遵循模块化方法。
-
支持便携式交换机架构(PSA)——P4-OvS不会提出另一个P4架构模型。相反,项目利用已经存在且记录良好的PSA体系结构。
-
P4Runtime作为控制接口——OpenFlow不可扩展,不能支持P4。项目设计者不相信P4和OpenFlow之间的翻译是可能的。因此,P4-OvS(确切地说是P4桥)将向外部应用程序(控制器)公开基于P4Runtime的控制接口。
架构
如前所述,P4-OvS的想法是通过支持P4的数据路径和P4Runtime接口来扩展开放虚拟交换机,但保留(至少在第一个版本中)开放虚拟交换机和开放流编程模型的众所周知的特性。因此,P4-OVS的架构在很大程度上是基于OvS的抽象。从功能的角度来看,P4开放式虚拟交换机扩展了一个基础开放式虚拟交换机,增加了四个新模块:
-
可重新配置的(或P4)数据路径——新的大组件负责处理进入P4桥相关端口的数据包。它应该允许在运行时注入新的数据包处理管道(由P4程序生成)。可重新配置的数据路径公开了管理P4程序和控制P4对象(如P4表、寄存器等)的接口。).可重配置数据路径的例子可以是eBPF、XDP或uBPF。
-
P4Runtime接口——这个功能块在可重构数据路径和外部控制器之间提供了一个抽象层。特别是,它实现了gRPC服务器(P4Runtime协议定义),并允许用户控制P4数据路径。
-
P4编译器——尽管P4编译器将在一个单独的库中实现,但它也是功能架构的一部分。用户利用P4编译器从P4程序和P4运行时接口的P4Info元数据文件中生成特定于数据路径的二进制文件。
-
ovs-p4ctl——P4大桥的管理工具。它管理P4程序并控制P4对象。其他管理任务(如添加新端口)仍由其他OVS实用工具(如ovs-vsctl)执行。
可重构数据路径
到目前为止,考虑了以下两个数据路径:
-
用户空间伯克利包过滤器(UBPF)——eBPF的用户空间再实现。它提供了uBPF虚拟机,在那里可以在运行时注入任意的BPF字节码。uBPF与用户空间数据路径和内核旁路解决方案(如DPDK/AF_XDP)配合良好。
-
eXpress DataPath(XDP)——XDP提供的内核快速路径也可以作为P4 OvS的可重构数据路径。还有p4c-xdp编译器,它可以将P4代码翻译成与xdp兼容的BPF字节码。
由于模块化设计,应该可以集成一个新的可重构数据路径(如现场可编程门阵列)。
uBPF数据路径
P4-OvS的PoC版本实现了uBPF数据路径。尽管它有一些实现上的怪癖,但它展示了使用uBPF作为默认P4数据路径的一般思想。
PoC实施基于netdev数据路径。netdev数据路径依赖于分组处理和PMD线程来轮询来自网络接口的分组。
uBPF遵循同样的方法。然而,在uBPF包分类的情况下,对包的其他操作是在uBPF程序内部执行的(对每个传入的包调用)。这对实施有一些影响。首先,netdev利用缓存架构(EMC、SMC缓存)来加速数据包分类。
相反,uBPF数据路径不能重用基于缓存的分类器,而是依赖p4c-ubpf生成的包分类器。此外,netdev创建每个流的数据包批次。在uBPF的情况下,应该按照每个动作构造包批次。关于uBPF的数据包处理的一般观点如下。
与OpenFlow桥的互操作性
P4-OvS的设计是为了保持开放虚拟开关的众所周知的功能。因此,项目也致力于提供具有OpenFlow桥的互操作性模型。
上图展示了一个场景,其中有一个异构部署,即P4Runtime和OpenFlow桥都是为开放虚拟交换机的实例配置的。在右侧,有两个OpenFlow桥通过一个补丁(patch)端口连接。
补丁端口是OVS的一个众所周知的概念,它提供了连接两个OpenFlow桥的轻量级方法,而不需要使用vEth对。它也比vEth更有效。对于P4Runtime桥,项目使用相同的概念。P4-OvS将实现对补丁端口的支持,因此不需要使用vEth来连接两个P4Runtime桥。该图还展示了OpenFlow和P4Runtime桥如何相互连接。在这种情况下,需要使用vEth对来连接它们,因为br-p41和br-of1使用不同的数据路径类型(例如“ubpf”和“netdev”)。
实现架构
OVS提供了分层的、可扩展的架构。说到OpenFlow抽象的实现,有两个主要的“接口”:ofproto-provider.h和dpif-provider.h。前者指定OpenFlow开关抽象。后者指定了OpenFlow数据路径接口——OpenFlow数据路径应该实现的一组动作。
P4-OVS应该有类似的设计。然而,为了避免代码重复,P4-OvS使用了dpifprovider.h,并用P4特有的函数对其进行了扩展,这些函数不应该由OpenFlow数据路径来实现。P4-OvS只实现了一个新的p4rt-provider.h,它提供了P4Runtime开关抽象。
执行决策
端口分配
OpenFlow版本的OpenVSSwitch区分了数据路径级端口号和OpenFlow级端口号。
ofproto-dpif提供OpenFlow端口和数据路径级端口之间的映射。在P4的情况下,不能进行这样的映射,因为端口号可以在P4程序中明确使用,该程序在数据路径级别使用端口号。因此:
-
如果用户在使用ofport_request添加端口号时没有指定端口号,端口号将由数据路径自动分配。
-
如果用户指定了一个端口号,P4-OvS将尝试在数据路径中分配给定的端口号。
上面的自然结果是,端口号在开放虚拟交换机中必须是唯一的。对于传统的开放式虚拟交换机,端口号对于给定的网桥必须是唯一的。对于P4-OvS,用户必须请求端口号,任何P4桥都不使用该端口号。
注意!如果用户指定一个已经在使用的端口号,P4-OvS将返回一个错误并分配一个新的端口号。
支持多个P4项目
根据要求,每座P4大桥都应有其独特的、独立的P4规划。P4Runtime规范使用设备标识字段来区分由同一P4Runtime服务器控制的不同P4设备。在P4-OvS的情况下,每个P4桥由设备标识来标识。这种方法使P4操作系统符合P4Runtime规范。
注意!PoC版本也使用device_id在数据路径级别识别P4程序。只要只使用一个P4数据路径,它就能工作。对于进一步的版本,应该有所提供的数据路径所使用的device_id和program_id之间的映射。
使用
P4-OvS遵循开放式虚拟交换机的使用模式。网桥和端口配置有ovsvsctl。为了使用新的“p4桥”,新的P4标志、数据路径类型(PoC中只允许ubpf)和目标二进制文件的路径必须传递给add-br命令。
ovs-vsctl add-br br0 -- set bridge p4=true datapath_type=ubpf other_config:program=" <PATH-TO-P4-PROGRAM>"
上面的命令将使用uBPF数据路径创建“P4”类型的OVS桥,并将目标二进制(uBPF字节码)注入uBPF数据路径,以便数据包可以由用户配置的管道处理。然后,用户可以简单地向网桥添加端口。对于P4桥,应禁用ovs-ofctl工具,例如:
ovs-ofctl dump-flows br0 ERROR: OpenFlow tools are disabled for P4-capable bridge br0
注意!如果ovs-ofctl用于P4桥,当前版本通过返回以下消息通知用户。对于P4桥来说,ovs-ofctl将无法工作,因为P4桥没有公开OpenFlow接口。
ovs-ofctl: br0 is not an OpenFlow bridge or a socket
ovs-p4ctl应该用于管理和配置基于P4Runtime的ovs桥。示例命令可能如下所示:
ovs-p4ctl --help
ovs-p4ctl: P4Runtime switch management utility
For P4Runtime switches:
show SWITCH show P4Runtime information
dump-tables SWITCH print table stats
dump-table SWITCH TABLE print table information
add-pipe SWITCH inserts P4 program to the switch
set-pipe SWITCH inserts and activates P4 program
get-pipe SWITCH gets current P4 program
add-entry SWITCH TABLE <ENTRY> adds table entry
del-entry SWITCH TABLE <MATCH> deletes table entries with given
MATCH
dump-entry SWITCH TABLE prints table entries of TABLE
试验结果
P4-OVS的性能已经过初步测试,结果如下所示。使用原型版本的uBPF数据路径,它能够实现比OVS-DPDK稍差的吞吐量。请注意,DPDK配置可能不是最佳的,性能可以调整,但OVS-DPDK和P4-OvS使用了相同的环境。
用例
我在哪里可以看到高性能P4软件交换机的应用?
-
可扩展、可定制的虚拟机管理程序交换机——开放式虚拟交换机被广泛用作虚拟机管理程序交换机(例如,用于开放式堆栈)。用户可配置的版本也可以用作虚拟机管理程序交换机,它将允许云提供商按需定制网络并更快地创新。
-
商品服务器上的低成本、可编程“裸机”交换机——随着用户需求的不断变化,网络结构必须定制,新的网络功能必须按需部署。P4-OvS可能是DC结构的低成本、可编程网络交换机的基础。
-
虚拟网络文件系统的数据平面组件——VNF提供商可以使用P4虚拟网络文件系统来构建虚拟网络文件系统的高性能数据平面(例如5G UPF)。
附录一——实施
在本节中,将描述特定于实现的方面。
以下修改已应用于原始OVS代码,以启用P4数据路径:
-
新参数(p4,布尔类型)已添加到OVS大桥的数据库模型中。
-
新增目录(p4rt/)。它包含与P4和P4Runtime相关的文件(例如P4Runtime抽象的实现和P4Runtime提供程序)。
-
bridge.c中的struct桥已经用新的field struct p4rt *p4rt进行了扩展,它代表P4Runtime开关抽象(类似于struct of port和OpenFlow开关抽象)。
-
这座桥可以是“P4”或“开放流”两种类型中的一种。因此,在bridge.c中有if-else语句,用于检查桥是否属于P4类型。P4大桥的特定于开放流的功能被“阻止”。
-
dpif-netdev . c/create_dp_netdev()-内存分配已移出create _ DP _ net dev()函数(to construct_dp_netdev()),以允许dpif-ubpf重用dpif-net dev的一部分。基本上,为了快速原型化,一些dpif-netdev.c的结构和功能已经转移到dpif-netdev.h,这可能不是最好的想法,也不是目标解决方案。
-
dpif-provider在OpenFlow数据路径接口和P4Runtime数据路径接口之间共享。struct dpif_class已经扩展了仅用于P4(可重配置)数据路径的函数。这些功能不应该由OpenFlow数据路径接口实现。