OpenFlow:南向接口协议

主要作用:通过下发流表项来对数据平面设备的网络数据处理逻辑进行编程,从而实现可编程定义的网络。

版本:1.0和1.3(LTS)为业内常用版本。

概述

  • OpenFlow可以存在多个流表,但必须从Table 0开始匹配;
  • OpenFlow交换机可通过建立安全通道时的Feature消息确认自身所支持的流表个数;
  • 数据包与任何一个流表都不匹配的情况称为Table-Miss,此时利用packet-in消息转发到控制器,或丢弃数据包。

实例

数据包的处理过程:

OpenFlow 1.0

协议交互过程:

版本协商:

  • 当OF安全通道建立起来后,双方必须首先发送HELLO消息。TCP:端口6633
  • Hello消息中只包含OpenFlow Header:
    OpenFlow Header中的version字段为发送方所支持的最高版本;
    OpenFlow协议(OpenFlow 1.0中版本信息为0x01)
    通常情况下,安全通道中使用的版本号为:控制器发送版本号与交换机版本号中较小的一个
    如果双方协商版本不一致时,应发送Error消息后断开连接
  • 如果双方OpenFlow版本可以兼容,则OpenFlow连接建立成功。

获取交换机特性:

  • OpenFlow连接建立后,控制器最需要获得交换机的特性信息,交换机的特性信息包括交换机的ID(DPID),交换 机缓冲区数量,交换机端口及端口属性等等
  • 控制器向交换机发送Features Request消息查询交换机特性 ,Features Request消息只包含OpenFlow Header。
  • 交换机在收到Features Request消息后返回Features Reply消 息,Features Reply消息包括OpenFlow Header 和Features Reply Message

设置交换机:

1
2
3
4
5
6
7
8
9
10
11
12
struct ofp_switch_config{
struct ofp_header header;
uint16_t flags;
uint16_t miss_send_len;
};

enum ofp_config_flags{
OFPC_FRAG_NORMAL = 0, //No special handing for fragments
OFPC_FRAG_DROP = 1, //Drop fragments
OFPC_FRAG_REASM = 2, //Reassemble (only if OFPC_IP_REASM set)
OFPC_FRAG_MASK = 3
}
  • 第二个属性为miss_send_len,用来指示 当一个交换机无法处理的数据包到达时, 将数据包的发给控制器的最大字节数
  • GET_CONFIG消息和响应

Packet-in 事件:

触发情况:

  • 流表中没有相应的匹配流表项:

    1.交换机会根据SET_CONFIG消息中miss_send_len设置的值为最大的数据包数据封装packet-in发送至OpenFlow控制器

    2.同时数据包缓存到交换机中等待处理。

  • 交换机流表所指示的action列表中包含转发给控制器的动作(Output=CONTROLLER):

此时数据包不会被缓存在交换机中,而是将整个包封装packet-in消息发送给控制器处理。

Flow-Mod 消息:

作用:控制器对OpenFlow交换机进行流表项的设置的消息

通过Flow-Mod消息,可对流表项进行添加、删除、变更 设置等操作:

名称 说明
ADD 增加一个新的流表项
MODIFY 修改所有匹配的流表项
MODIFY_STRICT 修改严格匹配的流表项
DELETE 删除所有匹配的流表项
DELETE_STRICT 删除严格匹配的流表项

流表项的移除

  • 定时器计时结束:

    Idle_timeout(单位s):计算的是没有流匹配发生的最大空闲时间
    Hard_timeout(单位s):计算的是流表项在流表中的总的生存时间
    一旦到达时间期限,交换机将自动删除该流表项,同时发送一条流删除消息

  • 控制器主动删除流表项:

    控制器通过下发DELETE_STRICT、 DELETE等指令相关的协议 消息主动删除流表项

响应Packet-in 事件

​ 控制器向交换机写入了一条与数据包相关的流表项,并且指定该数据包按照此流表项的aciton列表处理。

Packet-out 消息:

1
2
3
4
5
6
7
8
struct ofp_packet_out{
struct ofp_header header;
uint32_t buffer_id; // ID assigned by datapath (-1 if none)
uint16_t in_port; // Input port (OFPP_NONE if none)
uint16_t actions_len; // Size of action array in bytes
struct ofp_action_header action[0]; //Actions
/* uint8_t data[0]; */ // Packet Data (only buffer_id == -1)
}
字段 比特数 说明
buffer_id 32 数据包在交换机中的缓存区ID;值为-1时,在data字段添加数据包
in_port 16 当buffer_id为-1,且action 列表中指定了output=TABLE的动作,in_port将作为data段数据包的额外匹配信息进行流表查询
actions_len 16 指定action列表的长度,用来区分actions和data段
Data 任意大小 为一个缓存区,可以存储一个以太网帧(buffer_id=-1)

作用:控制器向OpenFlow交换机发送的包含数据包命令的消息
替代Flow-Mod消息(网络中数量很少的ARP、IGMP等报文,没必要下发流表项去处理)
将OpenFlow控制器创建的数据包发送至OpenFlow交换机。buffer_id=-1
应用场景:经典的是链路发现

控制器向一个交换机A发送Packet-Out消息(携带LLDP指示),buffer_id=-1,actions为从交换机A的1端口转发

交换机A接收到packet-out消息后,根据actions的指示 从1端口发送包含在packet-out消息中的LLDP帧

发出这个数据包的端口连接一个OpenFlow交换机B, 对端的交换机B会产生一个(添加了此LLDP帧的) Packet-In消息,然后将这个特殊的数据包上交给控制器

控制器根据OpenFlow交换机发送的Packet-in消息中包 含的消息,构建拓扑视图。

协议消息类型:

类型 说明
controller-to-switch 由控制器发起,用来管理或获取OpenFlow交换机的状态
asynchronous 由OpenFlow交换机发起,用来将网络事件或交换机状态变化更新到控制器
symmetric 由交换机或控制器发起

controller-to-switch:OpenFlow交换机接收并处理可能 发送或不需要发送的应答消息

名称 说明
Features 在建立TIS会话时,控制器发送features请求消息 给交换机,交换机需要应答自身支持的功能
Configuration 控制器设置或查询交换机上的配置参数,交换机仅需要应答查询消息
Modify-state 控制器管理交换机流表项和端口状态等
Read-state 控制器向交换机请求诸如流表、端口、各个流表项等方面的统计信息
Packet-Out 控制器通过交换机指定端口发出数据包
Barrier 控制器通过barrier请求及相应报文,确认相关消 息已经被满足或收到完成操作的通知

asynchronous:单向消息,不需要控制器应答;向控制器通知收到报文、状态变化以及出席错误等事件信息

名称 说明
Packet-in 上面已经讲过
Flow-removed 交换机中流表项因为超时或收到修改删除命令等原因被删除掉,会触发Flow-removed 消息
Port-status 端口状态变化,触发Port-status消息
Error 发生的问题

symmetric:双向对称消息,用于建立连接、检测对方是否在线等

名称 说明
Hello 用于在OpenFlow交换机和控制器之间发起连 接建立
Echo 交换机和控制器均可以向对方发出Echo消息, 接收者则需要回复Echo reply。该消息用来协 商延迟、带宽、是否连接保持等控制器到 OpenFlow交换机之间隧道的连接参数
Vendor 用于OpenFlow交换机协商厂家自定义的附加 功能,为未来版本预留

OpenFlow 1.0 流表

示例:

  • OpenFlow交换机中可以有多个流表
  • OpenFlow1.0,能够匹配到的流表项只有1个
Header Fields Action Counters
报文头信息 必备动作+可选动作 数据包计数

Header Fields(包头域信息):除了进接口,传统2层到4层的寻址信息都出现在包头域中(MAC,IP,PORT)

Counters

针对交换机中的每张流表、每个流、每个设备端口、 每个转发队列进行维护,统计数据流量的相关信息

  • 针对每张流表:统计当前活动的表项数、数据包查询次数、数据包匹配次数等

  • 针对每个数据流:统计接收到的数据包数、字节数、数据流持续时间等

  • 针对每个设备端口:除统计接收到的数据包数、发送数据包数、接收字节数,发送 字节数等指标之外,还可以对各种错误发生的次数进行统计

  • 针对每个队列:统计发送的数据包数和字节数,还有发送时的溢出(Overrun) 错误次数等

Action

1
2
3
4
5
6
struct ofp_action_output{
uint16_t type; //OFPAT_OUTPUT
uint16_t len; //Length is 8
uint16_t port; //Output port
uint16_t max_len; //Max length to send to controller
}
  • OpenFlow交换机缺少控制平面的能力,因此需要用action来详细说明交换机将要对数据包 所做的处理

  • 每个流表项可以对应有零至多个action,如果没有定义转发动作,那么与流表项包头域匹 配的数据包将被默认丢弃

  • 同一流表项中的多个动作的执行可以具有优先级,但是在数据包的发送上并不保证其顺序

如果流表项中出现有交换机不支持的参数值,交换机将向控制器返回相应的出错息。

  • 必备动作:所有OpenFlow交换机都默认支持;可选动作:需要交换机告知控制控制器它能支持的动作

必备动作:

名称 说明
转发(Forward) 交换机必须支持将数据包转发给设备的物理端口及如下的一个或多个虚拟端口:
ALL:转发给所有出端口,但不包括入端口
CONTROLLER :OpenFlow数据包封装并转发给控制器
LOCAL:转发给本地的网络栈
TABLE:对packet_out消息执行流表的动作
IN_PORT:从入端口发出
丢弃(Drop) 交换机对没有明确指明处理动作的流表项,将会对与其所匹配的所有数据包进行默认的丢弃处理

在OpenFlow 1.0规范中,将Forward行动标记为OFPAT_OUTPUT。另外,将ALL、CONTROLLER、LOCAL、TABLE、NORMAL、IN_PORT、FLOOD作为表示输出目的地的虚拟端 口,分配了16比特的数值。

虚拟端口
OFPP_IN_PORT 0xfff8
OFPP_TABLE 0xfff9
OFPP_NORMAL 0xfffa
OFPP_FLOOD 0xfffb
OFPP_ALL 0xfffc
OFPP_CONTROLLER 0xfffd
OFPP_LOCAL 0xfffe
OFPP_NONE 0xffff

可选动作:修改域在OpenFlow只能修改ToS高六位,其他在1.1后才支持。

名称 说明
转发(Forward) NORMAL:利用交换机所能支持的传统转发机制(例如二层的MAC、VLAN信息或者三层的IP信息)处理数据包
FLOOD:遵照最小生成树从设备出端口洪泛发出,但不包括入端口
排队(Enqueue) 交换机将数据包转发到某个出端口对应的转发队列中,便于提供QoS支持
修改域(Modify-Field) 设置VLAN ID、VLAN优先级,剥离VLAN头
修改源MAC地址、目的MAC地址
修改源IPv4地址、目的IPv4地址、ToS位
修改源TCP/IP端口、目的TCP/IP端口

协议演进:

  • OpenFlow 1.3 字段增加优先级、超时定时器、Cookie

  • 增加多级流表,1.3提出在多流表每个表的最都增加Table-miss项

  • OpenFlow 1.1 后引入组表

    Group Identifier Group Type Counters Action Buckets
    组标识符 组类型 计数器 行动桶
    用于表示组的识别符。依据该识别符使用各组 指定组的动作。分别为all、select、indirect、fast failover四种 记录通过该组表项处理的数据包数 多个行动数据桶。各行动桶存储了多个执行行动和其对应的参数
    • 适合于实现广播或组播,或者规定只执行某些特定的操作集。

    • 其中,组类型规定了是否所有的动作桶中的指令都会被执行:

    所有(all):执行所有动作桶中的动作,可用于组播或广播

    选择(select):执行该组中的一个动作桶中的动作,可用于多路径

    间接(indirect):执行该组的一个确定的动作桶中的动作

    快速故障恢复(fast failover):执行第一个具有有效活动端口的动作桶中的指令

  • 1.3 增加的计量表(Meter Table):结构如下

    Meter Identifier Meter Bands Counters
    32位的无符号整数,用来唯一识别该计量表项 由计量带组成的无序列表,其中每个计量带都指明了其速率及处理数据包的方式 用于在报文被计量表项处理时更新相关计数

    Bands结构如下:

    Band Type Rate Counters Type specific arguments
    定义了数据包怎样被处理 用于选择计量带,定义了带可以运行的最高速率 当数据报文被计量带处理时,更新计数器 带类型的可选参数

    其中Band Type 有两种可选的类型:

    • Drop:通过丢弃数据包,定义带宽速率限制
    • Dscp remark :降低数据包的IP头中的DSCP字段丢弃的优先级,可用于定义简单的DiffServ策略
  • 匹配域更加丰富

  • 计数器更加丰富:

    OpenFlow 1.1增加了组表的概念,因此计数器相应增加了针 对每组、每个动作桶的相关统计。

    OpenFlow 1.3增加了针对数据流的计量表,因此计数器相应 增加了针对各个数据流计量表的统计。

  • 行动改为指令,不断丰富,增加如下:

版本 指令类型 指令名称 说明
v1.1 可选指令 Apply-Actions 立即进行指定行动,而不改变行动集。经常在修改数据包,以及在两 个表之间执行同类型的多个行动时使用
可选指令 Clear-Actions 清除行动集中所有的行动
可选指令 metadata/mask 在元数据区域记录元数据(由掩码指定修改哪一位元数据值)
必备指令 Write-Actions 将指定的多个行动合并到当前的行动集中,行动集中已存在同一类型 时将其覆盖,不存在同一类型时进行添加
必备指令 Goto-Table next-table-id 指示在流水线中的下级流表,参数table-id必须大于当前流表的table-id 而流水线最后的流表不能包含这个指令
v1.3 可选指令 Meter meter id 将数据包指向指定的计量表,通过计量表处理的数据大多都是被丢弃(实际处理结果根据计量表的配置和状态)

在OpenFlow 1.3版本中定义了7种行动类型:

类型 指令名称 说明
必备 OutPut 输入动作,将数据包从指定的OpenFlow端口转发,OpenFlow交换机必须支持转发到物理端口、交换机定义的逻辑端口和必须支持的保留端口
可选 Set-Queue 为数据包设置队列ID,已完成QoS功能在OpenFlow 1.0中被称作 Enqueue,OpenFlow 1.1将其更名
必备 DROP 用于丢弃数据包
必备 Group 用指定组处理数据包,而具体的操作要根据组类型决定。OpenFlow 1.1中增加
可选 Push-Tag/Pop-Tag 用于VLAN,MPLS、Tag的入栈和出栈,在OpenFlow 1.1中增加
可选 Set-Field 用于设置数据包头的类型和修改数据包头的值,该动作在OpenFlow 1.0中被称作Modify-field,OpenFlow 1.1及后续版本将其更名为Set-Field
可选 Change-TTL 用于修改TTL值,在OpenFlow 1.2中增加

优先级:

优先顺序 行动 说明
1 copy TTL inwards 将TTL复制到内侧
2 pop 应用所有的标签pop
3 push 应用所有的标签push
4 copy TTL outwards 将TTL复制到外侧
5 decrement TTL 将TTL减去1
6 Set 将set-Field行动运用到数据包中
7 qos 将queue中设置的所有QoS行动应用到数据包中
8 group Group行动已指定时,应用相应列表中指定的适当的组行动
9 output Group行动未指定时,将数据包转发至通过output行动指定的端口中

处理过程:

  • 端口变化,分类:

    OpenFlow 1.2及后续版本提出OpenFlow端口的概念,它是OpenFlow进程和网络 之间传递数据包的网络接口,OpenFlow交换机之间通过OpenFlow端口在逻辑上相互连接

    OpenFlow标准端口:包括物理端口,逻辑端口,LOCAL 保留端口(假如支持):

    ​ 标准端口可以作为入端口匹配和出端口动作端口

    ​ 标准端口可以在group组中使用

    ​ 标准端口关联有计数器信息

    OpenFlow物理端口:一般和物理硬件端口一一对应,交换机硬件接口对应的虚拟切片

    OpenFlow逻辑端口:交换机定义的接口,不与硬件接口直接对应。譬如聚合端口,隧道,环回端口 等

    ​ 尽管逻辑端口可能和实际的物理端口有各种映射,但是对于OpenFlow协议层面来说它和 物理端口一样,区别在于逻辑端口数据包拥有元数据Tunnel-ID

    OpenFlow保留端口:ALL、CONTROLLER、LOCAL、TABLE、NORMAL、IN_PORT、FLOOD等 端口,其在OpenFlow 1.0中成为“虚拟端口”

    OpenFlow 1.3 定义了8种端口:

    名称 说明
    ALL 表示所有端口均可用于转发指定数据包。当其被用作输出端口时,数据包被复制后发送到所有 的标准端口, 但不包括数据包的入端口及被配置为OFPPC_NO_FWD的端口
    CONTROLLER 表示到OpenFlow控制器的控制通道,它可以用作一个入端口或作为一个出端口。当用作一个出端口时,封 装数据包中为数据包消息,并使用OpenFlow协议发送。当用作一个入端口时,确认来自控制器的数据包
    TABLE 表示OpenFlow流水线的开始。这个端口仅在输出行为的时候有效,此时OpenFlow交换机提交报文给第一流 表使数据包可以通过OpenFlow流水线处理(转发给某一个流表)
    IN PORT 代表数据包进入端口。只有一种情况用于输出端口,即从入端口发送数据包
    ANY 某些OpenFlow命令中的特定值,用在没有指定端口的(端口通配符)情形,不能用于入端口和出端口
    LOCAL(可选) 表示交换机的本地网络堆栈和管理堆栈。可以用作一个入端口或者一个出端口。该端口使得远程实体可以与 交换机通过OpenFlow网络交互,而不再需要单独的控制网络。通过配置一组合适的默认流表项,该端口可用 于实现一个带内控制器的连接
    NORMAL(可选) 代表传统的非OpenFlow流水线处理。仅可用作普通流水线的输出端口。如果交换机不能从OpenFlow流水线 转发数据包到普通流水线,它必须表明它不支持这一动作
    FLOOD(可选) 表示使用普通流水线处理洪泛过程。可用于作为一个输出端口,除入端口或OFPPS_BLOCKED状态的端口 外,可以将数据包发往其他所有标准端口。交换机也可以通过数据包的VLAN ID选择哪些端口洪泛

OpenFlow 1.3

指令:

组表结构:

1
2
3
4
5
6
7
> ovs-ofctl add-group s2 group_id=1,type=all,bucket=output:2,bucket=output:3 -O OpenFlow13
> ovs-ofctl dump-groups s2 -O OpenFlow13
OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):
group_id=1,type=all,bucket=actions=output:2,bucket=a ctions=output:3
OVS-OFCTL ADD-FLOW BR-SW
IN_PORT=2,ACTIONS=group:s2,outpu:3

组表的作用:

Meter表的结构:

流限速:

1
2
3
4
> ovs-ofctl add-meter br0 meter=2,kbps,band=type=drop,rate=30000  
> ovs-ofctl add-flow br0 in_port=1,actions=meter:2,output:2
> ovs-ofctl add-meter br0 meter=3,kbps,band=type=dscp_remark,rate=30000,prec_level=14
> ovs-ofctl add-flow br0 in_port=2,actions=meter:3,output:1