前言

在当今网络架构中,OpenFlow技术作为SDN(软件定义网络)的关键支持技术之一,为网络流量控制提供了更加灵活和智能的解决方案。Wireshark作为一个优秀的网络协议分析工具,可以帮助我们深入了解OpenFlow协议背后的数据交换过程。在本文中,我们将通过Wireshark工具来分析OpenFlow协议,探索其工作原理和数据交换过程。

1. OpenFlow简介

OpenFlow是一种通信协议,用于在网络设备之间进行通信,并 能够实现控制数据流的灵活性和集中管理。OpenFlow协议通过控制器来管理网络设备,并根据网络流量的需求对网络设备进行动态配置和管理。

2. Wireshark简介

Wireshark是一款开源的网络协议分析工具,可以帮助用户捕获和分析网络数据包。通过Wireshark工具,我们可以深入了解数据包的传输过程,进而解决网络问题和优化网络性能。

3.实验步骤

文献参考https://www.cnblogs.com/eleven955/p/15328388.html

3.1实验前置任务


1.首先在ubuntu系统中启动mininet可视化界面

mininet/examples/miniedit.py

然后按照下图所示,搭建拓扑图

2.点击左上角的Exit里的Preferences,并按照下图进行设置


3.将修改好的拓扑图保存为*.py的格式,如下图所示


使用vim打开文件,编辑每个终端的IP地址,当然,您也可以提前在拓扑图中编辑IP地址。

vim name.top

保存好之后,主要任务的前置任务就算完成了

3.2基础实验


首先再打开一个终端,用来启动Wireshark进程

wireshark

如果您使用的账户非root模式,请在指令前加上sudo

之后 ,使用第一个终端运行 保存好的拓扑图py文件

python {name}.py

pingall

打开Wireshark开始分析数据包
当控制器和交换机建立连接时,它们会通过发送 "OFPT_HELLO" 消息进行握手。这个握手过程用于确保双方都理解彼此的通信协议版本,并为后续的通信建立基础。,其中包含了源端口号(6633)与目的端口号(59784)

并且可以看到使用的传输协议是TCP协议

查看openflow_v6的数据包

查看openflow_v1的数据包的OFPT_FEATURES_REQUEST,OFPT_FEATURES_REQUEST用于控制器向交换机请求交换机的特性和能力。当控制器与交换机建立连接后,通常会发送此类消息以获取关于交换机的信息,以便控制器可以了解交换机的功能和配置。

查看openflow_v1的数据包的OPTF_SET_CONFIG,OPTF_SET_CONFIG可以确保控制器和交换机之间的行为一致,并能够对交换机的行为进行精细的控制。

查看openflow_v1的数据包的OPTF_PACKET_IN,OPTF_PACKET_IN用于将从交换机收到的数据包传送给控制器。当交换机无法根据当前的流表项处理接收到的数据包时,会生成一个 "OFPT_PACKET_IN" 消息,并将数据包及相关信息发送到控制器。

查看openflow_v1的数据包的OPTF_PACKET_OUT, 通过“OFPT_PACKET_OUT”消息,控制器可以实现对数据包的编程式控制,用于实现特定的网络行为、策略或功能。
 

查看openflow_v1的数据包的OPTF_PACKET_MOD, 通过发送 "OFPT_FLOW_MOD" 消息,控制器可以向交换机添加、修改或删除流表项,从而控制数据包的处理方式。

3.3进阶实验


在OpenFlow的安装目录中,通过对比抓包结果和源代码,可以了解OpenFlow主要消息类型所对应的数据结构定义。相关的数据结构定义可以在openflow/include/openflow/openflow.h头文件中找到。

接下来我们将对openflow.h对比抓包结果进行分析

3.3.1  HELLO

以上四个为一一对应,分别是ofp版本、OFPT类型,长度与xid,xid为随机生成的一段字符串,两个数据包拥有相同的xid说明他们属于同一次会话

struct ofp_header {

    uint8_t version;    /* OFP版本。 */
    uint8_t type;       /* OFPT_常数之一。 */
    uint16_t length;    /* 长度,包括标头的长度。 */
    uint32_t xid;       /* 与此数据包关联的事务id。
                           回复使用与请求中相同的id
                           以便于配对。 */

};
struct ofp_hello {

    struct ofp_header header;

};
3.3.2  FEATURES_REQUEST


内容与HELLO的结构是相同的,所以这里就不举例子了


3.3.3  SET_CONFIG
/* Switch configuration. */

struct ofp_switch_config {

    struct ofp_header header;
    uint16_t flags;             /* OFPC_*标志。 */
    uint16_t miss_send_len;     /*数据路径应具有的新流的最大字节数
                                  发送到控制器。 */

};
3.3.4PORT_STATUS
/* A physical port has changed in the datapath */

struct ofp_port_status {

    struct ofp_header header;
    uint8_t reason;          /* OFPPR_*之一。 */
    uint8_t pad[7];          /* 对齐到64位。 */
    struct ofp_phy_port desc;

};
3.3.5FEATURES_REPLY
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位。 */

    /* Features. */
    uint32_t capabilities;  /* 支持“ofp_capabilities”的位图。 */
    uint32_t actions;       /* 支持的“ofp_action_type”s的位图。 */

    /* Port info.*/
    struct ofp_phy_port ports[0];  /* 端口定义。端口数
                                      根据中的长度字段推断
                                      标头。 */

};
/* Description of a physical port */

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;         /* OFPPC_*标志的位图。 */

    /* Bitmaps of OFPPF_* that describe features.  All bits zeroed if
     * unsupported or unavailable. */
    uint32_t curr;          /* 当前功能。 */
    uint32_t advertised;    /* 端口正在播发的功能。 */
    uint32_t supported;     /* 端口支持的功能。 */
    uint32_t peer;          /* 同行宣传的功能。 */

};
3.3.6PACKET_IN
有两种情况
交换机查找流表,发现没有匹配条目
enum ofp_packet_in_reason {

    OFPR_NO_MATCH,          /* 没有匹配的流。*/
    OFPR_ACTION             /* 动作明确输出到控制器。 */

};

有匹配条目,对应的action是OUTPUT=CONTROLLER,固定收到向控制器发送包

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(结构of_packet_in,数据)==
                               sizeof(struct-ofp_packet_in)-2。 */

};
3.3.7PACKET_OUT
struct ofp_packet_out {

    struct ofp_header header;
    uint32_t buffer_id;           /* 由数据路径分配的ID(如果没有,则为-1)。 */
    uint16_t in_port;             /* 数据包的输入端口(如果没有,则为OFPP_NONE)。 */
    uint16_t actions_len;         /* 操作数组的大小(以字节为单位)*/
                                     结构of_action_header actions[0];/*行动。 */
    /* uint8_t data[0]; */        /* 数据包数据。推断长度
                                     来自标头中的长度字段。
                                    (只有当buffer_id==-1时才有意义。) */

};
3.3.8FLOW_MOD
struct ofp_flow_mod {
    struct ofp_header header;
    struct ofp_match match;      /* 要匹配的字段 */
    uint64_t cookie;             /* 不透明控制器发布的标识符。 */

    /* Flow actions. */
    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]; /* 推断动作长度
                                            中的长度字段
                                            头 */
};
struct ofp_action_header {
    uint16_t type;                  /* OFPAT_*之一。 */
    uint16_t len;                   /* 行动时间长度,包括
                                       头这是动作的长度,
                                       包括任何填充物
                                       64位对齐。 */
    uint8_t pad[4];
};

4.总结

  • 实验难度:适中
  • 实验过程遇到的困难及解决办法:
    • 第一次建立拓扑后,因为操作错误想重新做一次,结果再次运行py文件,提示说文件已存在,一时有点不知所措。查询资料后发现可以用sudo mn -c删除一下,然后重新启动虚拟机再重新运行就可以了。
    • 打开wireshark后创建拓扑,过滤出Openflow数据包,发现没有找到Flow_Mod的数据包。重新看了老师给的pdf,并上网搜索资料后发现要先pingall一下,才能找到Flow_mod数据包。
  • 个人感想:

这次实验是验证性实验,实验难度相对会容易些,只需要建立拓扑后在wireshark中操作,就是找包的时候数据比较多,看起来比较累眼睛。通过阅读openflow的源码,能理清楚其中的数据结构,并和实际抓到的包的详细信息对应起来,从而理解openflow协议的数据包交互过程。除此之外,对wireshark中过滤器的使用也有了更深刻的了解,对openflow协议有了更深刻的认识。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐