介绍
随着P4周围的生态系统持续发展,越来越多的可编程目标正在出现。P4编译器已经支持下一代Linux数据路径,如eBPF/XDP。然而,在某些设置中,有必要在运行时扩展用户空间数据包处理应用程序。这可以通过使用用户空间BPF(uBPF)虚拟机来实现,该虚拟机是内核eBPF VM的重新实现,并提供在运行时可扩展的用户空间执行环境。
这篇博客文章介绍了p4c-ubpf
,这是新的p4c
编译器后端,可以为uBPF VM编程数据包处理模块。p4c-ubpf
可以在实现基于内核旁路解决方案中执行P4代码,包括DPDK、AF_XDP等。
用于数据包处理的用户空间BPF
为什么是uBPF?
uBPF项目[1]重新实现了基于eBPF内核的虚拟机。它为x86-64提供了eBPF汇编器、反汇编器、解释器和JIT编译器。虽然BPF最初旨在在内核中安全执行代码,但uBPF项目允许在用户空间中运行BPF程序。因此,uBPF虚拟机可以很容易地与内核旁路集成(例如DPDK和AF_XDP)应用程序。
此外,与GPL许可的eBPF实现不同,uBPF使用Apache许可证2.0版本,这增加了额外的灵活性。最后,用户空间eBPF使用不太复杂的虚拟机,这意味着一些功能不受支持(例如尾调用),但也取消了eBPF中的一些限制,例如512字节堆栈大小限制。
P4rt-OVS
P4rt-OVS是广泛使用的Open vSwitch(OVS)的扩展,它将BPF虚拟机集成到用户空间数据路径中。特别是,它支持在运行时注入BPF程序,从而可以在不重新编译OVS的情况下扩展数据包处理管道。在技术层面上,BPF程序作为可编程操作,并在OpenFlow表中作为新的OVS操作(关键字prog
)引用。这些操作可以读取和写入持久映射(散列表)以保持每个流状态,它们也可以写入数据包头。p4c-ubpf
架构模型暴露了广泛的P4功能,包括有状态寄存器。
编译P4到uBPF
P4-to-uBPF编译器遵循与其他eBPF和XDP p4c
后端相同的约定。也就是说,P4程序首先被翻译成C语言的表示,然后使用clang
编译为BPF。这种设计是模块化的,因为P4-to-C编译器不需要生成低级BPF指令。
------------ ---------
P4_16 ---> | p4c-ubpf | ---> C ----> | clang | --> uBPF
------------ ---------
P4c-uBPF的架构模型如下。它由单个解析器、匹配操作管道和去解析器组成。
p4c-ubpf编译器还提供了一个外部函数库,这些函数实现了P4语言中不直接支持的功能。这些函数可以作为正常操作从P4程序中调用。架构模型支持散列函数、有状态寄存器、时间戳和校验和等操作。架构模型的完整规格可以在此链接中看到。
将P4翻译成C
p4c-ubpf执行的主要操作是从P4转换为C。下表简要总结了每个P4结构如何映射到相应的C结构。请注意,翻译非常相似topp4c-ebpf
和p4c-xdp
。
TRANSLATING PARSERS
P4 Construct | C Translation |
---|---|
header |
struct type with an additional valid bit |
struct |
struct |
parser state | code block |
state transition | goto statement |
extract |
load/shift/mask data from packet buffer |
TRANSLATING MATCH-ACTION PIPELINES
P4 Construct | C Translation |
---|---|
table | eBPF map |
table key | struct type |
table actions block |
tagged union with all possible actions |
action arguments |
struct |
table reads |
eBPF map’s lookups |
action body |
code block |
table apply |
switch statement |
registers | additional eBPF map |
register reads |
eBPF map’s lookups |
register writes |
eBPF map’s updates |
TRANSLATING DEPARSERS
P4 Construct | C Translation |
---|---|
apply block |
code block + adjusting packet’s size |
emit operation |
header’s validity check + write/shift/mask data to packet buffer |
p4c-ubpf与其他BPF相关编译器
与从P4到BPF的其他编译器相比,p4c-ebpf
为Linux TC子系统生成程序,p4c-xdp
针对XDP内核钩子,而p4c-ubpf
生成用户空间代码。这些P4后端支持的功能有几个差异。下表提供了简短的比较。
COMPARSION OF FEATURES PROVIDED BY P4C-EBPF, P4C-XDP AND P4C-UBPF
Feature | p4c-ebpf | p4c-xdp | p4c-ubpf |
---|---|---|---|
Packet filtering | YES | YES | YES |
Packet’s modifications & tunneling | NO | YES | YES |
Simple packet forwarding | YES | YES | YES |
Registers | NO | NO | YES |
Counters | YES | YES | NO |
Checksum computation | NO | YES | YES |
摘要
P4编译器的uBPF后端支持在用户空间中处理数据包的应用程序。它已经用于实现各种简单的应用程序,如有状态防火墙、速率限制器和GTP隧道。当与P4rt-OVS一起使用时,p4c-ubpf
可以实现新的网络协议——这是Open vSwitch目前不支持的。有关更多示例,请参阅此链接。