3. NFV软件栈与Layerscape SDK
在 Layerscape 平台上做 NFV 工程,最容易踩的坑不是某个组件不会用,而是把一整套软件栈的层次关系搞混:LSDK 提供什么、Linux 内核负责什么、DPDK 和 ODP 各自解决哪一段、VPP 站在哪一层、OpenStack 与 Kubernetes 又从哪里接入。这一节先把整条栈的“纵向分层 + 横向数据面/控制面”关系讲清楚,再落到版本选择与匹配的实际判断上。
一、LSDK 是“底座”,不是单一软件
LSDK(Layerscape Software Development Kit)是 NXP 针对 Layerscape 系列 SoC 发布的整套软件开发包。它并不是一个可执行程序,而是一组协同交付物的集合,典型包含:
- U-Boot 与 ATF(ARM Trusted Firmware):负责启动流程、DDR/SerDes 初始化、PSCI 与安全启动,是后续所有软件运行的前提。
- Linux 内核源码与设备树:NXP 维护的 LSDK 内核分支,包含 DPAA/DPAA2、NETC、PCIe、SMMU 等平台驱动。
- 根文件系统与用户态组件:含网络工具、DPDK/ODP 运行库、示例程序与固件(如 MC 固件、DPAA2 的 DPL/DPC)。
- DPDK、ODP 的适配层:把平台加速硬件(BMan、QMan、SEC、CAAM、NETC)暴露给用户态数据面。
- 文档与配置脚本:如
lsdk_linux_*.itb、ls-addni、restool等工具,用于创建 DPAA2 对象。
理解 LSDK 的关键是:它把“芯片能力”翻译成“标准 Linux + 标准用户态接口”。DPDK、ODP、VPP 之所以能在 Layerscape 上跑,是因为 LSDK 已经把这些组件的平台适配做进了内核和用户态库。
二、从内核到用户态数据面的纵向关系
NFV 场景下,报文路径通常要绕开内核协议栈,直接进入用户态。Layerscape 的典型分层如下:
- 硬件层:DPAA2(或 DPAA1/NETC)提供以太网 MAC、队列管理 QMan、缓冲管理 BMan、加解密 SEC。
- 内核层:LSDK 内核中的
fsl-mc总线驱动、dpaa2-eth、dpaa2-ethsw、VFIO/UIO 等,负责设备枚举、资源分配与用户态直通。 - 用户态 I/O 抽象层:DPDK 的
dpaa2PMD 或 ODP 的odp-dpaa2,把硬件队列映射成用户态可轮询的收发接口。 - 数据面框架层:VPP 通过 DPDK 插件接管网卡,构建 graph node 转发流水线;ODP 则提供更抽象的
odp_pktio接口。 - 控制面/编排层:OpenStack Neutron、Kubernetes CNI 通过管理接口下发网络策略、创建 VF、挂载 VPP/OVS 端口。
这里有一个常见误区:DPDK 和 ODP 不是上下层关系,而是并列的两条用户态 I/O 路径。DPDK 更贴近硬件、性能调优空间大;ODP 提供统一 API,便于跨平台移植。VPP 既可以跑在 DPDK 之上,也可以跑在 ODP 之上,取决于编译选项。
三、版本选择:不是“越新越好”,而是“同代对齐”
Layerscape 的软件栈版本选择有一条硬约束:LSDK 内核版本、DPDK/ODP 适配版本、VPP 版本、编排层插件版本必须属于同一代。原因在于 DPAA2 的 MC 固件、DPL/DPC 配置、内核 fsl-mc 驱动与用户态 PMD 之间存在 ABI 约定,跨代混用常表现为“网卡能识别但收不到包”或“队列创建失败”。
实际选型时可按以下顺序判断:
- 先定 LSDK 版本:例如 LSDK 21.08 对应 Linux 5.10、U-Boot 2021.04、MC 固件 10.28.x。这是整个栈的基准。
- 再选 DPDK/ODP:LSDK 21.08 通常配套 DPDK 20.11 或 21.05 的 NXP 适配分支;ODP 则对应
odp-dpaa2的同期版本。不要直接拉 DPDK 主线最新版,除非确认 PMD 已合入。 - VPP 跟随 DPDK:VPP 21.01 支持 DPDK 20.11,VPP 21.06 支持 DPDK 21.05。VPP 的
dpdk插件在编译时绑定 DPDK 版本,升级 DPDK 必须重新编译 VPP。 - 编排层插件最后对齐:OpenStack 的
networking-vpp或 Kubernetes 的vpp-cni需与 VPP 版本匹配;SR-IOV CNI 则依赖内核 VF 与 DPDK VF 的绑定方式。
restool dprc show 确认 DPAA2 对象正常,再运行 dpdk-testpmd 看能否收发包。如果 testpmd 正常但 VPP 不通,问题通常在 VPP 与 DPDK 的版本绑定,而不是硬件。四、OpenStack 与 Kubernetes 的接入差异
两者在 NFV 栈中的位置不同,接入方式也不同:
- OpenStack:Neutron 通过 ML2 插件管理网络,VPP 可作为 ML2 的 mechanism driver,也可用 OVS-DPDK 替代。虚拟机通过 vhost-user 接入 VPP,SR-IOV 则把 VF 直通给 VM。控制面走 REST,数据面走 vhost-user 或 VF。
- Kubernetes:CNI 负责 Pod 网络。VPP 场景常用
vpp-cni或 Multus + 自定义 CNI;SR-IOV 场景用 SR-IOV CNI 把 VF 注入 Pod。控制面走 CNI 配置与 Device Plugin,数据面走 memif 或 VF。
选择时的一个实际判断:如果业务以虚拟机为主、需要成熟的租户网络与安全组,优先 OpenStack;如果业务是容器化 VNF、需要快速弹性与声明式编排,优先 Kubernetes。两者也可以共存,但要注意 VPP 实例与端口资源的隔离,避免同一张网卡被两个编排层同时接管。
五、一个可参考的版本组合示例
以下组合属于教学示例,用于说明“同代对齐”的选型思路,并非唯一正确方案:
| 层次 | 组件 | 示例版本 | 关键匹配点 |
|---|---|---|---|
| 底座 | LSDK | 21.08 | Linux 5.10 / U-Boot 2021.04 / MC 10.28 |
| 内核 | LSDK Linux | 5.10 | fsl-mc、dpaa2-eth、VFIO |
| 用户态 I/O | DPDK | 20.11 (NXP 分支) | dpaa2 PMD、VFIO 绑定 |
| 用户态 I/O | ODP | 1.27 (odp-dpaa2) | pktio 与 QMan 映射 |
| 数据面 | VPP | 21.01 | dpdk 插件绑定 DPDK 20.11 |
| 编排 | OpenStack | Wallaby | networking-vpp 与 VPP 21.01 |
| 编排 | Kubernetes | 1.21 | vpp-cni / SR-IOV CNI |
把这张表与前面的分层图对照,可以看到每一层都通过明确的接口与上下层交互:LSDK 提供内核与固件,DPDK/ODP 提供用户态 I/O,VPP 提供转发流水线,编排层提供策略下发。版本选择的核心动作,就是保证这些接口在同一代内闭合。实际项目中,建议先在单板用 dpdk-testpmd 和 vppctl show interface 验证数据面,再接入编排层,这样能把版本问题与配置问题分开定位。