OVS内核态 与 OVS-DPDK 对比分析

5 阅读5分钟

OVS 与 OVS-DPDK 对比分析 (opus 4.6)

架构差异总览

【OVS 内核态】
应用 → 内核协议栈 → OVS内核模块(openvswitch.ko) → 网卡驱动 → 网卡
                         ↕ (upcall/首包)
                    ovs-vswitchd (用户空间)

【OVS-DPDK】
应用 → 内核协议栈 → ovs-vswitchd + DPDK PMD (用户空间轮询) → 网卡(UIO/VFIO)
         (完全绕过内核数据面)

核心区别

1. 数据面位置

维度OVS(内核态)OVS-DPDK
数据转发位置内核空间(openvswitch.ko)用户空间(DPDK PMD 轮询)
网卡驱动传统内核驱动DPDK PMD(UIO/VFIO 接管网卡)
包处理方式中断驱动轮询驱动(Polling)
控制面ovs-vswitchd(用户空间)ovs-vswitchd(用户空间,同时承载数据面)

2. 数据包处理流程对比

OVS 内核态
网卡收包
  → 硬件中断 → 软中断(NET_RX)
    → 内核网卡驱动收包
      → OVS内核模块流表匹配
        → 命中:内核直接转发 ✅(快速路径)
        → 未命中:Netlink upcall → ovs-vswitchd(慢速路径)
          → 上下文切换 × 2
          → 用户空间计算决策,下发流表
OVS-DPDK
DPDK PMD 线程持续轮询网卡(忙等待)
  → 直接从网卡队列取包(无中断、无系统调用)
    → 用户空间流表匹配(EMC → SMC → dpcls → upcall)
      → 命中:用户空间直接转发 ✅
      → 未命中:同进程内 upcall(无内核态切换)
    → 直接写入目标网卡/vhost-user 队列

3. 关键性能差异

指标OVS 内核态OVS-DPDK
延迟~50-100 μs~10-20 μs
吞吐量(小包64B)~1-3 Mpps~10-20+ Mpps
上下文切换频繁(中断 + upcall)几乎为零
数据复制内核态 sk_buff 操作用户空间 mbuf,零拷贝
CPU 使用按需使用持续 100% 占用(轮询线程)
首包延迟高(Netlink upcall 跨内核/用户空间)低(进程内 upcall)

详细差异分析

中断 vs 轮询

OVS 内核态(中断驱动)
网卡收到包
  → 触发硬中断(IRQ)
    → CPU 保存上下文,跳转到中断处理程序
      → 调度软中断 NAPI 轮询
        → 处理一批数据包
          → 软中断退出
  • 每次中断有 数μs 的开销
  • 高流量下中断风暴导致 CPU 被中断处理占满
  • NAPI 做了优化(中断+轮询混合),但仍有开销
OVS-DPDK(PMD 轮询)
PMD 线程(绑定到专用 CPU 核)
  while(true) {
      nb_rx = rte_eth_rx_burst(port, queue, mbufs, batch_size);
      if (nb_rx > 0) {
          process_packets(mbufs, nb_rx);
          rte_eth_tx_burst(port, queue, mbufs, nb_tx);
      }
      // 永不休眠,永不让出 CPU
  }
  • 零中断:完全消除中断开销
  • 零系统调用:网卡通过 UIO/VFIO 映射到用户空间
  • 代价:PMD 线程独占 CPU 核,即使没有流量也 100% 占用

内存管理差异

维度OVS 内核态OVS-DPDK
包缓冲区sk_buff(内核动态分配)mbuf + mempool(预分配大页内存)
内存分配每包可能触发 kmalloc预分配池,零动态分配
大页内存不需要必须配置 HugePages
NUMA 感知有限完整 NUMA 亲和性

与 KubeVirt VM 的连接方式

OVS 内核态 + vhost-net
VM(virtio-net) → vring → vhost-net(内核) → tap设备 → OVS内核模块
  • vhost-net 在内核态处理 vring
  • 数据从 vring → tap → OVS 内核模块,路径较短
OVS-DPDK + vhost-user
VM(virtio-net) → vring(共享内存) ← OVS-DPDK PMD 直接轮询
  • 使用 vhost-user 协议(替代 tap + vhost-net)
  • OVS-DPDK 的 PMD 线程直接读取 VM 的 vring 共享内存
  • 省去了 tap 设备和 vhost-net 内核模块
  • 数据路径:
Guest 应用 → Guest 内核 → virtio vring → (共享内存) → OVS-DPDK PMD → 网卡
                                    ↑
                               无需经过Host内核

数据复制次数对比(KubeVirt 场景)

OVS 内核态路径

序号复制说明
1应用 → Guest 内核send() 系统调用
2Guest 内核 → vringvirtio 描述符
3vring → tap sk_buffvhost-net 内核处理
4OVS 内核转发sk_buff 指针操作(可能零拷贝)
5内核 → 网卡DMA
总计4-5 次

OVS-DPDK 路径

序号复制说明
1应用 → Guest 内核send() 系统调用
2Guest 内核 → vringvirtio 描述符
3vring → DPDK mbufPMD 直接从共享内存读取
4DPDK → 网卡DMA(用户空间发起)
总计3-4 次

上下文切换对比

切换类型OVS 内核态OVS-DPDK
Guest send()1次1次
VM Exit1次1次
vhost-net / PMD内核态处理无切换(用户空间轮询)
中断处理多次0次
OVS upcall(首包)2次(内核↔用户空间)0次(进程内)
总计5-7 次2-3 次

部署复杂度对比

维度OVS 内核态OVS-DPDK
配置复杂度
HugePages不需要必须配置(通常 1G 页)
CPU 绑定不需要需要隔离 CPU 核给 PMD
内存预留不需要需要预留大量大页内存
NUMA 规划不敏感必须规划 NUMA 拓扑
K8s 集成成熟需要额外配置(CPU Manager 等)
调试难度低(标准内核工具)高(专用工具)

适用场景

选 OVS 内核态

  • 通用工作负载,对延迟不敏感
  • 资源有限,不能独占 CPU 核
  • 运维团队对 DPDK 不熟悉
  • VM 密度优先

选 OVS-DPDK

  • 电信/NFV 场景(高吞吐、低延迟)
  • 需要线速转发小包
  • 有充足的 CPU 和内存资源可以专用
  • 对网络性能有严格 SLA 要求

一句话总结

OVS 内核态用中断 + 内核模块处理数据包,通用但开销较多;OVS-DPDK 将整个数据面搬到用户空间轮询,以独占 CPU 核为代价,换取更少的数据复制、几乎零上下文切换和数倍的吞吐性能