1 2 3 4

实验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主要消息类型对应的数据结构定义。控制器与交换机连接建立完成后,控制器下发转发信息,交换机上传网络资源信息,最终实现全网主机的互通。

posted @ 2022-10-02 17:31  garty  阅读(132)  评论(0)    收藏  举报