实验3:OpenFlow协议分析实践
一、搭建下图所示拓扑,完成相关 IP 配置,并实现主机与主机之间的 IP 通信。用抓包软件获取控制器与交换机之间的通信数据。
(1)拓扑


(2)主机互ping

(3)抓包结果


(4)建立连接的交互图与文字说明

当双方hello报文中openflow版本可以互相兼容,则会按照上图所示的流程继续建立连接;若版本不兼容,则发送error消息后断开链接
packet_in发送原因:交换机查找流表,发现没有匹配条目时
有匹配条目但是对应的action是OUTPUT=CONTROLLER时
packet_out:直接告诉交换机端口如何处理数据包(按照控制器给的action进行处理)
flow_mod:下发流表项(源,目的ip地址),指导数据的转发处理
(5)交换机与控制器建立通信时是使用TCP协议还是UDP协议?
TCP协议
二、进阶实验
(1)header(所有的openflow消息必有的部分)
struct ofp_header {
uint8_t version; /* openflow协议版本 */
uint8_t type; /*openflow消息类型 */
uint16_t length; /* 包括头部的openflow报文长度*/
uint32_t xid; /* 与此数据包关联的事务id(答复时使用与请求时相同的id)*/
};
(2)hello

struct ofp_hello {
struct ofp_header header;
};
(3)port_status

struct ofp_port_status {
struct ofp_header header;
uint8_t reason; /* One of OFPPR_*. */
uint8_t pad[7]; /* Align to 64-bits. */
struct ofp_phy_port desc;
};
OFP_ASSERT(sizeof(struct ofp_port_status) == 64);
(4)features_request

struct ofp_features_request{
struct ofp_header header;
};
(5)set config

struct ofp_switch_config {
struct ofp_header header;
uint16_t flags; /* OFPC_* flags. */
uint16_t miss_send_len; /* Max bytes of new flow that datapath should
send to the controller. */
};
OFP_ASSERT(sizeof(struct ofp_switch_config) == 12);
enum ofp_config_flags {
/* Handling of IP fragments. */
OFPC_FRAG_NORMAL = 0, /* No special handling for fragments. */
OFPC_FRAG_DROP = 1, /* Drop fragments. */
OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */
OFPC_FRAG_MASK = 3
};
(6)features_reply

struct ofp_queue_get_config_reply {
struct ofp_header header;
uint16_t port;
uint8_t pad[6];
struct ofp_packet_queue queues[0]; /* List of configured queues. */
};
OFP_ASSERT(sizeof(struct ofp_queue_get_config_reply) == 16);
struct ofp_aggregate_stats_reply {
uint64_t packet_count; /* Number of packets in flows. */
uint64_t byte_count; /* Number of bytes in flows. */
uint32_t flow_count; /* Number of flows. */
uint8_t pad[4]; /* Align to 64 bits. */
};
OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24);
struct ofp_stats_reply {
struct ofp_header header;
uint16_t type; /* One of the OFPST_* constants. */
uint16_t flags; /* OFPSF_REPLY_* flags. */
uint8_t body[0]; /* Body of the reply. */
};
OFP_ASSERT(sizeof(struct ofp_stats_reply) == 12);
(7)packet_in

struct ofp_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 of OFPR_*) */
uint8_t pad;
uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word,
so the IP header is 32-bit aligned. The
amount of data is inferred from the length
field in the header. Because of padding,
offsetof(struct ofp_packet_in, data) ==
sizeof(struct ofp_packet_in) - 2. */
};
OFP_ASSERT(sizeof(struct ofp_packet_in) == 20);
(8)packet_out

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.) */
};
OFP_ASSERT(sizeof(struct ofp_packet_out) == 16);
(9)flow_mod
struct ofp_flow_mod {
struct ofp_header header;
struct ofp_match match; /* Fields to match */
uint64_t cookie; /* Opaque controller-issued identifier. */
/* Flow actions. */
uint16_t command; /* One of OFPFC_*. */
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Max time before discarding (seconds). */
uint16_t priority; /* Priority level of flow entry. */
uint32_t buffer_id; /* Buffered packet to apply to (or -1).
Not meaningful for OFPFC_DELETE*. */
uint16_t out_port; /* For OFPFC_DELETE* commands, require
matching entries to include this as an
output port. A value of OFPP_NONE
indicates no restriction. */
uint16_t flags; /* One of OFPFF_*. */
struct ofp_action_header actions[0]; /* The action length is inferred
from the length field in the
header. */
};
OFP_ASSERT(sizeof(struct ofp_flow_mod) == 72);
三、实验总结
本次实验难度适中,用wireshark抓包时选择“any”,在过滤中写入openflow_v1来筛出所有openflow包。要在拓扑建立前抓包。通过观察openflow包,总结出交换机与控制器建立连接的步骤,以及通过观察源端口号和目的端口号,总结出报文的具体发送过程。而在拓展实验中,经查阅资料,发现openflow源码存放在openflow/include/openflow/openflow.h处,通过gedit命令查看后,与openflow包的信息进行比对,最终了解了OpenFlow主要消息类型对应的数据结构定义。控制器与交换机连接建立完成后,控制器下发转发信息,交换机上传网络资源信息,最终实现全网主机的互通。

浙公网安备 33010602011771号