摘要
SD-WAN 网络通过将控制平面与转发平面分离来实现网络的管理和状态在逻辑上集中到一起,使网络获得前所未有的可编程、可控制和自动化能力,让用户可以很容易根据业务需求,建立高度可扩展的弹性网络。要实现 SD-WAN 网络的转控分离架构,就需要在 SD-WAN 控制器与数据转发层之间建立一个通信接口标准,OpenFlow 便是完成这样功能的标准协议之一,尽管它最早是被用于 SDN 中。本文首先介绍了 OpenFlow 的发展历程以及各阶段的主要特性,其次对协议的主要结构进行详细说明,最后结合具体示例详细解释了主要数据结构的用法。
发展
2008年,斯坦福大学成立了一个名为 Clean Slate 的特别工作小组,这个小组在2009年提出了一个可以满足 SDN 网络转控分离架构的标准协议,即OpenFlow 1.0,同时该小组还开发出了 OpenFlow 的参考交换机和 NOX 控制器。OpenFlow 协议允许控制器直接访问和操作网络设备的转发平面,这些设备可以是物理设备,也可以是虚拟的路由器或者交换机。
OpenFlow 1.0问世后不久就引起了业界关注。2011年3月21日,德国电信、脸书、谷歌、微软、雅虎等公司共同成立的了ONF(Open Networking Foundation)组织,旨在推广 SDN,并加大 OpenFlow 的标准化力度。芯片商Broadcom,设备商Cisco、Juniper、HP等,各数据中心解决方案提供者以及众多运营商纷纷参与。该组织陆续制定了OpenFlow 1.1、1.2、1.3、1.4、1.5等标准,目前仍在继续完善中,且随着越来越多的公司加入ONF,OpenFlow及SDN技术的影响力也越来越大。
协议版本 | 主要功能 |
---|---|
OpenFlow 1.0 | 单流表、IPV4 |
OpenFlow 1.1 | 多级流表、组表、流水线处理、MPLS、VLAN |
OpenFlow 1.2 | 多控制器、IPV6基本头 |
OpenFlow 1.3 | 计量表、版本协商能力、IPV6扩展头 |
OpenFlow 1.4 | 流表同步机制、协议消息完善 |
OpenFlow 1.5 | 流量识别、出端口流水线 |
关键构成
流
流(Flow)就是具有相同特征的数据包集合,例如,源 MAC 地址为 MAC_A,目的 MAC 地址为 MAC_B 的所有数据包集合就可以视为一条流,可见流具有方向性。有别于传统网络中路由器基于数据包独立转发的模式,使用 OpenFlow 的网络是基于流进行转发的,即对相同特征的数据包集合采用同样的处理。
流表
流表(Flow Table)是 OpenFlow 中最重要的一张表,它用于指导 OpenFlow 交换机对收到的数据包进行转发,相当于二层的 MAC 地址表和三层的路由表。在 OpenFlow 1.1 以后的版本中,每台交换机支持使用多张流表,构成流水线处理,从而完成对数据包更为复杂的处理。流表由若干条流表项(Flow Entry)组成,流表项结构主要包含以下几个部分:
- 匹配域(Match Fields):用于定义某条流,包含一个或多个匹配项,如源地址、目的地址、协议类型等
- 指令(Instructions):表示对该条流应该如何处理
- 优先级(Priority):表示该流表项的优先匹配程度
- 计数器(Counters):用于统计该条流的信息
- 生存时间(Timeouts):表示流表项的有效存活时间
- Cookie:控制器设置用来过滤被流统计、流修改和流删除操作请求影响的流表项
- 标志(Flags):用于流表项管理
流表项最为重要的两项为匹配域和指令,当 OpenFlow 交换机收到一个数据包后,会首先将它包头解析后与流表中流表项匹配域进行匹配,匹配成功则执行对应指令,因此流表可以简化理解为 key-value 形式的{匹配域-指令}表。指令(Instruction)可以分为三类:
- 更新动作集(Action Set):添加、修改、清空动作集
- 修改流水线处理次序:从序号低的表跳转到序号高的表
- 处理数据包:执行立即在数据包上生效的动作列表
指令按 OpenFlow 交换机是否必须支持可分为必须动作(RequiredActions)和可选动作(OptionalAction),交换机只需要支持 RequiredActions 即可,在其连接到控制器时将被告知哪些是可选动作。当一个报文匹配上流表项时,会执行表项包含的指令集:
| 指令 | 是否可选 | 功能 | | Apply-Actions | 可选 | 立即执行动作列表(Action List)中的动作目不改变动作集(Action Set ) | | Clear-Actions | 必须 | 清空动作集 | | Write-Actions | 必须 | 添加一条动作到动作集或修改动作集中的动作 | | Goto-Table | 必须 | 跳转到指定流表 | | Write-Metadata | 可选 | 更新元数据,在多个流表之间传递信息 | | Stat-Trigger | 可选 | 若流的某个统计信息超过设定闯值,生成一个事件通知控制器 | | Meter | 可选 | 交由计量表处理,对报文执行指定的测量 |
当流表项的指令集中不包含 GoTo-Tabl e时,立即执行相关联的动作集:
动作 | 是否可选 | 功能 |
---|---|---|
Output | 必须 | 转发报文到指定 OpenFlow 端口 |
Group | 必须 | 交由组表处理,执行指定组的处理 |
Drop | 必须 | 丢弃报文 |
Set-Queue | 可选 | 将报文送至输出端口的指定队列 |
Push-Tag/Pop-Tag | 可选 | MPLS、VLAN 的 tag 处理 |
Set-Field | 可选 | 修改报文头相应字段 |
Copy-Field | 可选 | 在报文头字段之间进行拷贝 |
Change-TTL | 可选 | 修改 IPV4 和 MPLS 的 TTL 或 IPv6 的 Hop Limit |
组表
每台OpenFlow交换机只有一张组表(Group Table),组表由若干条组表项(Group Entry)组成,具有将多个端口定义为一个组的能力,从而实现广播、多播,负载均衡、链路聚合、故障转移等。表项中定义了一个动作桶(Action Bucket)列表,用于描述转发到指定端口前对数据包的处理。组表项结构主要有:
- 组号:用于标识一个组
- 类型:指定组的动作,根据不同组类型从动作桶列表中选取不同的桶执行
- 计数器:统计组表项处理的数据包数
- 动作桶列表:包含一个或多个动作桶,每个动作桶包含一个动作集
其中组表项类型有:
- All:执行桶列表中的所有动作,可以用于组播
- Indirect:只包含一个动作桶的组表项,转发效率更高,可以用于路由聚合
- Select:根据某种算法(Hash、轮询等)选择一个桶执行,用于实现网络负载均衡、链路聚合等
- Fast Failover:选择第一个有效的桶执行,可用于实现故障转移
- Action Buckets:随机选择一个桶执行
计量表
计量表(Meter Table)可以对流进行测量,从而为流提供QoS功能,如限速、DiffServ 等。每台 OpenFlow 交换机只有一张计量表,由若干计量表项(Meter Entry)组成,每个计量表项包含编号、计量带列表、计数器等组成,其中计量带(Meter Band)定义了带宽阈值和数据包处理方式(丢弃、DSCP标记),每个计量带包含类型、宽带阈值、计数器、类型参数等部分。
安全通道和消息
安全通道(Secure Channel)是连接交换机和控制器的接口,所有的安全通道消息都必须遵守 OpenFlow 协议。OpenFlow 消息按照发送的位置可分为三大类,每一大类中有若干子消息:
- Controller-to-Switch消息:由控制器发起,用于直接管理或监视交换机的状态
- Features:用于获取交换机特性
- Configuration:用来配置和查询交换机参数
- Modify-State:用来修改交换机状态信息,如增删改流表项、组表项等
- Table-Mod
- Flow-Mod:用于流表操作,包括添加、删除、修改流表项
- Group-Mod
- Port-Mod
- Meter-Mod
- Read-State:用来读取交换机状态信息(当前配置、统计信息等)
- Port-Stats:用于控制器查询交换机的端口计数器,从而获取端口的统计信息
- Flow-Stats
- …
- Packet-Out:用来指定交换机将数据包从指定端口转发出去
- Barrier:在不同消息之间使用,确保操作顺序执行
- Role Request:控制器用于询问或设置自身在交换机中的角色,常用于交换机与多控制器连接的场景
- Asynchronous-Configuration:控制器设置异步消息过滤器,只接收感兴趣的异步消息,一般在多控制器场景下使用
- Asynchronous(异步)消息:由交换机发起,用以提醒控制器更新网络事件和交换机状态变化的状态
- Packet-In:将数据包交给控制器处理,一般流表匹配中出现Table-Miss时或流表项显示指定将数据包交给控制器时,触发该消息
- Flow-Removed:通知控制器,流表项被删除;流表项超时或控制器删除流表项时触发该消息(需要在交换机配置时使能该消息)
- Port-status :通知控制器,交换机端口状态发生变化
- Role-status:通知控制器,控制器在交换机中的角色发送变化
- Controller-Status:通知控制器,OpenFlow通道状态发生变化
- Flow-monitor:通知控制器,流表发送变化
- Symmetric(对称)消息:可以由交换机或控制器发起而无须邀请
- Hello:建立控制器与交换机之间的OpenFlow通道
- Echo:检测交换机与控制器之间的连接状态或测量OpenFlow通道的时延和带宽
- Error:用于通告错误
- Experiment:用于实验,测试新特性
使用案例
传统网络 VS OpenFlow网络
- 传统网络设备工作过程
假设主机 A 向主机 B 发送 IP 数据包,且所有路由表和 MAC 地址表中都有该数据包的相应表项,传统网络数据包转发流程如下:
- 路由器之间运行分布式路由协议构建路由表,收到数据包时会根据目的 IP 进行查表,查表成功则基于目的IP地址转发;查表失败则丢弃数据包
- 交换机根据自学习算法构建 MAC 地址表。查表成功则基于目的 MAC 地址转发;查表失败时,除入端口外其余所有端口转发出去
- OpenFlow 网络设备工作过程
假设主机 A 向主机 B 发送 IP 数据包,且 OpenFlow 交换机中流表为空:
- 交换机接收 IP 数据包
- 交换机解析数据包首部并查询流表,由于流表为空所以查询失败
- 交换机向控制器发送 Packet-In 消息询问路由信息
- 控制器为主机 A 发送给主机 B 的 IP 数据包计算路由
- 控制器通过 FlowMod 消息向交换机下发流表,交换机接收该消息后安装流表
- 控制器向交换机发送 Packet-Out 消息,指示交换机按照刚安装好的流表转发 IP 数据包
- 交换机收到 Packet-Out 消息后转发数据包
流表匹配示例
流表在解析数据包时,首先根据首部内容与流表项匹配域进行匹配,若一个数据包与多个流表项匹配成功,最后只与优先级最高的流表项进行匹配:匹配成功,则更新计数器并执行相应指令;匹配失败,若流表中没有设置 Table-Miss 流表项则直接丢弃数据包,若流表中设置有 Table-Miss 流表项(优先级为 0 且匹配域为 ANY ),则最后会匹配该表项,执行相应指令(如丢弃、交由控制器处理、交给下一张流表处理)。
假设主机 A 发送数据包给主机 B,使用单张流表的交换机处理数据包过程如上图所示:
- 交换机从 1 端口接收数据包
- 交换机解析数据包首部,并查询流表进行流表匹配,匹配第一条流表项,并执行相应指令
- 将数据包转发到交换机的 2 端口
多流表与流水线报文过滤示例
多级流表的出现一方面能够实现对数据包的复杂处理,另一方面又能有效降低单张流表的长度,提高查表效率。在多级流表中,每张表都有序号,数据包通过跳转指令按照流表序号递增的方向在多个流表之间进行匹配,这样就构成了一条有方向的流水线。流水线处理可以在 OpenFlow 交换机的入端口或出端口上进行,当流水线上只有一张流表时,就简化成单流表匹配的情况。多级流表一般处理流程如下图所示:
由上图可知,流水线处理过程可以分为以下几个阶段:
- 流水线处理开始:交换机接收数据包后,执行入端口的流水线处理,同时给该流水线分配一个动作集(Action Set)
- 流表匹配
- 匹配成功,则更新相应流表项的计数器,完成对该条流的统计工作,执行流表项对应的指令
- 匹配失败,则判断数据包能否匹配到 Table-Miss 流表项(优先级为0且匹配域为ANY),可以匹配就根据 Table-Miss 流表项处理数据包(丢弃数据包、转发给控制器、交给下一个流表处理);不可以匹配则直接丢弃数据包
- 流水线处理结束:若当前不是执行跳转指令,则执行出端口的流水线处理,然后结束流水线处理
假设使用多级流表实现主机 A 到主机 B 的所有 TCP 报文正常转发,UDP 报文均丢弃,从而实现对不同流的细粒度控制:创建三个流表,流表 0 匹配 A 到 B 的流,流表 2 过滤报文类型,如下图所示。
组表多播使用示例
假设使用组表实现主机 A 使用多播方式向主机 B 和 C 发送 IP 数据包:先通过流表匹配主机 A 到 B、C 组的匹配,再通过组表中的桶完成报文到端口的转发,如下图所示。
计量表实现限速示例
假设使用计量表实现将目的 IP 地址为 10.0.0.2 的流限速为 z,且当前测得该流的数据包速率为 x:先通过流表实现对该流的匹配,再通过计量表对当前网速进行检查,当 x>z 时通过计量带定义的方式(如丢弃)实现限速。