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

相关文章

网页解析 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对象

【Linux】应用层http协议

一、HTTP协议 1.1 简要介绍一下HTTP        我们在网络的应用层中可以自己定义协议,但是,已经有大佬定义了一些现成的,非常好用的应用层协议,供我们直接使用,HTTP(超文本传输协议)就是其中之一。        在互联网世界中,HTTP(超文本传输协议)是一个至关重要的协议,他定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或者传输超文本(比如HTML文档)。

OWASP十大安全漏洞解析

OWASP(开放式Web应用程序安全项目)发布的“十大安全漏洞”列表是Web应用程序安全领域的权威指南,它总结了Web应用程序中最常见、最危险的安全隐患。以下是对OWASP十大安全漏洞的详细解析: 1. 注入漏洞(Injection) 描述:攻击者通过在应用程序的输入数据中插入恶意代码,从而控制应用程序的行为。常见的注入类型包括SQL注入、OS命令注入、LDAP注入等。 影响:可能导致数据泄

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

多线程解析报表

假如有这样一个需求,当我们需要解析一个Excel里多个sheet的数据时,可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成。 Way1 join import java.time.LocalTime;public class Main {public static void main(String[] args) thro

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(