作者:韩文,单位:中国移动智慧家庭运营中心安全产品部
谈到高性能网络处理,DPDK已成为用户态网络数据处理的基础框架,其中最广泛熟知的项目就是OVS-DPDK。然而由于DPDK完全旁路内核,这会导致TCP/UDP等协议栈需要在用户态重新实现,且迄今还没有较好的通用用户态协议栈开源项目出现。在这种情况下,XDP借助于eBPF虚拟机技术在网卡驱动层实现高性能网络框架,且其原生运行在内核态可直通内核TCP/UDP协议栈。XDP作为一种数据面高性能框架技术为平衡高速数据处理和协议栈兼容开辟了一个新的道路。
1、XDP的基本概念
XDP全称eXpress Data Path,即快速数据路径,是Linux内核提供的高性能、可编程的网络数据包处理框架。XDP会直接接管网卡的RX方向数据包,通过在内核运行eBPF指令快速的处理报文并无缝对接内核协议栈。
XDP不是内核旁路,是在网卡和内核协议栈之间增加了一个快速数据路径。XDP借助于eBPF技术从而继承了其可编程、即时实现、安全等优良特性。
XDP智能网卡是XDP概念的延伸。在支持eBPF指令的智能网卡上,将CPU上XDP对应的eBPF指令下沉加载到智能网卡,这样可以同时实现CPU资源节约和规则硬件卸载。
XDP借助eBPF技术提供了一个高性能网络处理框架,用户根据标准eBPF编程指南来自定义网络处理行为。同时内核新增AF_XDP协议族,在内核XDP框架中被匹配的数据包通过其送抵用户态,这又将XDP的支持从内核拓展到用户态应用场景。
2、XDP的整体框架
如下图1,我们通过XDP整体框架图来展示其在内核系统中的相对位置以及其如何满足数据平面开发框架的要求。
图1 XDP整体框架图
图1包含了网卡设备、XDP框架、TCP/IP协议栈、Socket接口、应用层等各个层面,覆盖了网络数据包从网卡到服务端的数据流全过程。图1中间的灰色部分(XDP Packet Processor)是XDP框架,其数据面处理单元在内核中的相对位置处于网卡驱动和协议栈之间,实际运行在驱动层。从网卡到CPU处理器的网络数据包经由网卡驱动首先到达XDP框架,被运行在XDP框架中的用户自定义eBPF程序处理,数据包的处理结果为丢弃(Drop)、转发(Forward)、本地接受(Receive Local)等,结果为本地接受的网络数据包延续原有内核路径继续进入TCP/IP协议栈处理,结果为转发或者丢弃的网络数据包则直接在XDP框架中被直接处理(这部分流量在现实网络中占据大头,其执行路径相对传统的内核路径被大大缩短)。图1中间灰色部分(XDP Packet Processor)中的黑色虚线展示了上层控制对XDP框架中的eBPF程序进行加载/更新/配置等通道能力,内核提供对应的系统调用来实现控制面对数据面的管控。图1XDP整体框架图完整的展示了XDP作为一个高性能网络数据面和控制面集合的整体框架。
3、XDP应用开发介绍
XDP框架以eBPF技术为基础。BPF是一个通用目的RISC指令集。1992年,BPF第一次在Berkeley实验室被提出。2013年,BPF被加强从而得到eBPF,并在2014年正式并入Linux内核。eBPF提供了一种在各种内核和应用事件发生时运行一小段程序的机制。如下图2,我们讲述eBPF的开发/运行过程及在XDP上的具体应用。
图2 典型eBPF开发、运行流程图
图2展示了一个典型的eBPF开发、运行全过程。开发者用C语言的一个子集(内核运行,不可用标准C库)开发程序,然后用LLVM/clang编译器将其编译成eBPF指令(Bytecode),在eBPF验证器(Verifier)检验通过后被内核中的即时编译器(JIT Compiler)将eBPF指令映射成处理器的原生指令(opcode)再加载到内核各个模块预设的钩子(Hooks)处。其中XDP框架是内核在网卡驱动开辟的一个网络数据快速路径的钩子(Hooks)。内核其他典型钩子(Hooks)分别为内核函数 (kprobes)、用户空间函数 (uprobes)、系统调用、fentry/fexit、跟踪点、网络路由、TC、TCP拥塞算法、套接字等模块。
XDP是内核基于eBPF实现对网络快速路径的一个具体应用。下图3我们罗列了内核中支持eBPF钩子(Hooks)节点的典型应用。
图3 eBPF支持众多内核钩子应用
相比于传统的用户态/内核态程序,eBPF/XDP有如下典型特征:
(1)如下图4所示,内核即时编译器(in-kernel JIT Compiler)会将eBPF字节码映射成性能更优的处理器原生指令以实现高性能,同时其程序校验器(verifier)会校验程序安全性并提供沙箱运行环境。其安全检查包含判断是否有循环,程序长度是否超过限制,程序内存访问是否越界,程序是否包含不可达的指令等。最强优势是可以在不中断工作负载下实现实时更新。
图4 eBPF加载、检验、编译示意图
(2)eBPF程序的内核态与用户态数据交换通过BPF maps来实现,其类似进程间通信的共享内存访问。其支持的数据类型有Hash表、数组、LRU缓存(Least Recently Used)、 环形队列、堆栈轨迹、LPM路由表(Longest Prefix match)。如下图5所示,BPF Map承担了用户态和内核态的数据交互角色。
图5 BFP Map衔接用户态和内核态的数据交互
(3)eBPF通过提供辅助函数来弥补标准C库的缺失。常见的如获取随机数、获取当前时间、map访问、获取进程/cgroup上下文、处理网络数据包和转发、访问套接字数据、执行尾调用、访问进程栈、访问系统调用参数等,在实际开发中可通过man bpf-helpers命令获取更多帮助信息。下图6展示了一个bpf命名开头的获取随机数辅助函数。
图6 BPF辅助函数范例-获取随机数
(4)相比纯内核kmodule等开发模式,eBPF提供了一种独特的尾调用和函数调用机制。因受内核栈空间宝贵及eBPF不支持循环,递归深度限制(最大32)等原因,eBPF引入尾调用和函数调用来实现eBPF程序间跳转。尾调用和函数调用机制对性能优化做了充分设计,其中尾调用能复用当前的栈帧并跳转至另外一个eBPF程序,具体细节请参考bpf_tail_call辅助函数使用手册。由于eBPF程序彼此独立,尾调用机制在事实上给开发者提供了以函数为单元的编排能力。从Linux 4.16和LLVM 6.0开始,eBPF开始支持函数调用,并且在内核5.9以后支持尾调用和函数调用的协同工作。尾调用的缺点是生成的程序镜像大但是省内存;函数调用的优点是镜像小但是内存消耗大。开发者可根据实际需要灵活选择不同的方式。下图7展示了eBPF程序尾调用和函数调用的混合协作过程,其中tail call为尾调用,bpf2bpf call为函数调用。
图7 eBPF程序尾调用和函数调用的混合协作
4、XDP的同类技术对比
以目前最广泛使用的用户态数据面开发框架DPDK为对标,我们通过如下数据流图来说明XDP和DPDK的实现差异。如下图8,DPDK完全旁路内核且运行在用户态,XDP在内核中运行在网卡和内核协议栈之间。DPDK是脱离内核的一个全新数据平面开发框架,而XDP则是依附于内核的一个快速数据路径(相比原先的内核网络慢路径)。
图8 数据流在XDP和DPDK数据平面上的走向差异
如下是XDP和DPDK具体的对比情况:
(1)DPDK会独占CPU资源且需要大页内存。XDP对CPU不独占也不需要大页内存。XDP对硬件的要求较DPDK更低。
(2)以DPDK为数据面框架的项目会是重开发人力资源投入,可参考典型项目FD.IO(VPP)和OVS-DPDK。XDP为内核原生自带的快速数据通道,是轻量级数据面框架。
(3)DPDK需要网卡驱动和用户态协议栈等各层面的代码支持和许可证支持。XDP直接由Linux基金会维护和发布,具体技术生态由其子项目IO Visor来维护。
(4)DPDK在大容量高吞吐等场景有优势。XDP在云原生等场景有优势。
目前XDP有如下应用场景的典型项目:
- DDoS防御
- 防火墙
- 基于XDP的负载均衡
- 协议栈前处置
- 云原生应用服务优化 (如对K8S,OpenStack,Docker等服务改进项目)
- 流量控制
5、基于eBPF/XDP的著名开源项目
Cilium是使用eBPF和XDP为容器提供快速的内核内网络和安全策略实施的开源项目。Cilium项目为Pod和外部服务之间的流量实现了分布式负载平衡,并且能够完全取代kube-proxy,在eBPF中使用高效的哈希表,允许几乎无限的扩展。它还支持高级功能,如集成入口和出口网关、带宽管理和服务网格,并提供深度网络和安全可见性和监控。
如下图9所示,eBPF/XDP(小蜜蜂)处于容器、Pod等服务和网卡之间,通过XDP技术来改善上层服务的性能和安全,其非常巧妙和安全的在内核数据流节点动态完成之前内核无法完成的工作。
图9 Cilium项目组件分布图
图10展示了Cilium项目中分别通过XDP和eBPF在内核网卡和Socket层实现功能改善的一个具体案例。图10左边是在网卡驱动层XDP框架植入用户态网络处理代码,右边是在Socket层插入套接字处理代码,这样既可以在不修改内核的前提下实现功能动态拓展又实现了对上层容器、Pod等典型节点应用的无感知功能升级。
图10 Cilium项目中通过XDP和eBPF对内核进行功能扩展示意图
Cilium项目为云原生场景下的服务性能提升和安全改进等方面提供了一个非常好的模范解决方案。如图11,各类常见的云原生服务都得益于eBPF/XDP来实现性能提高和安全改进。
图11 eBPF/XDP在Cilium项目中的核心价值
6、DP的发展前景
为实现灵活的数据平面和加速NFV应用,Linux基金会成立子项目IO Visor以实现基于Linux内核延伸出一个开放可编程的网络数据面开源项目,XDP属于IO Visor项目的子项目。Linux内核没有虚拟化是IO Visor在NFV场景下最大的挑战,XDP通过eBPF虚拟机即时实现技术来弥补这个缺陷。但是几乎所有的虚拟机都运行在用户空间,受制于eBPF虚拟机在内核运行的安全性要求,将虚拟化相关的任务移植到内核空间会是比较大的挑战。
在性能改进方面,Sebastiano Miano等人于2019年使用XDP和TC钩子挂载eBPF程序实现了Linux的防火墙iptable,在规则数量提高的情况下提供相比原始iptable高数倍甚至数十倍的性能。Yoann Ghigoff等人于2021年更是基于eBPF和XDP、TC在内核中实现了一层Memcached的缓存,达到了比DPDK内核旁路方案还要高的性能。
XDP项目在传统内核模型和全新用户态框架之间开盘了新的道路,用以填补新技术跨度过大带来的资源投入陷阱。我们看到微软在2022年宣布计划在Windows平台开始支持XDP技术。随着整个生态环境的逐步完善,XDP带来的轻量级、即时实现、高性能通道、安全可靠等能力会日益发挥更大的价值。
中国移动智慧家庭中心会保持对XDP技术的密切跟踪,从技术层面持续跟踪产业的发展方向,对新兴技术保持开放的心态并积极拥抱新技术,推动产业界通过新兴技术为广大人民群众带来实实在在的数智化服务。