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 的 dpaa2 PMD 或 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 NFV 软件栈分层与集成关系 编排 / 控制面 OpenStack Neutron / Nova Kubernetes CNI / Multus / SR-IOV 管理接口 REST / Netconf / CLI 数据面框架 VPP graph node 转发流水线 OVS-DPDK vhost-user / 流表 自研 NFV App 基于 DPDK/ODP 用户态 I/O 抽象(并列两条路径) DPDK dpaa2 PMD / VFIO ODP odp-dpaa2 / pktio 共享内存 / 队列 无锁 ring / QMan Linux 内核(LSDK 内核分支) fsl-mc 总线 DPAA2 对象管理 dpaa2-eth / ethsw MAC / 交换机驱动 VFIO / UIO 用户态直通 Layerscape 硬件加速 QMan / BMan 队列 / 缓冲 SEC / CAAM 加解密卸载 以太网 MAC 10/25/100G PCIe / SMMU IOMMU 隔离 控制面下发 数据面直通 版本匹配原则:LSDK 内核 ↔ DPDK/ODP 适配版本 ↔ VPP 编译选项 ↔ 编排层插件,四者需同代对齐

三、版本选择:不是“越新越好”,而是“同代对齐”

Layerscape 的软件栈版本选择有一条硬约束:LSDK 内核版本、DPDK/ODP 适配版本、VPP 版本、编排层插件版本必须属于同一代。原因在于 DPAA2 的 MC 固件、DPL/DPC 配置、内核 fsl-mc 驱动与用户态 PMD 之间存在 ABI 约定,跨代混用常表现为“网卡能识别但收不到包”或“队列创建失败”。

实际选型时可按以下顺序判断:

  1. 先定 LSDK 版本:例如 LSDK 21.08 对应 Linux 5.10、U-Boot 2021.04、MC 固件 10.28.x。这是整个栈的基准。
  2. 再选 DPDK/ODP:LSDK 21.08 通常配套 DPDK 20.11 或 21.05 的 NXP 适配分支;ODP 则对应 odp-dpaa2 的同期版本。不要直接拉 DPDK 主线最新版,除非确认 PMD 已合入。
  3. VPP 跟随 DPDK:VPP 21.01 支持 DPDK 20.11,VPP 21.06 支持 DPDK 21.05。VPP 的 dpdk 插件在编译时绑定 DPDK 版本,升级 DPDK 必须重新编译 VPP。
  4. 编排层插件最后对齐: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 实例与端口资源的隔离,避免同一张网卡被两个编排层同时接管。

五、一个可参考的版本组合示例

以下组合属于教学示例,用于说明“同代对齐”的选型思路,并非唯一正确方案:

层次组件示例版本关键匹配点
底座LSDK21.08Linux 5.10 / U-Boot 2021.04 / MC 10.28
内核LSDK Linux5.10fsl-mc、dpaa2-eth、VFIO
用户态 I/ODPDK20.11 (NXP 分支)dpaa2 PMD、VFIO 绑定
用户态 I/OODP1.27 (odp-dpaa2)pktio 与 QMan 映射
数据面VPP21.01dpdk 插件绑定 DPDK 20.11
编排OpenStackWallabynetworking-vpp 与 VPP 21.01
编排Kubernetes1.21vpp-cni / SR-IOV CNI

把这张表与前面的分层图对照,可以看到每一层都通过明确的接口与上下层交互:LSDK 提供内核与固件,DPDK/ODP 提供用户态 I/O,VPP 提供转发流水线,编排层提供策略下发。版本选择的核心动作,就是保证这些接口在同一代内闭合。实际项目中,建议先在单板用 dpdk-testpmd 和 vppctl show interface 验证数据面,再接入编排层,这样能把版本问题与配置问题分开定位。