目录
OpenFlow1.0代码
文中所有数据结构请查看openflow1.0源代码
提取码:g3nq
在include->openflow->openflow.h中
白皮书openflow-spec-v1.0.0.pdf也在里面
OpenFlow交换机流表OpenFlow交换机中的转发表称为流表(Flow Table),列表中的每个条目称为表项,每个表项包括三个域,包头域(header field),计数器(counters),行动(actions)。
包头域
数据包匹配特征:
- 一层:交换机入端口(Ingress Port)
- 二层:源MAC地址(Ether source)、目的MAC地址(Ether dst)、以太网类型(Ether Type)、VLAN标签(VLAN id)、VLAN优先级(VLAN priority)
- 三层:源IP(IP src)、目的IP(IP dst)、IP协议字段(IP proto)、IP服务类型(IPToS bits)
- 四层:TCP/UDP源端口号(TCP/UDP src port)、TCP/UDP目的端口号(TCP/UDP dst port)
Ingress Port | Ether Source | Ether st | Ether type | VLAN id | VLAN priority | IP src | IP dst | IP proto | IP ToS bits | TCP/UDP src port | TCP/UDP dst port |
对数据包匹配特征的描述
/ *与流量匹配的字段* /
struct ofp_match {
uint32_t wildcards; / *通配符字段。 * /
uint16_t in_port; / *输入开关端口。 * /
uint8_t dl_src [OFP_ETH_ALEN]; / *以太网源地址。 * /
uint8_t dl_dst [OFP_ETH_ALEN]; / *以太网目标地址。 * /
uint16_t dl_vlan; / *输入VLAN ID。 * /
uint8_t dl_vlan_pcp; / *输入VLAN优先级。 * /
uint8_t pad1 [1]; / *对齐64位* /
uint16_t dl_type; / *以太网帧类型。 * /
uint8_t nw_tos; / * IP ToS(实际上是DSCP字段,6位)。 * /
uint8_t nw_proto; / * IP协议或以下的低8位
* ARP操作码。 * /
uint8_t pad2 [2]; / *对齐64位* /
uint32_t nw_src; / * IP源地址。 * /
uint32_t nw_dst; / * IP目标地址。 * /
uint16_t tp_src; / * TCP / UDP源端口。 * /
uint16_t tp_dst; / * TCP / UDP目标端口。 * /
};
相对于前面所说,多了三个字段,分别是wildcards、pad1[1]、pad2[2],作用如翻译所写。
wildcards字段
/ *流通配符。 * /
enum of_p_flow_wildcards{
OFPFW_IN_PORT = 1 << 0,/ *开关输入端口。 * /
OFPFW_DL_VLAN = 1 << 1,/ * VLAN ID。 * /
OFPFW_DL_SRC = 1 << 2,/ *以太网源地址。 * /
OFPFW_DL_DST = 1 << 3,/ *以太网目标地址。 * /
OFPFW_DL_TYPE = 1 << 4,/ *以太网帧类型。 * /
OFPFW_NW_PROTO = 1 << 5,/ * IP协议。 * /
OFPFW_TP_SRC = 1 << 6,/ * TCP / UDP源端口。 * /
OFPFW_TP_DST = 1 << 7,/ * TCP / UDP目标端口。 * /
/ * IP源地址通配符位数。 0是完全匹配,1则忽略
* LSB,2忽略2个最低有效位,...,32和更高的通配符
*整个领域。这与通常的约定相反
*例如/ 24表示通配符为8位(不是24位)。 * /
OFPFW_NW_SRC_SHIFT = 8
OFPFW_NW_SRC_BITS = 6
OFPFW_NW_SRC_MASK =(((1 << OFPFW_NW_SRC_BITS)-1)<< OFPFW_NW_SRC_SHIFT,
OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT,
/ * IP目标地址通配符位数。与源格式相同。 * /
OFPFW_NW_DST_SHIFT = 14
OFPFW_NW_DST_BITS = 6
OFPFW_NW_DST_MASK =(((1 << OFPFW_NW_DST_BITS)-1)<< OFPFW_NW_DST_SHIFT,
OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,
OFPFW_DL_VLAN_PCP = 1 << 20,/ * VLAN优先级。 * /
OFPFW_NW_TOS = 1 << 21,/ * IP ToS(DSCP字段,6位)。 * /
/ *通配所有字段。 * /
OFPFW_ALL =((1 << 22)-1)
};
22-31 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
保留 | IP服务类型 | VLAN优先级 | 目的IP | 源IP | 目的端口 | 源端口 | IP协议字段 | 以太网类型 | 目的MAC | 源MAC | VLAN标签 | 入端口 |
除源IP和目的IP以外,掩码位为0表示对应匹配项需要精确匹配,掩码为为1表示忽略匹配项。
源IP和目的IP字段的掩码表示32bit lP地址可以忽略匹配的长度。
如果源IP的掩码为8(wildcard的8-13bit为001000),表示源IP字段的高24bit需要精确匹配,源IP字段的低8bit可以忽略。
计数器
计数器可以针对每张表、每个流、每个端口、每个队列来维护。用来统计流量的一些信息,例如活动表项、查找次数、发送包数等。
行动
OpenFlow1.0.0提供多种行动,前两个必备:
丢弃(Drop)
没有明确指明处理行动的表项,所匹配的所有网包默认丢弃。
转发(Forward)
- ALL转发到所有出口(不包括入口)
- CONTROLLER封装并转发给控制器
- LOCAL转发给本地网络栈
- TABLE对要发出的包执行流表中的行动
- IN PORT从入口发出
修改包头(Modify field)
- SET_VLAN_VID 修改VLAN标签
- SET_VLAN_PCP 修改VLAN优先级
- STRIP_VLAN 弹出VLAN标签
- SET_DL_SRC 修改源MAC地址
- SET_DL_DST 修改目的MAC地址
- SET_NW_SRC 修改源IP地址
- SET_NW_DST 修改目的IP地址
- SET_NW_TOS 修改IP服务类型字段
- SET_TP_SRC 修改源端口号
- SET_TP_DST 修改目的端口号
以上每一种操作称为一个动作(Action),流表中的数据包处理方法是一个动作列表(Action List),动作列表由以上各种动作组合合成。
Action的头
/ *所有动作共有的头。 长度包括
*头和用于使操作64位对齐的任何填充。
*注意:动作的长度*必须*始终是8的倍数。 * /
struct ofp_action_header {
uint16_t type; / * OFPAT_ *之一。 * /
uint16_t len; / *动作时长,包括此
头。 这是行动的时长,
包括任何填充物
64位对齐。 * /
uint8_t pad [4];
};
其中,type字段为以下之一
enum of_p_action_type{
OFPAT_OUTPUT, / *输出到交换机端口。 * /
OFPAT_SET_VLAN_VID,/ *设置802.1q VLAN ID。 * /
OFPAT_SET_VLAN_PCP,/ *设置802.1q优先级。 * /
OFPAT_STRIP_VLAN, / *剥离802.1q标头。 * /
OFPAT_SET_DL_SRC, / *以太网源地址。 * /
OFPAT_SET_DL_DST, / *以太网目标地址。 * /
OFPAT_SET_NW_SRC, / * IP源地址。 * /
OFPAT_SET_NW_DST, / * IP目标地址。 * /
OFPAT_SET_NW_TOS, / * IP ToS(DSCP字段,6位)。 * /
OFPAT_SET_TP_SRC, / * TCP / UDP源端口。 * /
OFPAT_SET_TP_DST, / * TCP / UDP目标端口。 * /
OFPAT_ENQUEUE, / *输出到队列。 * /
OFPAT_VENDOR = 0xffff
};
其中OFPAT_OUTPUT和OFPAT_ENQUEUE为转发操作,其他类型为修改包头操作
OUTPUT类型
/ * OFPAT_OUTPUT的操作结构,该结构将数据包从“端口”发送出去。
*当“端口”为OFPP_CONTROLLER时,“ max_len”表示最大
*要发送的字节数。 “ max_len”为零表示没有字节
*数据包应该发送。* /
struct ofp_action_output {
uint16_t type; / * OFPAT_OUTPUT。 * /
uint16_t len; / *长度为8。* /
uint16_t port; / *输出端口。 * /
uint16_t max_len; / *要发送到控制器的最大长度。 * /
};
output类型Action的结构包含一个port参数和一个max_len参数Port参数指定了数据包的输出端口,输出端口可以是交换机的一个实际物理端口,也可以是一下虚拟端口
- ALL:将数据包从除入端口以外其他所有端口发出
- CONTROLLER:将数据包发送给控制器
- LOCAL:将数据包发送给交换机本地端口>TABLE:将数据包按照流表匹配条目处理
- IN_PORT:将数据包从入端口发出
- NORMAL:按照普通二层交换机流程处理数据包
- FLOOD:将数据包从最小生成树使能端口转发(不包括入端口)当port为CONTROLLER时,max_len指定了发给CONTROLLER的数据包最大长度。当port为其他参数时,max_len无意义。
ENQUEUE类型
/ * OFPAT_ENQUEUE操作结构:将数据包发送到端口上的给定队列。 * /
struct ofp_action_enqueue {
uint16_t type; / * OFPAT_ENQUEUE。 * /
uint16_t len; / * Len是16。* /
uint16_t port; / *队列所属的端口。 应该
引用有效的物理端口
(即<OFPP_MAX)或OFPP_IN_PORT。 * /
uint8_t pad [6]; / * pad用于64位对齐。 * /
uint32_t queue_id; / *将数据包放入队列的位置。 * /
};
VLAN_VID类型——修改VLAN的ID
/ * OFPAT_SET_VLAN_VID的操作结构。 * /
struct ofp_action_vlan_vid {
uint16_t type; / * OFPAT_SET_VLAN_VID。 * /
uint16_t len; / *长度为8。* /
uint16_t vlan_vid; / * VLAN ID。 * /
uint8_t pad [2];
};
VLAN_PCP类型——修改VLAN优先级
/ * OFPAT_SET_VLAN_PCP的操作结构。 * /
struct ofp_action_vlan_pcp {
uint16_t类型; / * OFPAT_SET_VLAN_PCP。 * /
uint16_t len; / *长度为8。* /
uint8_t vlan_pcp; / * VLAN优先级。 * /
uint8_t pad [3];
};
DL_ADDR类型——修改MAC地址
/ * OFPAT_SET_DL_SRC / DST的操作结构。 * /
struct ofp_action_dl_addr {
uint16_t type; / * OFPAT_SET_DL_SRC / DST。 * /
uint16_t len; / *长度为16。* /
uint8_t dl_addr [OFP_ETH_ALEN]; / *以太网地址。 * /
uint8_t pad [6];
};
NW_ADDR类型——修改IP地址
/ * OFPAT_SET_NW_SRC / DST的操作结构。 * /
struct ofp_action_nw_addr {
uint16_t类型; / * OFPAT_SET_TW_SRC / DST。 * /
uint16_t len; / *长度为8。* /
uint32_t nw_addr; /* IP地址。 * /
};
NW_TOS类型——修改IP服务类型
/ * OFPAT_SET_NW_TOS的操作结构。 * /
struct ofp_action_nw_tos {
uint16_t类型; / * OFPAT_SET_TW_SRC / DST。 * /
uint16_t len; / *长度为8。* /
uint8_t nw_tos; / * IP ToS(DSCP字段,6位)。 * /
uint8_t pad [3];
};
TP_PORT类型——修改传输层端口号
/ * OFPAT_SET_TP_SRC / DST的操作结构。 * /
struct ofp_action_tp_port {
uint16_t类型; / * OFPAT_SET_TP_SRC / DST。 * /
uint16_t len; / *长度为8。* /
uint16_t tp_port; / * TCP / UDP端口。 * /
uint8_t pad [2];
};
流表匹配
Openflow消息总共分为三大类:
1、Controller-to-Switch(控制器至交换机消息),此类消息由控制器主动发出
- Features 在建立传输层安全会话的时候,控制器发送feature请求(OFPT_FEATURES_REQUEST)消息给交换机,交换机需要应答(OFPT_FEATURES_REPLY)自身支持的功能。
- Configuration 控制器设置或查询交换机上的配置信息。交换机仅需要应答查询消息。
- Modify-State 控制器管理交换机流表项和端口状态等。
- Read-State 用来读取交换机流表、端口状态
- Send-Packet 用来通过指定端口发送数据包
- Barrier 控制器确保消息依赖满足,或接收完成操作的通知(OFPT_BARRIER_REQUEST、OFPT_BARRIER_REPLY)
/ *交换机配置消息。 * /
OFPT_FEATURES_REQUEST,
OFPT_FEATURES_REPLY,
OFPT_GET_CONFIG_REQUEST,
OFPT_GET_CONFIG_REPLY,
OFPT_SET_CONFIG,
/ *控制器命令消息。 * /
OFPT_PACKET_OUT,
OFPT_FLOW_MOD,
OFPT_PORT_MOD,
/ *统计信息。 * /
OFPT_STATS_REQUEST,
OFPT_STATS_REPLY,
/ *障碍消息。 * /
OFPT_BARRIER_REQUEST,
OFPT_BARRIER_REPLY,
/ *队列配置消息。 * /
OFPT_QUEUE_GET_CONFIG_REQUEST,
OFPT_QUEUE_GET_CONFIG_REPLY
2、Asynchronous(异步消息),此类消息由交换机主动发出
- Packet-in 用来告知控制器交换机接收到数据包
- Flow-Removed用来告知控制器交换机流表被删除>Port-Status用来告知控制器交换机端口状态更新
- Error用来告知控制器交换机发生错误
OFPT_PACKET_IN,
OFPT_FLOW_REMOVED,
OFPT_PORT_STATUS,
OFPT_ERROR,
3、Symmetric(对称消息),此类消息可以由控制器或交换机主动发起
- Hello用来建立Openflow连接
- Echo用来确认交换机与控制器之间的连接状态
- Vendor厂商自定义消息
OFPT_HELLO,
OFPT_ECHO_REQUEST,
OFPT_ECHO_REPLY,
OFPT_VENDOR,
OpenFlow消息格式
OpenFlow协议数据包由OpenFlow Header和OpenFlow Message两部分组成
OpenFlow的头
/ *所有OpenFlow数据包的头。 * /
struct ofp_header {
uint8_t version; / * OFP_VERSION。 * /
uint8_t type; / * OFPT_常量之一。 * /
uint16_t length; / *长度,包括此ofp_header。 * /
uint32_t xid; / *与该数据包关联的交易ID。
回复使用与请求中相同的ID
方便配对。 * /
};
OpenFlow消息
enum ofp_type{
/ *不可变的消息。 * /
OFPT_HELLO, / *对称消息* /
OFPT_ERROR, / *对称消息* /
OFPT_ECHO_REQUEST,/ *对称消息* /
OFPT_ECHO_REPLY, / *对称消息* /
OFPT_VENDOR, / *对称消息* /
/ *交换机配置消息。 * /
OFPT_FEATURES_REQUEST, / *控制器/交换机消息* /
OFPT_FEATURES_REPLY, / *控制器/交换机消息* /
OFPT_GET_CONFIG_REQUEST,/ *控制器/交换机消息* /
OFPT_GET_CONFIG_REPLY, / *控制器/交换机消息* /
OFPT_SET_CONFIG, / *控制器/交换机消息* /
/ *异步消息。 * /
OFPT_PACKET_IN, / *异步消息* /
OFPT_FLOW_REMOVED,/ *异步消息* /
OFPT_PORT_STATUS, / *异步消息* /
/ *控制器命令消息。 * /
OFPT_PACKET_OUT,/ *控制器/交换机消息* /
OFPT_FLOW_MOD, / *控制器/交换机消息* /
OFPT_PORT_MOD, / *控制器/交换机消息* /
/ *统计消息。 * /
OFPT_STATS_REQUEST,/ *控制器/交换机消息* /
OFPT_STATS_REPLY, / *控制器/交换机消息* /
/ *障碍消息。 * /
OFPT_BARRIER_REQUEST,/ *控制器/交换机消息* /
OFPT_BARRIER_REPLY, / *控制器/交换机消息* /
/ *队列配置消息。 * /
OFPT_QUEUE_GET_CONFIG_REQUEST,/ *控制器/交换机消息* /
OFPT_QUEUE_GET_CONFIG_REPLY / *控制器/交换机消息* /
};
对称消息
建立OpenFlow连接(OFPT_HELLO消息)
控制器与交换机互相发送Hello消息,Hello消息中只包含Openflow Header,Openflow Header中的version字段为发送方所支持的最高版本Openflow协议
双方选取Hello消息中最低版本的协议作为通信协议如果有一方不支持Openflow协议版本,应发送Error消息后断开连接
如果双方Openflow版本可以兼容,则Openflow连接建立成功。
报告错误(OFPT_ERROR消息)
共64+16+16+8=104位,后面有一句OFP_ASSERT(sizeof(struct ofp_error_msg) == 12);12*8=96,也就是没有data的话是会报错的。
/ * OFPT_ERROR:错误消息(数据路径->控制器)。 * /
struct ofp_error_msg {
struct ofp_header header;
uint16_t type;
uint16_t code;
uint8_t data [0]; / *可变长度数据。 根据类型和代码进行编译。 * /
};
里面的code type也有很多的枚举类型,防止文章太长,读者看不进去,接下来只黏贴重要部分,想看代码的自行下载阅读,不到1000行,还可以。
获取交换机特性信息(Features消息)
Openflow连接建立后,控制器最需要获得交换机的特性信息,交换机的特性信息包括交
换机的ID(DPID),交换机缓冲区数量,交换机端口及端口属性等等。
控制器向交换机发送Features Request消息查询交换机特性,Features Request消息只包含Openflow Header。
交换机在收到Features Request消息后返回Features Reply消息,Features Reply消息包括Openflow Header 和Features Reply Message
Features Reply Message结构
/ *交换机功能 * /
struct ofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; / *数据路径唯一ID。 低48位用于
MAC地址,而高16位是
实施者定义的。 * /
uint32_t n_buffers; / *一次缓冲的最大数据包数。 * /
uint8_t n_tables; / *数据路径支持的表数。 * /
uint8_t pad[3]; / *对齐64位。 * /
/* 特征。 * /
uint32_t capabilities; / *支持“ ofp_capabilities”的位图。 * /
uint32_t actions; / *支持的“ ofp_action_type”的位图。 * /
/ *端口信息* /
struct ofp_phy_port ports[0]; / *端口定义。 端口数
从中的长度字段推断
标头。 * /
};
物理端口描述
/ *物理端口的说明* /
struct ofp_phy_port {
uint16_t port_no;
uint8_t hw_addr [OFP_ETH_ALEN];
char name[OFP_MAX_PORT_NAME_LEN]; / *空终止* /
uint32_t config; / * OFPPC_ *标志的位图。 * /
uint32_t state; / * OFPPS_ *标志的位图。 * /
/ * OFPPF_ *位图,用于描述功能。 如果所有位清零
*不支持或不可用。 * /
uint32_t curr; / *当前功能。 * /
uint32_t advertised; / *端口正在通告的功能。 * /
uint32_t supported; / *端口支持的功能。 * /
uint32_t peer; / *由对等方通告的功能。 * /
};
/ *指示物理端口行为的标志。 这些标志是
*在ofp_phy_port中用于描述当前配置。 他们是
*在ofp_port_mod消息中使用,用于配置端口的行为。
* /
enum of_p_port_config{
OFPPC_PORT_DOWN = 1 << 0, / *端口在管理上已关闭。 * /
OFPPC_NO_STP = 1 << 1, / *禁用端口上的802.1D生成树。 * /
OFPPC_NO_RECV = 1 << 2, / *丢弃除802.1D跨越之外的所有数据包
树包。 * /
OFPPC_NO_RECV_STP = 1 << 3,/ *丢弃收到的802.1D STP数据包。 * /
OFPPC_NO_FLOOD = 1 << 4, / *泛洪时不包括此端口。 * /
OFPPC_NO_FWD = 1 << 5, / *丢弃转发到端口的数据包。 * /
OFPPC_NO_PACKET_IN = 1 << 6 / *不要为端口发送入站消息。 * /
};
配置交换机Openflow属性
/ *交换机配置。 * /
struct ofp_switch_config {
struct ofp_header header;
uint16_t flags; / * OFPC_ *标志。 * /
uint16_t miss_send_len; / *数据路径应包含的新流的最大字节数
发送给控制器。 * /
};
Openflow交换机只有两个属性需要控制器配置第一个属性为flags,用来指示交换机如何处理IP分片数据包;第二个属性为miss _send_len,用来指示当一个交换机无法处理的数据包到达时,将数据包发给控制器的最大字节数。
enum of_p_config_flags{
/ *处理IP片段。 * /
OFPC_FRAG_NORMAL = 0,/ *对片段没有特殊处理。 * /
OFPC_FRAG_DROP = 1, / *丢弃片段。 * /
OFPC_FRAG_REASM = 2, / *重新组装(仅在设置了OFPC_IP_REASM的情况下)。 * /
OFPC_FRAG_MASK = 3
};
异步消息
交换机接收数据包(Packet-in消息)
Packet-in消息触发情况1:
当交换机收到一个数据包后,会查找流表,找出与数据包包头相匹配的条目。
如果流表中有匹配条目,则交换机按照流表所指示的action列表处理数据包。
如果流表中没有匹配条目,则交换机会将数据包封装在Packet-in消息中发送给控制器处理。此时数据包会被缓存在交换机中等待处理。
Packet-in消息触发情况2:
交换机流表所指示的action列表中包含转发给控制器的动作(Output=CONTROLLER)。
此时数据包不会被缓存在交换机中。
Packet-in消息格式
/ *在端口(数据路径->控制器)上接收到的数据包。 * /
struct ofp_packet_in {
struct ofp_header header;
uint32_t buffer_id; / *由数据路径分配的ID。 * /
uint16_t total_len; / *整个帧的长度。 * /
uint16_t in_port; / *接收帧的端口。 * /
uint8_t reason; / *原因包被发送(OFPR_ *之一)* /
uint8_t pad;
uint8_t data[0]; / *以太网帧,位于32位字的中间,
因此IP标头是32位对齐的 的
从长度推断数据量
标头中的字段。 由于填充,
offsetof(struct ofp_packet_in,data)==
sizeof(struct ofp_packet_in)-2. * /
};
64+32+16+16+8+8+8=152。我抓到过长度为86、90、108等长度的数据包。后面有一句OFP_ASSERT(sizeof(struct ofp_packet_in) == 20); 20*8=160,应该是不能超过160,就是不能多一个字节,少的还不清楚最少是多少,应该是和header一样,64位。
reason字段,由这个字段可以看出前面所写Packet_in事件触发的两种情况。
/ *为什么将此数据包发送到控制器? * /
enum of_p_packet_in_reason{
OFPR_NO_MATCH,/ *没有匹配的流程。 * /
OFPR_ACTION / *操作明确输出到控制器。 * /
};
控制器-交换机消息
控制器配置流表(Flow-Mod消息)
Flow-Mod消息用来添加、删除、修改Openflow交换机的流表信息
Flow-Mod消息共有五种类型:
- ADD 类型的flow-mod消息用来添加一条新的流表项
- DELETE 类型的flow-mod消息用来删除所有符合一定条件的流表项
- DELETE-STRICT 类型的flow-mod消息用来删除某一条指定的流表项
- MODIFY 类型的flow-mod消息用来修改所有符合一定条件的流表项
- MODIFY-STRICT 类型的flow-mod消息用来修改某一条指定的流表项
/ *流设置和拆除(控制器->数据路径)。 * /
struct ofp_flow_mod {
struct ofp_header header;
struct ofp_match match; / *要匹配的字段* /
uint64_t cookie; / *不透明的控制器发出的标识符。 * /
/ *流动作。 * /
uint16_t command; / * OFPFC_ *之一。 * /
uint16_t idle_timeout; / *丢弃前的空闲时间(秒)。 * /
uint16_t hard_timeout; / *丢弃前的最长时间(秒)。 * /
uint16_t priority; / *流条目的优先级。 * /
uint32_t buffer_id; / *要应用于的缓冲数据包(或-1)。
对于OFPFC_DELETE *没有意义。 * /
uint16_t out_port; / *对于OFPFC_DELETE *命令,要求
匹配条目以将此作为
输出端口。值为OFPP_NONE
表示没有限制。 * /
uint16_t flags; / * OFPFF_ *之一。 * /
struct ofp_action_header actions [0]; / *
从标头中的长度字段推断动作长度
* /
};
用Flow-Mod消息响应Packet-in消息
当交换机收到一个数据包并且交换机中没有与该数据包匹配的流表项时,交换机将此数据包封装到Packet-in消息中发送给控制器,并且交换机会将该数据包缓存。
控制器收到Packet-in消息后,可以发送Flow-Mod消息向交换机写一个流表项。并且将Flow-Mod消息中的buffer_id字段设置为Packet-in消息中的buffer_id值。从而控制器向交换机写入了一条与数据包相关的流表项,并且指定该数据包按照此流表项的aciton列表处理。
交换机转发数据包(Packet-Out消息)
并不是所有的数据包都需要向交换机中添加一条流表项来匹配处理,网络中还存在多种数据包,它出现的数量很少(如ARP、IGMP等),以至于没有必要通过流表项来指定这一类数据包的处理方法。
此时,控制器可以使用PacketOut消息,告诉交换机某一个数据包如何处理。
Packet-Out消息格式
/* Send packet (controller -> datapath). */
struct ofp_packet_out {
struct ofp_header header;
uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */
uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */
uint16_t actions_len; /* Size of action array in bytes. */
struct ofp_action_header actions[0]; /* Actions. */
/* uint8_t data[0]; */ /* Packet data. The length is inferred
from the length field in the header.
(Only meaningful if buffer_id == -1.) */
};
/ *发送数据包(控制器->数据路径)。 * /
struct ofp_packet_out {
struct ofp_header header;
uint32_t buffer_id; / *由数据路径分配的ID(如果没有则为-1)。 * /
uint16_t in_port; / *数据包的输入端口(如果没有,则为OFPP_NONE)。 * /
uint16_t actions_len; / *操作数组的大小,以字节为单位。 * /
struct ofp_action_header actions [0]; / *动作。 * /
/ * uint8_t数据[0]; * / / *数据包数据。 该长度是根据标题中的length字段推断出来的。
(仅在buffer_id == -1时有意义。)* /
};
Packet-Out消息的应用场景
1、指定某一个数据包的处理方法
2、让交换机产生一个数据包并按照action列表处理典型应用:链路发现
控制器向一个交换机发送Packet-Out消息,buffer_id=-1,data段为某种特殊数据包,actions为从交换机的某个端口转发
如果发出这个数据包的端口另一端也连接一个Openflow交换机,对端的交换机会产生一个Packet-ln消息将这个特殊的数据包上交给控制器,从而控制器探测到一条链路的存在
更多SDN相关内容,请查看:SDN-自学笔记
有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。