2. OpenFlow协议规范精读
OpenFlow 是 SDN 控制平面与数据平面之间的南向接口协议,其规范由 ONF(Open Networking Foundation)维护。要真正读懂 OpenFlow,不能只记住“控制器下发流表”这句话,而必须理解三个层次:协议消息如何封装与交互、流表如何组织匹配与处理规则、端口/组表/计量表如何扩展转发能力。本节以 OpenFlow 1.0、1.3、1.5 三个代表性版本为主线,逐层拆解这些核心概念。
一、版本演进与消息类型
OpenFlow 1.0 定义了最基础的消息集合,1.3 是部署最广泛的长期支持版本,1.5 则进一步补充了出口表、计量表增强等能力。三个版本的消息都可分为三大类:
- Controller-to-Switch(控制器到交换机):由控制器主动发起,如
OFPT_FEATURES_REQUEST查询交换机能力、OFPT_FLOW_MOD增删改流表、OFPT_PACKET_OUT让交换机直接发出指定报文、OFPT_STATS_REQUEST读取统计信息。 - Asynchronous(异步):交换机主动上报,如
OFPT_PACKET_IN把无法匹配的报文上送控制器、OFPT_FLOW_REMOVED通知流表被删除、OFPT_PORT_STATUS报告端口状态变化。 - Symmetric(对称):双方均可发起,如
OFPT_HELLO用于版本协商、OFPT_ECHO_REQUEST/REPLY用于保活、OFPT_ERROR用于错误通告。
版本协商是建立连接的第一步:双方各自发送携带最高支持版本的 HELLO,取两者交集的最小版本作为会话版本。例如控制器支持 1.5、交换机支持 1.3,则最终使用 1.3。若没有交集,交换机会回复 OFPT_ERROR 并终止连接。
二、流表结构:匹配域、优先级与指令集
流表是 OpenFlow 的核心数据结构。1.0 只有单级流表,1.3 起引入多级流表(Table 0 到 Table N),报文按 table_id 顺序逐级匹配。每条流表项(flow entry)由以下字段构成:
- 匹配域(Match Fields):1.0 使用固定结构,支持入端口、以太网源/目的、VLAN、IP 源/目的、TCP/UDP 端口等;1.3 起改为 TLV 形式的 OXM(OpenFlow Extensible Match),可匹配更多字段,如 IPv6、MPLS、隧道 ID、元数据
metadata。 - 优先级(Priority):数值越大越优先,同优先级下由交换机决定匹配顺序。
- 计数器(Counters):统计匹配报文数和字节数。
- 指令集(Instructions):1.0 中称为动作(Actions),1.3 起统一为指令,包括
Goto-Table、Apply-Actions、Write-Actions、Clear-Actions、Write-Metadata、Meter。 - 超时(Timeouts):
idle_timeout与hard_timeout,到期后流表项自动删除并触发FLOW_REMOVED。 - Cookie:控制器自定义的标识,便于批量删除或统计。
需要特别区分 Apply-Actions 与 Write-Actions:前者立即执行动作,后者把动作写入动作集,等报文离开流水线时统一执行。若同时存在 Goto-Table,则先跳转,动作集在后续表中继续累积。
三、指令与动作
动作决定报文如何被处理,常见动作包括:OUTPUT(从指定端口发出)、DROP(丢弃)、SET_FIELD(修改字段,如改 VLAN、改目的 MAC)、PUSH_VLAN/POP_VLAN(压入/弹出 VLAN 标签)、GROUP(交给组表处理)、METER(交给计量表限速)。1.0 的动作直接挂在流表项上,1.3 起动作被封装进指令,结构更清晰。
四、端口、组表与计量表
端口(Port)是报文进出的逻辑或物理接口。除物理端口外,OpenFlow 还定义了特殊端口:ALL(除入端口外所有端口)、CONTROLLER(上送控制器)、LOCAL(交换机本地协议栈)、IN_PORT(从入端口原路返回)、FLOOD(泛洪)。
组表(Group Table)用于实现组播、负载均衡和快速故障切换。组类型包括:ALL(复制到所有桶)、SELECT(按哈希选一个桶)、INDIRECT(固定单桶)、FF(快速故障切换,第一个存活桶)。每个桶包含动作集和权重。
计量表(Meter Table)用于限速与统计,1.3 引入。计量表由 meter_id 标识,包含多个 band,每个 band 定义速率阈值 rate、突发 burst_size 和动作(如 DROP 或 DSCP_REMARK)。流表项通过 Meter 指令引用计量表,实现按流限速。
五、版本差异速查
1.0 与 1.3 的关键差异在于:1.0 只有单级流表、动作直接挂在流表项、匹配字段固定;1.3 引入多级流表、OXM 可扩展匹配、指令与动作分离、组表与计量表、以及 metadata 在表间传递。1.5 进一步增加了出口表(Egress Table)、OFPT_CONTROLLER_STATUS 等消息,并增强了计量表与组表的灵活性。实际开发中,若控制器与交换机都支持 1.3,优先使用 1.3,因为其生态最成熟、文档最完整。
OFPT_HELLO → OFPT_FEATURES_REQUEST/REPLY → OFPT_FLOW_MOD → OFPT_PACKET_IN 这条主线,再逐步展开流表字段与指令细节。用 Wireshark 抓取 OpenFlow 报文,对照规范逐字段查看,比单纯阅读文本效率高得多。
六、一个可观察的示例
假设控制器向交换机下发一条流表项:匹配 in_port=1, eth_type=0x0800, ipv4_dst=10.0.0.2,优先级 100,指令为 Apply-Actions: SET_FIELD(eth_dst=00:11:22:33:44:55), OUTPUT:2,idle_timeout=30。当端口 1 收到目的 IP 为 10.0.0.2 的报文时,交换机会修改目的 MAC 并从端口 2 发出;若 30 秒内无匹配报文,该流表项被删除并上报 FLOW_REMOVED。通过 OFPT_STATS_REQUEST 查询该流表项的 packet_count 与 byte_count,即可验证转发是否生效。