OpenFlow好文集锦-OpenFlow1.0协议解析

2024-02-10 09:10

本文主要是介绍OpenFlow好文集锦-OpenFlow1.0协议解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 OpenFlow1.0协议解析

控制器通过Openflow管理、控制交换机,分析wireshark抓到的OpenFlow包就可以大体推测控制器与交换机通信的流程。虽然没有进行任何操作,但是一旦交换机连接控制器,wireshark就能捕捉到很多OpenFlow包。依次是hello消息、feature消息,stats消息,以及packet_in和packet_out。

1 Hello

控制器与交换机建立连接时由其中某一方发起Hello消息,双方协调协议版本号。Hello消息只有of包头,没有主体部分。而of头部结果如下:
/* Header on all OpenFlow packets. */
struct ofp_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 this packet. Replies use the same id as was in the request to facilitate pairing. */
};
OFP_ASSERT(sizeof(struct ofp_header) == 8);

Hello消息如下:
Version:OpenFlow版本,低位为版本号,如上所示。
Type:OpenFlow消息类型,主要包括:
注:
enum ofp_type {
/* Immutable messages. */
OFPT_HELLO, /* Symmetric message */
OFPT_ERROR, /* Symmetric message */
OFPT_ECHO_REQUEST, /* Symmetric message */
OFPT_ECHO_REPLY, /* Symmetric message */
OFPT_VENDOR, /* Symmetric message */
/* Switch configuration messages. */
OFPT_FEATURES_REQUEST, /* Controller/switch message */
OFPT_FEATURES_REPLY, /* Controller/switch message */
OFPT_GET_CONFIG_REQUEST, /* Controller/switch message */
OFPT_GET_CONFIG_REPLY, /* Controller/switch message */
OFPT_SET_CONFIG, /* Controller/switch message */
/* Asynchronous messages. */
OFPT_PACKET_IN, /* Async message */
OFPT_FLOW_REMOVED, /* Async message */
OFPT_PORT_STATUS, /* Async message */
/* Controller command messages. */
OFPT_PACKET_OUT, /* Controller/switch message */
OFPT_FLOW_MOD, /* Controller/switch message */
OFPT_PORT_MOD, /* Controller/switch message */
/* Statistics messages. */
OFPT_STATS_REQUEST, /* Controller/switch message */
OFPT_STATS_REPLY, /* Controller/switch message */
/* Barrier messages. */
OFPT_BARRIER_REQUEST, /* Controller/switch message */
OFPT_BARRIER_REPLY, /* Controller/switch message */
/* Queue Configuration messages. */
OFPT_QUEUE_GET_CONFIG_REQUEST, /* Controller/switch message */
OFPT_QUEUE_GET_CONFIG_REPLY /* Controller/switch message */
};

Length:消息总长度,包含头部。
Xid:事件ID,同一件事件的ID号一致。如feature_request和对应的feature_reply就使用同一个Transaction id,但是两个hello消息的Transaction id并不相同,不过据实验结果看两个id一般是两个相邻的数字。并且packet_in的transaction id都为0。

2 Feature消息

TLS会话一建立,控制器就会向交换机发送一个ofpt_feature_request消息,该消息只有of包头,如下所示。交换机会回复一条ofpt_feature_reply消息。
ofpt_feature_request如图:(有时候会发现一个数据包中有多个request,并且后面会有一一对应的reply包。)

ofpt_feature_reply如图:

ofpt_feature_reply消息结构如下:
注:
/* Switch features. */
struct ofp_switch_features {
struct ofp_header header;
uint64_t datapath_id; /* Datapath unique ID. The lower 48-bits are for a MAC 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 by datapath. */
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 the length field in the header. */
};
OFP_ASSERT(sizeof(struct ofp_switch_features) == 32);

datapath_id:数据通道独一无二的标识符,低48位是一个MAC地址,而高16位是自定义的。例如,用高16位代表VLAN ID区别一个物理交换机中的多个虚拟交换机。
n_buffers:一次最多缓存的数据包数量。
n_tables:表示交换机支持的流表数量。而每个流表可以设置不同的通配符和不同数量的流表项。控制器和交换机第一次通信的时候,控制器会从feature_reply消息中找出交换机支持多少流表,如果控制器还想了解大小、类型和流表查询的顺序,就发送一个ofpst_table stats请求,交换机必须按照数据包遍历流表的顺序把这些流表回复给控制器,并且精确匹配流表排在通配流表前。
capabilities:所支持的功能,该字段使用以下flags:
注:
/* Capabilities supported by the datapath. */
enum ofp_capabilities {
OFPC_FLOW_STATS = 1 << 0, /* Flow statistics. */
OFPC_TABLE_STATS = 1 << 1, /* Table statistics. */
OFPC_PORT_STATS = 1 << 2, /* Port statistics. */
OFPC_STP = 1 << 3, /* 802.1d spanning tree. */
OFPC_RESERVED = 1 << 4, /* Reserved, must be zero. */
OFPC_IP_REASM = 1 << 5, /* Can reassemble IP fragments. */
OFPC_QUEUE_STATS = 1 << 6, /* Queue statistics. */
OFPC_ARP_MATCH_IP = 1 << 7 /* Match IP addresses in ARP pkts. */
};
actions:该bitmask表示交换机所支持的actions,“required”action必须支持,vendor action不应该通过该bitmask显示,actions根据ofp_action_type的值决定需要左移几位。
ports[0]:以数组的形式罗列出该系统中支持OpenFlow的物理端口。数据长度可以根据OpenFlow头部中的length推测出来。

3 Packet_in消息

当交换机碰到新数据包不知道如何处理,或者action要求发送给控制器,那么交换机就会用packet_in消息发送给控制器。一般将数据包缓存在交换机中,将有效的数据包信息(默认的128字节,如果原因是 “send to controller” action,那么长度由action_out的max_len决定;如果是原因table miss,那么长度由set_config消息中的miss_send_len决定。)和缓存id发送给控制器,不过,如果交换机不支持缓存或者内存用光了,那么就把整个数据包放在数据部分发给控制器,并且缓存id为-1。
Packet_in消息如下:





Packet_in消息结构如下:

/* Packet received on port (datapath -> controller). */
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);

buffer_id:数据通道分配的缓存id,标志数据包存在交换机中的位置,如果没有缓存在交换机中则buffer_id则为-1。
total_len:整个数据帧的长度。
in_port:接收数据帧的端口。
reason:将数据包发送给控制器的原因,一般有俩原因,一是没有匹配到流表项,二是动作要求发给控制器。

4 Packet_out消息

当控制器希望交换机发送某个数据包,就使用packet_out消息。Packet_out消息如下所示:

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.) */
};
OFP_ASSERT(sizeof(struct ofp_packet_out) == 16);

buffer_id:与packet_in中给的一样,如果为-1就表明数据包附在数据数组中。

5 Configuration消息

控制器可以发送OFPT_SET_CONFIG / OFPT_GET_CONFIG_REQUEST消息设置/查询交换机配置参数,交换机只需响应OFPT_GET_CONFIG_REQUEST消息即可。
OFPT_SET_CONFIG消息如下所示:

OFPT_GET_CONFIG_REQUEST消息没有消息主体,OFPT_SET_CONFIG 、OFPT_GET_CONFIG_reply的消息结构如下所示:

/* Switch configuration. */
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);

Flags:配置类型flags,主要包括:
注:
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
};
miss_send_len:决定发送给控制器的数据包长度,如果该字段为0,则交换机发送一个大小为0的packet_in消息。

6 Stats消息

交换机和控制器连接后,控制器会不断发送stats消息询问交换机的状态,就好像两个打电话的人,一方不断询问“你在吗?”另一方不断回答“在呀!”抓到的stats消息如下所示:


ofp_stats_request和ofp_stats_reply消息结构相同,都使用以下结构:
注:
struct ofp_stats_request {
struct ofp_header header;
uint16_t type; /* One of the OFPST_* constants. */
uint16_t flags; /* OFPSF_REQ_* flags (none yet defined). */
uint8_t body[0]; /* Body of the request. */
};
OFP_ASSERT(sizeof(struct ofp_stats_request) == 12);

Type:该字段决定传递的信息的类型并且怎样解释body部分。主要包括:
注:

enum ofp_stats_types {
/* Description of this OpenFlow switch.
* The request body is empty.
* The reply body is struct ofp_desc_stats. */
OFPST_DESC,
/* Individual flow statistics.
* The request body is struct ofp_flow_stats_request.
* The reply body is an array of struct ofp_flow_stats. */
OFPST_FLOW,
/* Aggregate flow statistics.
* The request body is struct ofp_aggregate_stats_request.
* The reply body is struct ofp_aggregate_stats_reply. */
OFPST_AGGREGATE,
/* Flow table statistics.
* The request body is empty.
* The reply body is an array of struct ofp_table_stats. */
OFPST_TABLE,
/* Physical port statistics.
* The request body is struct ofp_port_stats_request.
* The reply body is an array of struct ofp_port_stats. */
OFPST_PORT,
/* Queue statistics for a port
* The request body defines the port
* The reply body is an array of struct ofp_queue_stats */
OFPST_QUEUE,
/* Vendor extension.
* The request and reply bodies begin with a 32-bit vendor ID, which takes
* the same form as in "struct ofp_vendor_header". The request and reply
* bodies are otherwise vendor-defined. */
OFPST_VENDOR = 0xffff
};
Flags:ofp_stats_request的flag字段目前还没有定义,而reply消息的flag字段只有一个值0x0001,该值表示后面是否还有更多的reply。

7 Flow_mod

控制器与交换机建立连接后,控制器会自发给交换机发送一组flow_mod消息,抓到的消息如下:

flow_mod消息结构:

/* Flow setup and teardown (controller -> datapath). */
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);
Cookie: 控制器设置的不透明数据。当command为OFPFC_MODIFY或OFPFC_MODIFY_STRICT时,匹配了的流表项需要适当的更新cookie字段。
Command可能会是
注:
enum ofp_flow_mod_command {
OFPFC_ADD, /* New flow. */
OFPFC_MODIFY, /* Modify all matching flows. */
OFPFC_MODIFY_STRICT, /* Modify entry strictly matching wildcards */
OFPFC_DELETE, /* Delete all matching flows. */
OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */
};

idle_timeout和hard_timeout控制流表项的生命周期。当idle_timeout为x(x不为0)并且hard_timeout为0时,流表项在x秒收不到数据包后就到期。当idle_timeout为0并且hard_timeout为x时,x秒后无论收不收得到数据包流表项都到期。当idle_timeout为x(x不为0)并且hard_timeout为y(y不为0)时,x秒收不到数据包或者y秒后,哪个期限先到就按哪个算。当idle_timeout和hard_timeout都为0时,表明这个流表项是永恒的,除非用OFPFC_DELETE删除,否则不会到期。
priority:priority只和含通配字段的流表项有关。Priority值越大,表明流表优先级越高。交换机必须将优先级最高的通配流表项放在编号最低的通配流表中。无论流表是什么配置,交换机需要确保精确流表项排在通配流表项之前。
buffer_id:标志由packet_in消息发送的数据包存储的地方。
out_port:delete和delete_strict消息利用该字段确定作用域,而add、modify、modify_strict消息会自动忽略该字段。如果out_port为ofpp_none则表明禁用output端口过滤功能,否则就相当于添加了一个额外的匹配限制条件。连0也是有效端口id,表示约束条件是必须有关于该端口的output动作。而ofp_match和优先级等条件依旧生效,该字段只是添加了一个额外的约束。
flags:flags主要包括:
注:
enum ofp_flow_mod_flags {
OFPFF_SEND_FLOW_REM = 1 << 0, /* Send flow removed message when flow
* expires or is deleted. */
OFPFF_CHECK_OVERLAP = 1 << 1, /* Check for overlapping entries first. */
OFPFF_EMERG = 1 << 2 /* Remark this is for emergency. */
};
(1)、设置OFPFF_SEND_FLOW_REM标识表示当流表项到期时交换机发送一条flow removed消息,一般默认情况下交换机是不会为新添加的流表项发送flow removed消息的。
(2)、OFPFF_CHECK_OVERLAP生效表明交换机必须检查是否有优先级冲突的流表项,如果冲突,则flow mod无效并且回复错误提醒。
(3、)OFPFF_EMERG为1则代表该流表项是紧急流表项,当交换机与控制器断开连接时就利用该表项转发数据包。

收集自 http://www.jianshu.com/p/e660508f1c5d

这篇关于OpenFlow好文集锦-OpenFlow1.0协议解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/696708

相关文章

使用Python实现批量访问URL并解析XML响应功能

《使用Python实现批量访问URL并解析XML响应功能》在现代Web开发和数据抓取中,批量访问URL并解析响应内容是一个常见的需求,本文将详细介绍如何使用Python实现批量访问URL并解析XML响... 目录引言1. 背景与需求2. 工具方法实现2.1 单URL访问与解析代码实现代码说明2.2 示例调用

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

在C#中合并和解析相对路径方式

《在C#中合并和解析相对路径方式》Path类提供了几个用于操作文件路径的静态方法,其中包括Combine方法和GetFullPath方法,Combine方法将两个路径合并在一起,但不会解析包含相对元素... 目录C#合并和解析相对路径System.IO.Path类幸运的是总结C#合并和解析相对路径对于 C

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象