转发表发生变化后,报文可能换一个出口,也可能在更高优先级规则处被丢弃。SDN 把控制逻辑与转发执行分开,OpenFlow 定义控制器操作交换机表项的协议,P4 则描述可编程包处理管线;三者不能当作同义词。

第 10 篇讨论路由器查表与转发,第 30 篇讨论 Linux 主机路径。本篇用固定软件模型验证规则变化,不把模型结果当作 Open vSwitch、P4 软件交换机或硬件 ASIC 的运行证据。

控制面安装规则,数据面逐包执行

OpenFlow 交换机包含一个或多个流表。流表项通常具有匹配字段、优先级、计数器和指令;报文按管线匹配后执行输出、修改、丢弃或转入下一张表等动作。表未命中时的行为也必须由配置或规范语义决定。

SDN 控制器根据拓扑和策略计算规则,再通过南向接口下发。控制器“希望安装”与交换机“已经安装并用于报文”是两个事件,需要事务回复、表项读取和数据面探测分别取证。

P4_16 描述 parser、可编程 control 和 deparser 等抽象。P4 程序能表达什么还受目标架构、表容量、动作能力、编译器和硬件资源限制。可编程不等于任意程序都能以线速运行。P4 语言定义表的匹配类型和抽象行为,P4Runtime 则是管理 P4 数据面实体的一种控制面 API;它们也不能与 OpenFlow 的流表规则直接换名。

模式提炼:程序、表项与报文结果三层对齐

管线定义 + 运行时表项 + 输入报文 = 数据面动作

只检查 P4 源码会漏掉运行时表项,只检查控制器状态会漏掉设备拒绝或部分更新,只发一个探测包又无法证明所有匹配域正确。

固定规则的前后对照

模型初始有两条前缀规则:10.0.0.0/24 → port 1,10.0.1.0/24 → port 2,其他目的地址丢弃。为了让输出可重复,这个 Python 模型自定义了选择语义:先选数值最大的优先级,并列时再选最长前缀,若仍并列则选输入中较早的规则。这是教学约定,不是 OpenFlow 的通用行为。

更新后新增 10.0.0.42/32 → drop,并把 10.0.1.0/24 的出口改为 port 3。于是目的 10.0.0.42 从 port 1 变成丢弃,10.0.1.9 从 port 2 改到 port 3,未匹配地址继续丢弃。

这个前后差异证明模型遵守指定匹配与动作,不证明 OpenFlow bundle 原子性、控制器收敛顺序或真实硬件没有过渡状态。规则更新期间的包可能看到旧状态、新状态或实现允许的中间状态,必须由具体设备和更新机制说明。

OpenFlow 与 P4 的选择规则

OpenFlow Switch Specification 1.3.5 §5.3 要求选中匹配项中优先级最高的一条;如果多条匹配项拥有相同的最高优先级,规范明确把选择结果定义为 undefined。因此,对同时命中的 /24 和 /32 设置相同最高优先级时,不能用“前缀更长”预测 OpenFlow 必选 /32。控制器应用不同优先级消除这种重叠歧义;OFPFF_CHECK_OVERLAP 能在添加流表项时请求重叠检查,但不会把歧义改写成最长前缀规则。

P4_16 1.2.5 §14.2.1.1 把 lpm 定义为一种最长前缀匹配类型,掩码中连续 1 越多,自动优先级越高;§14.2.1.4.1 进一步说明,只有 exact/lpm 字段的表在多个前缀匹配时由最长前缀获胜。这条 P4 lpm 语义不能倒推为 OpenFlow 同优先级表项的规则。P4Runtime 官方仓库 v1.4.0 标签的 §9.1 对 optional/ternary/range 表项使用数值优先级,并同样警告:同优先级的重叠匹配在数据面不具有确定性。

素材中的反例让 10.0.2.0/24 → OUTPUT:4 与 10.0.2.42/32 → DROP 拥有相同优先级。教学模型依自定义规则选中 /32 并丢弃 10.0.2.42;对 OpenFlow 1.3.5 而言,这一输出没有规范保证。

软件交换模型验证

switch_model.py 读取两版规则、固定报文和同优先级重叠反例,输出每个报文的命中规则及动作。输出中的 custom_selection 和 openflow_1_3_5_boundary 分别标记模型约定与规范边界;后者是规范摘要,不是代码验证结果。

1
2
python3 source/_posts/2026-09-24-计算机网络E04-SDN与可编程数据面/switch_model.py --help
python3 source/_posts/2026-09-24-计算机网络E04-SDN与可编程数据面/switch_model.py

素材包括规则与报文、软件交换模型、前后对照结果、资料与运行记录和审阅记录。

条件、限制和反例

逻辑规则正确不等于硬件可部署。TCAM 容量、匹配宽度、动作资源、管线级数和芯片目标可能让程序无法编译或表项无法安装。

控制面集中不等于单个进程承担一切。控制器可以分布式部署,设备也可能保留本地协议和快速故障处理。

命中计数增长不证明接收端处理成功。计数器只对应所在观察点,后续端口、链路和接收协议栈仍可能丢弃报文。

练习

练习一:在 /24 转发规则之上增加 /32 丢弃规则,分别说明 /32 优先级高于、低于和等于 /24 时教学模型怎样选择;再按 OpenFlow 1.3.5 §5.3 单独回答这三种情形,不得把两套语义混在一起。

练习二:控制器报告更新成功,但探测包仍走旧出口。列出控制面确认、交换机表项、端口计数和接收端抓包四个观察点能排除的解释。

模式速查表

层次 工件 验证问题
意图 控制器策略 想要什么路径
管线 OpenFlow/P4 定义 能匹配和执行什么
运行时 流表或 P4Runtime 实体 实际安装了什么
数据面 计数、抓包、接收结果 报文实际经历什么

官方一手参考资料

验证边界

已验证:Python 3 标准库实现固定 match-action 软件交换模型,验证两版规则下的命中、输出和丢弃差异,并验证自定义同优先级决胜规则的确定性输出,验证类型为 STATIC。规范阅读支持语义对照,代码不验证 OpenFlow 或 P4 实现的行为。

NOT_RUN:当前环境没有 Open vSwitch、OpenFlow 控制器、P4 编译器、BMv2 或可编程网卡/交换芯片,未验证真实规则下发、计数器、更新一致性、硬件容量和线速性能。