本节摘要:OpenFlow 应用是纯事件驱动程序:订阅交换机事件(Packet-In、Port-Status、Flow-Removed),查询拓扑服务,输出三类写操作(Flow-Mod、Group-Mod、Packet-Out)。本节以一个带最短路径路由的完整 Ryu 应用为例走通开发循环,并给出调试与上线的工程清单。
阅读完本节,你应当能够:
所有 OpenFlow 应用都是同一个骨架:
应用骨架 { 事件入口: Packet-In / Port-Status / Flow-Removed / SwitchFeatures 状态查询: 拓扑(邻接表) · 主机位置库 · 交换机能力(Table-Features) 写操作: Flow-Mod(铺路) · Group-Mod(组播/冗余) · Packet-Out(救急) 自身状态: 主机表 · 已装规则索引(cookie 管理) }
下面是完整的可运行应用(Ryu),实现"首包上线时沿最短路逐台铺流表":
from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER, set_ev_cls from ryu.topology import event as topo_event # 交换机/链路事件 import networkx as nx class RoutableL2(app_manager.RyuApp): _CONTEXTS = {"networkx": lambda app: None} # 简化:全局图对象 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.graph = nx.Graph() # DPID 邻接图 self.hosts = {} # MAC → (dpid, port) @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) def features(self, ev): dp = ev.msg.datapath # Table-Miss:所有未知流量上送控制器(2.3 节的第一条规则) match = dp.ofproto_parser.OFPMatch() inst = [dp.ofproto_parser.OFPInstructionActions( dp.ofproto.OFPIT_APPLY_ACTIONS, [dp.ofproto_parser.OFPActionOutput(dp.ofproto.OFPP_CONTROLLER, dp.ofproto.OFPCML_NO_BUFFER)])] mod = dp.ofproto_parser.OFPFlowMod(datapath=dp, priority=0, match=match, instructions=inst) dp.send_msg(mod) @set_ev_cls(topo_event.EventLinkAdd) def link_add(self, ev): l = ev.link self.graph.add_edge(l.src.dpid, l.dst.dpid) @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def packet_in(self, ev): msg = ev.msg; dp = msg.datapath pkt = dp.ofproto_parser.OFPMatch.ethernet_pkt(msg.data) # 概念示意 src_mac, dst_mac = pkt.src, pkt.dst self.hosts.setdefault(src_mac, (dp.id, msg.match["in_port"])) if dst_mac not in self.hosts: return self._flood(dp, msg) # 目的未知:泛洪 path = nx.shortest_path(self.graph, dp.id, self.hosts[dst_mac][0]) self._install_path(path, src_mac, dst_mac) self._forward_first_packet(dp, msg, path) def _install_path(self, path, src, dst): for i, dpid in enumerate(path): # 沿途每台交换机装双向条目,cookie 标记本流便于回收 ... # Flow-Mod:match=eth_src/dst,output=下一跳端口
这个应用用到的全是前四章解剖过的零件:Table-Miss 兜底(2.3)、Packet-In 事件(2.2)、Flow-Mod 铺路(2.2)、拓扑图来自 LLDP 事件(3.3)、cookie 标记用于批量回收(2.3)。读懂它,你就读懂了所有 OpenFlow 应用的构造方式。
应用出 bug 时按顺序上工具:

⚠️ 常见坑:忘了处理 Packet-In 的洪峰(新虚机批量启动)。上送速率要有上限与合并策略,否则控制器 CPU 被首包打穿。
💡 关键直觉:OpenFlow 应用 = 事件回调 + 一张全局图。把状态从回调里拿出来集中管理,是应用能长大的前提。
应用怎么和现网里的其他技术共存?下一节讲集成。