1. Hello
控制器与交互及互相发送 Hello 消息。Hello消息中只包含有OpenFlow Header,其中的 type 字段为 OFPT_HELLO,version 字段为发送方所支持的最高版本 OpenFlow 。这时候会出现两种状况:缓存
若是双方 OpenFlow 版本能够兼容,则 OpenFlow 链接创建成功。
Q1:Hello 消息是使用什么协议传输?TCP?UDP?
Q2:全部的网络协议在升级的时候都必须向前兼容更低版本的协议?cookie
2. Features Request
OpenFlow 链接创建以后,就像你刚到手一部新手机,你最想知道的就是手机的配置如何同样,控制器最须要得到交换机的特性信息,交换机的特性信息包括交换机的 ID(DPID),交换机缓冲区数量,交换机端口及端口属性等等。
控制器向交换机发送 Features Request 消息查询交换机特性,Features Request 消息只包含 OpenFlow Header,其中 type 字段为 OFPT_FEATURES_REQUEST。网络
3. Features Reply
交换机在收到控制器发出的 Features Request 消息后返回 Features Request 消息,Features 消息包括 OpenFlow Header 和 Features Reply Message。后者结构以下:大数据
struct ofp_switch_features{ struct ofp_header header; uint64_t datapath_id; /*惟一标识 id 号*/ uint32_t n_buffers; /*交缓冲区能够缓存的最大数据包个数*/ uint8_t n_tables; /*流表数量*/ uint8_t pad[3]; /*align to 64 bits*/ uint32_t capabilities; /*支持的特殊功能,具体见 ofp_capabilities*/ uint32_t actions; /*支持的动做,具体见 ofp_actions_type*/ struct ofp_phy_port ports[0]; /*物理端口描述列表,具体见 ofp_phy_port*/ };
Q3:uint8_t pad[3] 这一字段的做用是什么?为了保证整个结构体长度是 64bits 的整数倍?ui
ofp_capabilities 结构以下:
ofp_actions_type 结构以下:
ofp_phy_port 结构以下:code
struct ofp_phy_port{ uint16_t port_no; /*物理端口的编号*/ uint8_t hw_addr[OFP_EHT_ALEN]; /*MAC地址*/ char name[OFP_MAX_PORT_NAME_LEN]; /*端口的名称*/ uint32_t config; /*端口配置,见 ofp_port_config*/ uint32_t state; /*端口状态,见ofp_port_state*/ uint32_t curr; /*物理属性*/ uint32_t advertised; /*物理属性*/ uint32_t supported; /*物理属性*/ uint32_t peer; /*物理属性*/ };
ofp_port_config 和 ofp_port_state 结构以下:
4. Set config
知道了交换机的特性以后就要配置交换机了。OpenFlow 交换机只有两个属性须要控制器配置:blog
5. Packet-in
有两种状况会触发交换机向控制器发送 Packet-in 消息:rem
struct ofp_packet_in { struct ofp_header header; uint32_t buffer_id; /*Packet-in消息所携带的数据包在交换机缓存区中的ID*/ uint16_t total_len; /*data字段的长度*/ uint16_t in_port; /*数据包进入交换机时的端口号*/ uint8_t reason; /*发送Packet-in消息的缘由,具体见 ofp_packet_in_reason*/ uint8_t pad; uint8_t data[0]; /*携带的数据包*/ };
ofp_packet_in_reason 结构以下:工作流
enum ofp_packet_in_reason { OFPR_NO_MACTH /*没有匹配的条目*/ OFPR_ACTION /*action列表中包含转发给控制器的动做*/ };
6. Flow-Mod / Packet-out
当控制器收到 Packet-in 消息时有两种响应的方式:
Flow-Mod
控制器收到 Packet‐in 消息后,能够发送 Flow‐Mod 消息向交换机写一个流表项。并
且将 Flow‐Mod 消息中的 buffer_id 字段设置为 Packet‐in 消息中的 buffer_id 值。从而
控制器向交换机写入了一条与数据包相关的流表项,而且指定该数据包按照此流表项的 action 列表处理。
Flow-Model 消息共有五种类型:it
struct ofp_flow_mod { struct ofp_header header; struct ofp_match match; /*流表的匹配域*/ uint64_t cookie; /*流表项标识符*/ uint16_t command; /*能够是ADD,DELETE,DELETE-STRICT,MODIFY,MODIFY-STRICT*/ uint16_t idle_timeout; /*空闲超时时间*/ uint16_t hard_timeout; /*最大生存时间*/ uint16_t priority; /*优先级,优先级高的流表项优先匹配*/ uint32_t buffer_id; /*缓存区ID ,用于指定缓存区中的一个数据包按这个消息的action列表处理*/ uint16_t out_port; /*若是这条消息是用于删除流表则须要提供额外的匹配参数*/ uint16_t flags; /*标志位,能够用来指示流表删除后是否发送flow‐removed消息,添加流表时是否检查流表重复项,添加的流表项是否为应急流表项。*/ struct ofp_action_header actions[0]; /*action列表*/ };
Packet-Out
并非全部的数据包都须要 向交换机中添加一条流表项来匹配处理,网络中有些数据包出现的数量不多(如ARP、 IGMP等),不必经过流表项来指定这一类数据包的处理方法。此时可使用 Packet-Out 消息,高速交换机某一个数据包如何处理。
struct ofp_packet_out { struct ofp_header header; uint32_t buffer_id; /*交换机缓存区id,若是为-1则指定的为packet-out消息携带的data字段*/ uint16_t in_port; /*若是buffer_id为‐1,而且action列表中指定了Output=TABLE的动做,in_port将做为data段 数据包的额外匹配信息进行流表查询*/ uint16_t actions_len; /*action列表的长度,能够用来区分actions和data段*/ struct ofp_action_header actions[0]; /*动做列表*/ uint8_t data[0]; /*数据缓存区,能够存储一个以太网帧,可选*/ }
Flow-Mod 是指定一类数据包的处理方法,而 Packet-Out 则是指定某一个数据包的处理方法。不只如此,Packet-Out 消息还可让交换机产生一个数据包并按照 action 列表处理。
基于 OpenFlow 的 SDN 工做流程,以下图: