OpenFlowJ-Loxigen - OFType
2/26/2017 11:07:29 PM
最近在学习使用Floodlight,OpenFlowJ-Loxigen是Floodlight中对OpenFlow协议的一个抽象层。它是用Java语言实现的,为上层应用提供了通用的和根据版本制定的Java API,为控制器与交换机之间的信息交换和控制提供易于使用的接口。本篇博文主要用于学习OpenFlowJ-Loxigen时的知识梳理,和之前或之后的其他系列的博文一样,会以流水账的形式记录知识点。因此,本博文的知识覆盖面一般不会很全面,需要全面了解OpenFlowJ-Loxigen的同学,可以进入官网查阅OpenFlowJ-Loxigen的Java Doc。
2017-2-28
本来准备只写一个简单的对该枚举量的介绍,然而没有想到居然扯到OpenFlowJ-Loxigen是如何对不同版本的OFType进行封装了。因为暂时要查阅一些资料,所以明后日再更(2017-3-2之前),感兴趣的同学敬请期待。
2017-3-2
晚上有算法讨论,时间有点紧,今天暂不更新了…
OFType是OpenFlowJ-Loxigen中的一个枚举量,官方文库中的类型声明为:
Enum OFType
该枚举量中的元素如下表所示,我们可以看到OFType中所包含的元素超过了20个,但我们在开发时并不一定每个都需要用到。官方文档中给出了元素的名称,但没有给出每个元素的详细介绍,而这则是OpenFlow协议的内容。然后,问题来了,OpenFlow经历了多个版本,这些元素又支持哪些版本呢。官方的说法是OpenFlowJ-Loxigen目前支持OpenFlow的版本为1.0,1.1,1.2,1.3,1.4 ,那么OFType是否可以通用呢,我们可以查看一下几个常用的元素在不同版本的OpenFlow协议中的定义(1.0,1.3):
元素名称 | 含义 |
---|---|
HELLO——————– | 1.0:Hello messages are exchanged between the switch and controller upon connection startup. 1.3:Hello messages are exchanged between the switch and controller upon connection startup |
ERROR | |
ECHO_REQUEST | |
ECHO_REPLY | |
EXPERIMENTER | |
FEATURES_REQUEST | |
FEATURES_REPLY | |
GET_CONFIG_REQUEST | |
GET_CONFIG_REPLY | |
SET_CONFIG | |
PACKET_IN | 1.0:For all packets that do not have a matching flow entry, a packet-in event is sent to the controller (or if a packet matches an entry with a \send to controller” action). If the switch has sufficient memory to buffer packets that are sent to the controller, the packet-in events contain some fraction of the packet header (by default 128 bytes) and a buffer ID to be used by the controller when it is ready for the switch to forward the packet. Switches that do not support internal buffering (or have run out of internal buffering) must send the full packet to the controller as part of the event. 1.3:Transfer the control of a packet to the controller. For all packets forwarded to the CONTROLLER reserved port using a flow entry or the table-miss flow entry, a packet-in event is always sent to controllers (see 5.12). Other processing, such as TTL checking, may also send packets to the controller using packet-in events. Packet-in events can be configured to buffer packets. For packet-in generated by an output action in a flow entries or group bucket, it can be specified individually in the output action itself (see A.2.5), for other packet-in it can be configured in the switch configuration (see A.3.2). If the packet-in event is configured to buffer packets and the switch has sufficient memory to buffer them, the packet-in events contain only some fraction of the packet header and a buffer ID to be used by a controller when it is ready for the switch to forward the packet. Switches that do not support internal buffering, are configured to not buffer packets for the packet-in event, or have run out of internal buffering, must send the full packet to controllers as part of the event. Buffered packets will usually be processed via a Packet-out message from a controller, or automatically expired after some time. If the packet is buffered, the number of bytes of the original packet to include in the packet-in can be configured. By default, it is 128 bytes. For packet-in generated by an output action in a flow entries or group bucket, it can be specified individually in the output action itself (see A.2.5), for other packet-in it can be configured in the switch configuration (see A.3.2). |
FLOW_REMOVED | 1.0:When a flow entry is added to the switch by a flow modify message, an idle timeout value indicates when the entry should be removed due to a lack of activity, as well as a hard timeout value that indicates when the entry should be removed, regardless of activity. The flow modify message also specifies whether the switch should send a flow removed message to the controller when the flow expires. Flow modify messages which delete flows may also cause flow removed messages. 1.3:Inform the controller about the removal of a flow entry from a flow table. FlowRemoved messages are only sent for flow entries with the OFPFF_SEND_FLOW_REM flag set. They are generated as the result of a controller flow delete requests or the switch flow expiry process when one of the flow timeout is exceeded (see 5.5) |
PORT_STATUS | |
PACKET_OUT | 1.0:这里在OpenFlow Protocol Overview中提到的是Send-Packet,原文:These are used by the controller to send packets out of a specified port on the switch. 1.3:These are used by the controller to send packets out of a specified port on the switch, and to forward packets received via Packet-in messages. Packet-out messages must contain a full packet or a buffer ID referencing a packet stored in the switch. The message must also contain a list of actions to be applied in the order they are specified; an empty action list drops the packet. |
FLOW_MOD | 1.0:Modify-State messages are sent by the controller to manage state on the switches. Their primary purpose is to add/delete and modify flows in the flow tables and to set switch port properties. 1.3:Modify-State messages are sent by the controller to manage state on the switches. Their primary purpose is to add, delete and modify flow/group entries in the OpenFlow tables and to set switch port properties. |
PORT_MOD | |
STATS_REQUEST | |
STATS_REPLY | |
BARRIER_REQUEST | |
BARRIER_REPLY | |
QUEUE_GET_CONFIG_REQUEST | |
QUEUE_GET_CONFIG_REPLY | |
GROUP_MOD | |
TABLE_MOD | |
ROLE_REQUEST | |
ROLE_REPLY | |
GET_ASYNC_REQUEST | |
GET_ASYNC_REPLY | |
SET_ASYNC | |
METER_MOD | |
ROLE_STATUS | |
TABLE_STATUS | |
REQUESTFORWARD | |
BUNDLE_CONTROL | |
BUNDLE_ADD_MESSAGE |
上面表格中的内容取自OpenFlow Protocol Overview。OpenFlow Protocol Overview中对OpenFlow协议支持的三种message的类型和不同message类型下的子类型进行了简单介绍(三种message类型:controller-to-switch, asynchronous, and symmetric)。所以FLOW_MOD的含义其实我是摘抄的Controller-to-Switch中Modify-State的定义,而FLOW_MOD则是Modify-State的一个子类。这之后我本来是打算比较不同版本的具体细节,如PACKET_IN,FLOW_REMOVED以及FLOW_MOD这三个消息的具体定义。但是我发现OpenFlow中也定义了OFType(原谅我,我也是个新手)。所以我们先来比较一下,OpenFlow中对OFType的定义和OpenFlowJ-Loxigen中的定义吧:
v1.0
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 */
};
v1.3
enum ofp_type {
/* Immutable messages. */
OFPT_HELLO = 0, /* Symmetric message */
OFPT_ERROR = 1, /* Symmetric message */
OFPT_ECHO_REQUEST = 2, /* Symmetric message */
OFPT_ECHO_REPLY = 3, /* Symmetric message */
OFPT_EXPERIMENTER = 4, /* Symmetric message */
/* Switch configuration messages. */
OFPT_FEATURES_REQUEST = 5, /* Controller/switch message */
OFPT_FEATURES_REPLY = 6, /* Controller/switch message */
OFPT_GET_CONFIG_REQUEST = 7, /* Controller/switch message */
OFPT_GET_CONFIG_REPLY = 8, /* Controller/switch message */
OFPT_SET_CONFIG = 9, /* Controller/switch message */
/* Asynchronous messages. */
OFPT_PACKET_IN = 10, /* Async message */
OFPT_FLOW_REMOVED = 11, /* Async message */
OFPT_PORT_STATUS = 12, /* Async message */
/* Controller command messages. */
OFPT_PACKET_OUT = 13, /* Controller/switch message */
OFPT_FLOW_MOD = 14, /* Controller/switch message */
OFPT_GROUP_MOD = 15, /* Controller/switch message */
OFPT_PORT_MOD = 16, /* Controller/switch message */
OFPT_TABLE_MOD = 17, /* Controller/switch message */
/* Multipart messages. */
OFPT_MULTIPART_REQUEST = 18, /* Controller/switch message */
OFPT_MULTIPART_REPLY = 19, /* Controller/switch message */
/* Barrier messages. */
OFPT_BARRIER_REQUEST = 20, /* Controller/switch message */
OFPT_BARRIER_REPLY = 21, /* Controller/switch message */
/* Queue Configuration messages. */
OFPT_QUEUE_GET_CONFIG_REQUEST = 22, /* Controller/switch message */
OFPT_QUEUE_GET_CONFIG_REPLY = 23, /* Controller/switch message */
/* Controller role change request messages. */
OFPT_ROLE_REQUEST = 24, /* Controller/switch message */
OFPT_ROLE_REPLY = 25, /* Controller/switch message */
/* Asynchronous message configuration. */
OFPT_GET_ASYNC_REQUEST = 26, /* Controller/switch message */
OFPT_GET_ASYNC_REPLY = 27, /* Controller/switch message */
OFPT_SET_ASYNC = 28, /* Controller/switch message */
/* Meters and rate limiters configuration messages. */
OFPT_METER_MOD = 29, /* Controller/switch message */
};
简单的比较,我们会发现1.3的版本还是与1.0的版本有很大的不同的,那么OpenFlowJ-Loxigen是如何处理不同版本之间的差异的呢?
敬请期待。
当我们比较一个协议的不同版本的时候,当然需要比较不同版本的具体细节。下面我们对PACKET_IN,FLOW_REMOVED以及FLOW_MOD这三个消息的具体定义做一个比较:
- OFPT_PACKET_IN:
v1.0
/* 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);
v1.3
/* 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. */
uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */
uint8_t table_id; /* ID of the table that was looked up */
uint64_t cookie; /* Cookie of the flow entry that was looked up. */
struct ofp_match match; /* Packet metadata. Variable size. */
/* Followed by:
* - Exactly 2 all-zero padding bytes, then
* - An Ethernet frame whose length is inferred from header.length.
* The padding bytes preceding the Ethernet frame ensure that the IP
* header (if any) following the Ethernet header is 32-bit aligned.
*/
//uint8_t pad[2]; /* Align to 64 bit + 16 bit */
//uint8_t data[0]; /* Ethernet frame */
};
OFP_ASSERT(sizeof(struct ofp_packet_in) == 32);
- OFPT_FLOW_REMOVED:
v1.0
/* Flow removed (datapath -> controller). */
struct ofp_flow_removed {
struct ofp_header header;
struct ofp_match match; /* Description of fields. */
uint64_t cookie; /* Opaque controller-issued identifier. */
uint16_t priority; /* Priority level of flow entry. */
uint8_t reason; /* One of OFPRR_*. */
uint8_t pad[1]; /* Align to 32-bits. */
uint32_t duration_sec; /* Time flow was alive in seconds. */
uint32_t duration_nsec; /* Time flow was alive in nanoseconds beyond
duration_sec. */
uint16_t idle_timeout; /* Idle timeout from original flow mod. */
uint8_t pad2[2]; /* Align to 64-bits. */
uint64_t packet_count;
uint64_t byte_count;
};
OFP_ASSERT(sizeof(struct ofp_flow_removed) == 88);
v1.3
/* Flow removed (datapath -> controller). */
struct ofp_flow_removed {
struct ofp_header header;
uint64_t cookie; /* Opaque controller-issued identifier. */
uint16_t priority; /* Priority level of flow entry. */
uint8_t reason; /* One of OFPRR_*. */
uint8_t table_id; /* ID of the table */
uint32_t duration_sec; /* Time flow was alive in seconds. */
uint32_t duration_nsec; /* Time flow was alive in nanoseconds beyond
duration_sec. */
uint16_t idle_timeout; /* Idle timeout from original flow mod. */
uint16_t hard_timeout; /* Hard timeout from original flow mod. */
uint64_t packet_count;
uint64_t byte_count;
struct ofp_match match; /* Description of fields. Variable size. */
};
OFP_ASSERT(sizeof(struct ofp_flow_removed) == 56);
- OFPT_FLOW_MOD
v1.0
/* 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);
v1.3
/* Flow setup and teardown (controller -> datapath). */
struct ofp_flow_mod {
struct ofp_header header;
uint64_t cookie; /* Opaque controller-issued identifier. */
uint64_t cookie_mask; /* Mask used to restrict the cookie bits
that must match when the command is
OFPFC_MODIFY* or OFPFC_DELETE*. A value
of 0 indicates no restriction. */
/* Flow actions. */
uint8_t table_id; /* ID of the table to put the flow in.
For OFPFC_DELETE_* commands, OFPTT_ALL
can also be used to delete matching
flows from all tables. */
uint8_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
OFP_NO_BUFFER.
Not meaningful for OFPFC_DELETE*. */
uint32_t out_port; /* For OFPFC_DELETE* commands, require
matching entries to include this as an
output port. A value of OFPP_ANY
indicates no restriction. */
uint32_t out_group; /* For OFPFC_DELETE* commands, require
matching entries to include this as an
output group. A value of OFPG_ANY
indicates no restriction. */
uint16_t flags; /* One of OFPFF_*. */
uint8_t pad[2];
struct ofp_match match; /* Fields to match. Variable size. */
//struct ofp_instruction instructions[0]; /* Instruction set */
};
OFP_ASSERT(sizeof(struct ofp_flow_mod) == 56);