OpenFlow协议思想是,网络设备维护一个FlowTable,并且只通过FlowTable对报文进行处理,FlowTable本身的生成、维护和下发完全由外置的控制器Controller来实现。
此外,OpenFlow交换机把传统网络中,完全由交换机/路由器控制的报文处理转变为由交换机和控制器来共同完成数据的转发操作,从而实现数据的转发与路由控制的分离。控制器则通过事先规定好的接口操作OpenFlow交换机中的流表,从而达到数据转发的目的。
目前OpenFlow协议主要支持三种消息类型,分别是:
Controller-to-switch消息:由控制器发起,用来管理或获取switch状态
asynchronous消息:由switch发起,用来将网络事件或交换机状态变化更新到控制器。
symmetic消息:可由交换机或控制器发起。
Hello、Feature、Echo消息分别包含REQUEST与REPLY消息,每一个消息REQUEST与REPLY的TransactionID相同,交换机通过ID进行识别对应事件端口。
OpenFlow协议基本报文格式如下:
通过构建OpenDaylight控制器与Mininet模拟器相结合的测试环境,来研究OpenFlow协议。Mininet中构建1个交换机和2个主机,这2个主机属于同网段。
1、启动OpenDaylight:
root@ubuntu:/home/rain/opendaylight/karaf-0.7.2/bin#./karaf
通过浏览器访问http://localhost:8181/index.html)页面。用户名和密码都是admin。
2、抓包验证
在ODL虚拟机上执行以下命令开始抓包
tcpdump-i any port 6633 -s0 -w openflow.pcap
3、登录Mininet虚拟机,执行以下命令启动Mininet,生成测试拓扑结构:
mn--controller=remote,ip=192.168.28.131,port=6633
4、分析抓的OpenFlow数据包
参考:OpenFlow协议抓包实验https://www.jianshu.com/p/e660508f1c5d
OpenDaylight二层转发机制实验https://www.sdnlab.com/15126.html
OpenFlow协议wireshark抓包分析https://www.cnblogs.com/cing/p/7709544.html
打开抓取的openflow.pcap文件,找到OFPT_HELLO报文,追踪TCP流。
可以看出先是进行了三次TCP握手,建立TCP连接。因而,OpenFlow协议的数据包封装在TCP报文中。
控制器与交换机通信过程详解:
1、hello消息
当交换机连接到控制器时,交换机与控制器会相互发送hello包,而hello消息中只包含ofHeader,没有主体部分。而of头部结果如下:
/*Header on all OpenFlow packets. */
structofp_header {
uint8_t version; /* OFP_VERSION. */
uint8_t type; /* One of the OFPT_ constants. */
uint16_t length; /* Length including this ofp_header. */
uint32_t xid; /* Transaction id associated with thispacket.
Replies use the same id as was in the request tofacilitate pairing. */
};
ofHeader中的version字段为发送方支持的最高版本的of协议版本。如果两者协议版本兼容,则建立of连接,否则发送error消息,断开连接。交换机向控制器发送的Hello消息如下所示:
2、feature消息
可以看到该报文里面包含了发送给交换机的OFPT_HELLO报文,但是TransactionID:21和交换机发给控制器的不一样。
交换机响应控制器发送的OFPT_FEATURES_REQUEST报文,向控制器发送OFPT_FEATURES_REPLY
连接建立后,控制器向交换机发送一个featuresRequest消息查询交换机的特性,features request消息也只包含ofHeader,交换机接受到该消息之后会返回一个features reply消息,这个消息就包含Header和Message。request和reply两个消息的TransactionID是一样的。
reply消息分析:
[0:8]为header(version、type、length、xid)
[8:32]长度24byte为sw的features,包含如下:
datapath_id:交换机的标识符,低48位是一个MAC地址,高16位是自定义的。
n_buffers:一次最多缓存的数据包数量。
n_tables:表示交换机支持的流表数量。每个流表可以设置不同的通配符和不同数量的流表项。控制器和交换机第一次通信的时候,控制器会从feature_reply消息中找出交换机支持多少流表,如果控制器还想了解大小、类型和流表查询的顺序,就发送一个ofpst_tablestats请求,交换机必须按照数据包遍历流表的顺序把这些流表回复给控制器,并且精确匹配流表排在通配流表前。
auxiliary_id:标识辅助连接。
capabilities:所支持的功能。交换机的一些详细信息的bitmap。
reserved:保留字段。
ofpt_feature_reply消息结构如下:
structofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for
aMAC address, while the upper 16-bits are implementer-defined. */
uint32_t n_buffers; /* Max packets buffered at once. */
uint8_t n_tables; /* Number of tables supported bydatapath. */
uint8_t pad[3]; /* Align to 64-bits. */
/* Features. */
uint32_t capabilities; /* Bitmap of support "ofp_capabilities".*/
uint32_t actions; /* Bitmap of supported"ofp_action_type"s. */
/* Port info.*/
struct ofp_phy_port ports[0]; /* Port definitions. The number of ports is inferred from thelength field in the header. */
};
3、barrier消息
控制器通过Barrier请求及相应报文,确认相关消息已经被满足或收到完成操作的通知。
Barrier消息:当控制器需要确认消息依存关系是否满足,或者希望接收到操作完成的通告时,就发送barrier消息,这个消息就是OFPT_BARRIER_REQUEST,它没有主体部分。OpenFlow交换机收到这个消息后,必须结束对所有之前收到的消息的处理,才能执行任何barrier请求之后接收的消息。当前处理完成后,交换机必须发送应答消息OFPT_BARRIER_REPLY,并在消息中携带原始请求交易的ID(xid)。
4.flow_mod消息
Flow-Mod消息用于添加、删除、修改openflow交换机的消息;Flow-Mod消息共有5种类型:
ADD类型消息用来添加一条新的流表项(flowentry)
DELETE类型消息用来删除所有符合一定条件的流表项
DELETE‐STRICT类型消息用来删除某一条指定的流表项
MODIFY类型消息用来修改所有符合一定条件的流表项
MODIFY‐STRICT类型息用来修改某一条指定的流表项
Flow-Mod消息对应修改的是流表中的流表项(flow entry)而不是整个流表(flowtable)。
控制器向交换机下发OFPT_FLOW_MOD消息:
消息解释:
cookies为控制器定义流表项标识符
Command:flow-mod的类型
Ldle_timeout是流表项的空闲超时时间;
Hard_timeout是流表项的最大生存时间;
Priority为流表项的优先级,交换优先匹配高优先级的流表项;
Buffer_id为交换机中的缓冲区ID,flow-mod消息可以指定一个缓冲区的ID,该缓冲区的数据包会按照此flow-mod消息的action列处理。如果是手动下发的流,buffer_id应填-1,即0xffff,告诉交换机这个数据包并没有缓存在队列中。
Out_port为删除流表的flow_mod消息提供的额外的匹配参数。
Flags为flow-mod命令的一些标志位,可以用来指示流表删除后是否发送flow-removed消息,添加流表时是否检查流表重复项,添加的流表项是否为应急流表项。
当OFPFF_SEND_FLOW_REM被设置的时候,表项超时删除会触发一条表项删除的信息。
当OFPFF_CHECK_OVERLAP被设置的时候,交换机必须检查同优先级的表项之间是否有匹配范围的冲突。
当OFPFF_EMERG被设置的时候,交换机将表项当作紧急表项,只有当与控制器连接断的时候才启用。
5、PACKET_IN消息
Packet-in事件在以下两种情况下会被触发:
1)当交换机收到一个数据包后,并未与流表中匹配成功,那么交换机就会将数据封装在Packer-in消息中,发送给控制器处理。此时数据包会被缓存在交换机中等待处理。
2.交换机流表所指示的action列表中包含转发给控制器的动作(Output=Controller),此时数据不会被缓存在控制器中。
一般将数据包缓存在交换机中,将有效的数据包信息(默认的128字节,如果原因是“sendto controller”action,那么长度由action_out的max_len决定;如果是原因tablemiss,那么长度由set_config消息中的miss_send_len决定。)和缓存id发送给控制器,不过,如果交换机不支持缓存或者内存用光了,那么就把整个数据包放在数据部分发给控制器,并且缓存id为-1。
交换机向控制器递交OFPT_PACKET_IN消息:
Packet_in消息结构如下:
/*Packet received on port (datapath -> controller). */
structofp_packet_in {
struct ofp_header header;
uint32_t buffer_id; /* ID assigned by datapath. */
uint16_t total_len; /* Full length of frame. */
uint16_t in_port; /* Port on which frame was received. */
uint8_t reason; /* Reason packet is being sent (one ofOFPR_*) */
uint8_t pad;
uint8_t data[0]; /* Ethernet frame, halfway through32-bit word,
so the IP headeris 32-bit aligned. The
amount of datais inferred from the length
field in theheader. Because of padding,
offsetof(structofp_packet_in, data) ==
sizeof(structofp_packet_in) - 2. */
};
协议解释:
buffer_id是packet-in消息所携带的数据包在交换机中的缓存ID
Total_len为data段的长度
Reason为packet-in事件的产生原因
8、PACKET_OUT消息
Packet-out消息的应用场景:
指定某一个数据包的处理方法
让交换机产生一个数据包并按照action流表处理。
典型应用:链路发现
控制器向一个交换机发送packet-out消息,buffer_id=-1,data段为某种特殊数据包,actions为从交换机的某个端口进行转发,如果发出这个数据包的端口另一端也连接一个openflow交换机,对端的交换机会产生一个packet-in消息将这个特殊的数据包转发给控制器,从而控制器他侧到一条链路的存在(控制器实现链路发现,就是依靠packet-out消息)。
当控制器断电或者交换机与控制器之间的连接断开,则交换机会寻找备用控制器,当无法找到备用控制器时便会进入紧急模式(交换机初始化时也是在这个模式下),在紧急模式下,交换机默认将所有接受到的数据包丢弃。
Packet_out消息结构:
structofp_packet_out {
struct ofp_header header;
uint32_t buffer_id; /* ID assigned by datapath (-1 ifnone). */
uint16_t in_port; /* Packet's input port (OFPP_NONEif 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 theheader.
(Onlymeaningful if buffer_id == -1.) */
};
协议解释:
buffer_id为交换机中缓存的buffer_id(同flow-mod);特别注意的是当buffer_id为“-1”时,指定的缓冲区为packet-out消息的data字段。
In_port为packet-out消息提供额外的匹配信息,当packet-out的buffer_id=-1,并且action流表中指定了output=TABLE的动作,in_port将作为data段数据包的额外匹配信息进行流表查询。
action_len指定了action列表的长度,用来区分actions和data段Data为一个缓冲区,可以存储一个以太网帧。
领取专属 10元无门槛券
私享最新 技术干货