datapath 在 Open vSwitch(OVS)和 Linux 内核网络里是一个核心概念。我们从最基础开始,层层解释:
在体系结构里:
OVS 分两部分:
它主要有几个职责:
拦截数据包
快速转发
执行动作
datapath 能执行的操作包括:
桥接内核和用户态
你可以这样理解整个过程:
物理网卡(eno12399) 收到数据包 → 内核驱动 → datapath 拦截 → 查 flow 表 →
所以 datapath 就是为什么你的物理网卡能把包“直接给 br-ex”的关键:
ovs-vsctl add-port br-ex eno12399
)。如果把 OVS 看成“一个虚拟交换机”:
要验证 datapath 的存在和工作情况,可以:
lsmod | grep openvswitch
ovs-dpctl show
、ovs-dpctl dump-flows
ovs-vsctl show
很多人一开始都会困惑:OVS 明明是一个“用户态程序”,为什么能插到内核里面,甚至能接管网卡转发?我们从原理和历史两方面来解释。
OVS 不只是一个用户态程序。
OVS 的完整实现包含两部分:
为什么要内核模块?
因为数据包的转发如果完全靠用户态,性能会非常差:
所以 OVS 在内核里写了一个 datapath 模块,直接在内核空间处理大部分数据包。
这样转发只需内核态一次处理,不用来回切换。
这并不是 OVS 私自“黑进去”的,而是内核官方提供的机制:
Linux 内核本身允许第三方内核模块
.ko
) 并加载到内核中。ixgbe.ko
, e1000.ko
) 本质上是同一类东西:驱动内核如何处理数据包。内核网络子系统是可扩展的
官方合并进了 Linux 主线内核
你提到的“ovs 不是 openstack 自己实现的一个程序嘛”这个是一个常见误区:
因为 datapath 就是一个内核里的虚拟交换机实现,它在内核里有独立的 flow table 结构。
flow table 在内核里:
这种设计就是 内核负责 fast path,用户态负责 slow path,完全模仿硬件交换机 ASIC 的架构。
可以这样打比方:
所以答案是:
要不要我帮你画一张 OVS 内核与用户态交互架构图?这样你就能直观看到 datapath 在内核里的位置,以及它和 ovs-vswitchd、OpenStack 的关系。
好,那我帮你画一个 OVS 架构图,重点突出 datapath 在内核里的角色,以及它和用户态 / OpenStack 的关系。
+----------------------+
| OpenStack |
| (Neutron ML2等) |
+----------+-----------+
|
v
+----------------------+
| ovs-vswitchd | ← 用户态控制进程
| (Control Plane) |
+----------+-----------+
| Netlink
v
============================================================
Linux 内核空间 (Data Plane)
============================================================
^
+----------+-----------+
| OVS datapath | ← 内核模块 (openvswitch.ko)
| (flow table, actions)|
+----------+-----------+
^
+---------------+-----------------+
| |
+-------+-------+ +-------+-------+
| 物理网卡 | | 虚拟端口/TAP |
| (eno12399等) | | (VM接口 vnetX)|
+---------------+ +---------------+
OpenStack Neutron
ovs-vsctl
等命令控制 ovs-vswitchd,告诉它“该建哪些桥、加哪些流表”。ovs-vswitchd(用户态)
OVS datapath(内核态)
物理网卡 / 虚拟端口
这样你就能直观理解:
数据包收发路径 的时序图?比如“外部请求进入 eno12399 → datapath → br-ex → 虚拟机 vnet0”的全过程。
(外部主机 → 物理网卡 eno12399 → OVS bridge br-ex → 内核 datapath → tap/vnetX → 虚拟机)
外部主机
│
│ 数据包 (dst=VM_IP)
▼
物理网卡 (eno12399)
│ 驱动收包
▼
Linux 内核
│
│ 交给 OVS datapath (openvswitch.ko)
▼
OVS datapath (flow table)
│
│ 查表:
│ - 如果有匹配 → 执行动作 (比如输出到 vnetX)
│ - 如果没有匹配 → 上报 ovs-vswitchd (用户态),请求安装 flow
▼
输出到 vnetX (虚拟端口,挂在 br-int 或 br-ex 上)
│
│ 数据包进入 VM 的 tap 接口
▼
虚拟机 (eth0)
│
│ 应用程序收到数据包
▼
处理完成
(VM → vnetX → OVS datapath → flow table → br-ex → 物理网卡 → 外部主机)
虚拟机 (eth0)
│
│ 应用程序发包
▼
tap/vnetX
│
│ 把包交给 OVS datapath
▼
OVS datapath (flow table)
│
│ 查表:
│ - 如果有匹配 → 执行动作 (比如输出到 eno12399)
│ - 如果没有匹配 → 上报 ovs-vswitchd,安装 flow
▼
物理网卡 (eno12399)
│ 驱动发包
▼
外部主机
fast path / slow path:
br-ex / br-int 的作用:
换句话说:
这就是 OVS datapath 在内核里“劫持”并加速转发的完整逻辑。
更底层的 Linux 内核调用路径图?比如 net_device → datapath hook → flow table → net_device
,这样能看清它是怎么嵌在内核网络栈里的。
重点展示 OVS datapath 是怎么嵌进内核网络栈里的。
外部数据包
│
▼
[ 网卡硬件收包 ]
│
▼
[ 网卡驱动 (ixgbe/e1000 等) ]
│
▼
[ net_device 接口 (Linux 内核统一抽象) ]
│
▼
==== Linux 网络协议栈 Hook ====
│
▼
[ OVS datapath (openvswitch.ko) ]
│
│ 查 flow table:
│ - 命中 → 执行动作 (转发/修改/丢弃)
│ - 未命中 → 通过 Netlink 通知 ovs-vswitchd
▼
[ net_device 输出 ]
│
├──> 虚拟网卡 (tap/vnetX → 虚拟机)
│
└──> 物理网卡 (eno12399 → 外部网络)
网卡驱动 → net_device
struct net_device
。协议栈 Hook → OVS datapath
flow table 匹配
用户态 ovs-vswitchd 回应
对比图:没有 OVS vs 有 OVS,这样能清楚看到 datapath 是怎么改变 Linux 默认转发流程的。
情况一:没有 OVS
====================
[ 物理网卡 eno12399 ]
│
▼
[ 内核 net_device ]
│
▼
[ Linux 协议栈 ]
- ARP
- 路由表 (ip route)
- iptables/nftables
│
▼
[ 输出网卡 (物理 or 虚拟) ]
│
▼
[ 外部网络 / 虚拟机 ]
情况二:有 OVS (datapath)
====================
[ 物理网卡 eno12399 ]
│
▼
[ 内核 net_device ]
│
▼
[ OVS datapath (openvswitch.ko) ]
- flow table 查找
- 命中 → 直接执行动作 (转发/改包/丢弃)
- 未命中 → 上报 ovs-vswitchd (用户态),安装新 flow
│
▼
[ 输出端口 (vnetX / br-ex / 物理网卡) ]
│
▼
[ 外部网络 / 虚拟机 ]
无 OVS:
内核完全按 路由表 / iptables 决定路径。转发逻辑比较固定。
有 OVS:
内核协议栈转发逻辑被 datapath 接管。
外部数据包进入 VM 的完整路径(有 OVS 时),把 br-ex
、br-int
、vnetX
等关键点。
[ 外部主机 ]
│
▼
[ 物理网卡 eno12399 ]
│ (驱动收包)
▼
[ 内核 net_device ]
│
▼
[ OVS datapath (openvswitch.ko) ]
│
│ flow table 查找:
│ - 从物理口进来 → 应该交给 br-ex
▼
[ br-ex (OVS bridge) ]
│
│ flow 规则:包要转发到 br-int
▼
[ OVS datapath 继续处理 ]
│
▼
[ br-int (OVS bridge) ]
│
│ flow 规则:根据 VM 的 MAC/IP
│ → 找到对应的虚拟端口 vnetX
▼
[ vnetX (tap 设备,挂在 VM 上) ]
│
▼
[ 虚拟机 eth0 ]
│
▼
[ VM 应用收到数据包 ]
路径就是倒过来:
VM eth0 → vnetX → br-int → datapath 查 flow → br-ex → datapath 查 flow → eno12399 → 外部网络。
所以核心总结: