本节摘要:OpenFlow 交换机 = 协议代理 + 流水线抽象 + 底层转发引擎。软件交换机把流水线直接跑在内核或用户态,硬件交换机则要把 OpenFlow 语义翻译到 TCAM 与 ASIC 的限制里。本节拆解这条翻译链,解释"支持 1.3"在不同设备上含义天差地别的原因,以及能力协商的正确姿势。
阅读完本节,你应当能够:

软件交换机(OVS 为代表):流水线在用户态完整实现,表深度近乎无限,任何 OXM 字段都能匹配。代价是吞吐受 CPU 限制,适合服务器侧与实验。OVS 还有个聪明设计——内核里只放"微流"精确匹配缓存,首包才上升到用户态完整流水线,摊薄了开销。
硬件交换机:协议语义要翻译进 TCAM。TCAM 的物理特性决定了三个硬约束:
所以"支持 OpenFlow 1.3"在软件交换机上意味着全集,在商用芯片上可能意味着"1.3 的一个子集 + 若干限制条款"。这就是能力协商存在的意义。
1.3 的 Table-Features 消息族让交换机逐表申报:每张表支持哪些匹配字段、哪些指令、能跳到哪些下一级表、最大条目数。控制器应该在握手后立刻拉取(Multipart-Request type=TABLE_FEATURES),把策略编译约束在这些边界内。
Table-Features 上报示例(简化) table 0: match 支持 in_port, eth, ipv4 ; instructions 支持 APPLY, GOTO next_tables = 1,2 ; max_entries = 4096 table 1: match 仅 ipv4_dst ; 不支持 GOTO → 控制器必须把"贴 VLAN"类操作编进 table 0
在实验台核对 OVS 的表能力:
sudo ovs-ofctl -O OpenFlow13 dump-table-features s1 sudo ovs-ofctl -O OpenFlow13 dump-tables s1
⚠️ 常见坑:按 datasheet 宣称的能力下发 Flow-Mod,交换机回 Error type=BAD_ACTION 或 FLOW_MOD_FAILED。正确姿势是策略编译器读 Table-Features 降级或拆分规则,而不是假设全集可用。
💡 关键直觉:软件交换机是"协议全集的解释器",硬件交换机是"协议子集的编译目标"。写控制器应用时要同时当两种角色的教练。
"别信 datasheet,信报文"的实操就是 Table-Features 查询。OVS 对此有部分支持,能看到每张表能匹配哪些字段、支持哪些指令:
sudo ovs-ofctl -O OpenFlow13 dump-table-features s1 | head -30 # Wildcards: ...
这张清单的用途是控制器的"落点适配":下发前逐字段核对,匹配字段不被支持就提前改写策略(比如硬件不支持 tcp_src 掩码,就升格为五元组精确匹配或降格为 IP 级匹配),而不是等一条条 Error 回来再补救。真实硬件交换机上这份清单往往比 OVS 短得多——TCAM 宽度限制会体现为 matching 列表里字段组合的缺失,这正是"支持 1.3"三个字在不同设备上含义天差地别的机械原因。采购评审时把 dump-table-features 的输出要过来对着设计稿核一遍,能拦下一大批上线后才暴露的能力性缺陷。
OVS 的内核模块维护微流(microflow)缓存,命中内核路径的包根本不进用户态完整流水线。这带来一个抓包可见的现象:交换机刚启动时 CPU 偏高(首流都要走用户态),之后归零。验证方法是观察 OVS 日志或用 ovs-appctl 查看 dpif 的流缓存:
sudo ovs-dpctl dump-flows | head -5 # packets:3186, bytes:333, used:0.001s, actions:2
注意区分两套 dump:ovs-ofctl dump-flows 看的是 OpenFlow 逻辑流表,ovs-dpctl dump-flows 看的是内核数据路径的微流。前者是控制器的合同,后者是转发面的实际执行。两套输出对不上时(逻辑表有条目、微流不增长),问题通常在快慢路径的同步,这是 OVS 特有、却让无数人误判为"控制器没下发"的经典现场。
交换机之间怎么连成网、控制器怎么"看见"拓扑?下一节从 LLDP 报文找答案。