Initial OpenFlow 1.3 support with new include/openflow/openflow-1.3.h.
Most of the messages that differ from 1.2 are implemented. OFPT_SET_ASYNC
is implemented via NX_SET_ASYNC_CONFIG, other new message types are yet to
be implemented. Stats replies that add duration fields are implemented at
encode/decode level only. Test cases for implemented features are included.
Remaining FIXME:s should not cause runtime aborts. Make check comes out
clean.
Signed-off-by: Jarno Rajahalme <jarno.rajahalme@nsn.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
names = []
domain = {}
reverse = {}
- for domain_name in ("OF1.0", "OF1.1", "OF1.2", "NX1.0", "NX1.1"):
+ for domain_name in ("OF1.0", "OF1.1", "OF1.2", "OF1.3",
+ "NX1.0", "NX1.1", "NX1.2", "NX1.3"):
domain[domain_name] = {}
reverse[domain_name] = {}
else:
code = None
- target_map = {"OF1.0+": ("OF1.0", "OF1.1", "OF1.2"),
- "OF1.1+": ("OF1.1", "OF1.2"),
- "OF1.2+": ("OF1.2",),
+ target_map = {"OF1.0+": ("OF1.0", "OF1.1", "OF1.2", "OF1.3"),
+ "OF1.1+": ("OF1.1", "OF1.2", "OF1.3"),
+ "OF1.2+": ("OF1.2", "OF1.3"),
+ "OF1.3+": ("OF1.3",),
"OF1.0": ("OF1.0",),
"OF1.1": ("OF1.1",),
"OF1.2": ("OF1.2",),
- "NX1.0+": ("OF1.0", "OF1.1", "OF1.2"),
+ "OF1.3": ("OF1.3",),
+ "NX1.0+": ("OF1.0", "OF1.1", "OF1.2", "OF1.3"),
+ "NX1.1+": ("OF1.1", "OF1.2", "OF1.3"),
+ "NX1.2+": ("OF1.2", "OF1.3"),
+ "NX1.3+": ("OF1.3",),
"NX1.0": ("OF1.0",),
"NX1.1": ("OF1.1",),
- "NX1.1+": ("OF1.1",),
- "NX1.2": ("OF1.2",)}
+ "NX1.2": ("OF1.2",),
+ "NX1.3": ("OF1.3",)}
if targets not in target_map:
fatal("%s: unknown error domain" % targets)
if targets.startswith('NX') and code < 0x100:
output_domain(reverse["OF1.0"], "ofperr_of10", "OpenFlow 1.0", 0x01)
output_domain(reverse["OF1.1"], "ofperr_of11", "OpenFlow 1.1", 0x02)
output_domain(reverse["OF1.2"], "ofperr_of12", "OpenFlow 1.2", 0x03)
+ output_domain(reverse["OF1.3"], "ofperr_of13", "OpenFlow 1.3", 0x04)
if __name__ == '__main__':
if '--help' in sys.argv:
"1.3+": (OFP13_VERSION, OFP13_VERSION),
"1.0-1.1": (OFP10_VERSION, OFP11_VERSION),
"1.0-1.2": (OFP10_VERSION, OFP12_VERSION),
+ "1.1-1.2": (OFP11_VERSION, OFP12_VERSION),
"<all>": (0x01, 0xff)}
def get_line():
include/openflow/openflow-1.0.h \
include/openflow/openflow-1.1.h \
include/openflow/openflow-1.2.h \
+ include/openflow/openflow-1.3.h \
include/openflow/openflow-common.h \
include/openflow/openflow.h
OFPC_FRAG_NX_MATCH = 3, /* Make first fragments available for matching. */
OFPC_FRAG_MASK = 3,
+ /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OpenFlow 1.3 */
+
/* TTL processing - applicable for IP and MPLS packets. */
OFPC_INVALID_TTL_TO_CONTROLLER = 1 << 2, /* Send packets with invalid TTL
to the controller. */
ovs_be32 curr_speed; /* Current port bitrate in kbps. */
ovs_be32 max_speed; /* Max port bitrate in kbps */
};
+OFP_ASSERT(sizeof(struct ofp11_port) == 64);
/* Modify behavior of the physical port */
struct ofp11_port_mod {
when this is not an exact-match entry. */
ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */
ovs_be16 hard_timeout; /* Number of seconds before expiration. */
- uint8_t pad2[6]; /* Align to 64-bits. */
+ ovs_be16 flags; /* OF 1.3: Set of OFPFF*. */
+ uint8_t pad2[4]; /* Align to 64-bits. */
ovs_be64 cookie; /* Opaque controller-issued identifier. */
ovs_be64 packet_count; /* Number of packets in flow. */
ovs_be64 byte_count; /* Number of bytes in flow. */
OFPXMT12_OFB_IPV6_ND_TLL, /* Target link-layer for ND. */
OFPXMT12_OFB_MPLS_LABEL, /* MPLS label. */
OFPXMT12_OFB_MPLS_TC, /* MPLS TC. */
+ /* Following added in OpenFlow 1.3 */
+ OFPXMT12_OFB_MPLS_BOS, /* MPLS BoS bit. */
+ OFPXMT12_OFB_PBB_ISID, /* PBB I-SID. */
+ OFPXMT12_OFB_TUNNEL_ID, /* Logical Port Metadata */
+ OFPXMT12_OFB_IPV6_EXTHDR, /* IPv6 Extension Header pseudo-field */
/* End Marker */
OFPXMT12_OFB_MAX,
#define OXM_OF_IPV6_ND_TLL OXM_HEADER (OFPXMT12_OFB_IPV6_ND_TLL, 6)
#define OXM_OF_MPLS_LABEL OXM_HEADER (OFPXMT12_OFB_MPLS_LABEL, 4)
#define OXM_OF_MPLS_TC OXM_HEADER (OFPXMT12_OFB_MPLS_TC, 1)
+#define OXM_OF_MPLS_BOS OXM_HEADER (OFPXMT12_OFB_MPLS_BOS, 1)
+#define OXM_OF_PBB_ISID OXM_HEADER (OFPXMT12_OFB_PBB_ISID, 4)
+#define OXM_OF_PBB_ISID_W OXM_HEADER_W (OFPXMT12_OFB_PBB_ISID, 4)
+#define OXM_OF_TUNNEL_ID OXM_HEADER (OFPXMT12_OFB_TUNNEL_ID, 8)
+#define OXM_OF_TUNNEL_ID_W OXM_HEADER_W (OFPXMT12_OFB_TUNNEL_ID, 8)
+#define OXM_OF_IPV6_EXTHDR OXM_HEADER (OFPXMT12_OFB_IPV6_EXTHDR, 2)
+#define OXM_OF_IPV6_EXTHDR_W OXM_HEADER_W (OFPXMT12_OFB_IPV6_EXTHDR, 2)
/* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate
* special conditions.
OFPVID12_NONE = 0x0000, /* No VLAN id was set. */
};
+/* Bit definitions for IPv6 Extension Header pseudo-field. */
+enum ofp12_ipv6exthdr_flags {
+ OFPIEH12_NONEXT = 1 << 0, /* "No next header" encountered. */
+ OFPIEH12_ESP = 1 << 1, /* Encrypted Sec Payload header present. */
+ OFPIEH12_AUTH = 1 << 2, /* Authentication header present. */
+ OFPIEH12_DEST = 1 << 3, /* 1 or 2 dest headers present. */
+ OFPIEH12_FRAG = 1 << 4, /* Fragment header present. */
+ OFPIEH12_ROUTER = 1 << 5, /* Router header present. */
+ OFPIEH12_HOP = 1 << 6, /* Hop-by-hop header present. */
+ OFPIEH12_UNREP = 1 << 7, /* Unexpected repeats encountered. */
+ OFPIEH12_UNSEQ = 1 << 8 /* Unexpected sequencing encountered. */
+};
+
/* Header for OXM experimenter match fields. */
struct ofp12_oxm_experimenter_header {
ovs_be32 oxm_header; /* oxm_class = OFPXMC_EXPERIMENTER */
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+* Junior University
+* Copyright (c) 2011, 2012 Open Networking Foundation
+*
+* We are making the OpenFlow specification and associated documentation
+* (Software) available for public use and benefit with the expectation
+* that others will use, modify and enhance the Software and contribute
+* those enhancements back to the community. However, since we would
+* like to make the Software available for broadest use, with as few
+* restrictions as possible permission is hereby granted, free of
+* charge, to any person obtaining a copy of this Software to deal in
+* the Software under the copyrights without restriction, including
+* without limitation the rights to use, copy, modify, merge, publish,
+* distribute, sublicense, and/or sell copies of the Software, and to
+* permit persons to whom the Software is furnished to do so, subject to
+* the following conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* The name and trademarks of copyright holder(s) may NOT be used in
+* advertising or publicity pertaining to the Software or any
+* derivatives without specific, written prior permission.
+*/
+
+/* OpenFlow: protocol between controller and datapath. */
+
+#ifndef OPENFLOW_13_H
+#define OPENFLOW_13_H 1
+
+#include "openflow/openflow-1.2.h"
+
+/*
+ * OpenFlow 1.3 modifies the syntax of the following message types:
+ *
+ * OFPT_FEATURES_REPLY = 6 (opf13_switch_features)
+ * - new field: auxiliary_id
+ * - removed: ofp_ports at the end
+ *
+ * OFPT_PACKET_IN = 10 (ofp13_packet_in) new field: cookie
+ *
+ * OpenFlow 1.3 adds following new message types:
+ *
+ * * Asynchronous message configuration. *
+ * OFPT13_GET_ASYNC_REQUEST = 26 (void)
+ * OFPT13_GET_ASYNC_REPLY = 27 (ofp13_async_config)
+ * OFPT13_SET_ASYNC = 28 (ofp13_async_config)
+ *
+ * * Meters and rate limiters configuration messages. *
+ * OFPT13_METER_MOD = 29 (ofp13_meter_mod)
+ *
+ * OpenFlow 1.3 modifies the syntax of the following statistics message types
+ * (now called multipart message types):
+ *
+ * OFPMP13_FLOW_REPLY = 1 (struct ofp13_flow_stats[])
+ * OFPMP13_TABLE_REPLY = 3 (struct ofp13_table_stats[])
+ * OFPMP13_PORT_REPLY = 4 (struct ofp13_port_stats[])
+ * OFPMP13_QUEUE_REPLY = 5, (struct ofp13_queue_stats[])
+ * OFPMP13_GROUP_REPLY = 6, (struct ofp13_group_stats[])
+ *
+ * OpenFlow 1.3 adds the following multipart message types
+ *
+ * Meter statistics:
+ * OFPMP13_METER_REQUEST = 9, (struct ofp13_meter_multipart_request)
+ * OFPMP13_METER_REPLY = 9, (struct ofp13_meter_stats[])
+ *
+ * Meter configuration:
+ * OFPMP13_METER_CONFIG_REQUEST = 10, (struct ofp13_meter_multipart_request)
+ * OFPMP13_METER_CONFIG_REPLY = 10, (struct ofp13_meter_config[])
+ *
+ * Meter features:
+ * OFPMP13_METER_FEATURES_REQUEST = 11 (void)
+ * OFPMP13_METER_FEATURES_REPLY = 11 (struct ofp13_meter_features)
+ *
+ * Table features:
+ * OFPMP13_TABLE_FEATURES_REQUEST = 12, (struct ofp13_table_features[])
+ * OFPMP13_TABLE_FEATURES_REPLY = 12, (struct ofp13_table_features[])
+ *
+ */
+
+enum ofp13_instruction_type {
+ OFPIT13_METER = 6 /* Apply meter (rate limiter) */
+};
+
+#define OFPIT13_ALL (OFPIT11_GOTO_TABLE | OFPIT11_WRITE_METADATA | \
+ OFPIT11_WRITE_ACTIONS | OFPIT11_APPLY_ACTIONS | \
+ OFPIT11_CLEAR_ACTIONS | OFPIT13_METER)
+
+/* Instruction structure for OFPIT_METER */
+struct ofp13_instruction_meter {
+ ovs_be16 type; /* OFPIT13_METER */
+ ovs_be16 len; /* Length is 8. */
+ ovs_be32 meter_id; /* Meter instance. */
+};
+OFP_ASSERT(sizeof(struct ofp13_instruction_meter) == 8);
+
+enum ofp13_action_type {
+ OFPAT13_PUSH_PBB = 26, /* Push a new PBB service tag (I-TAG) */
+ OFPAT13_PPO_PBB = 27 /* Pop the outer PBB service tag (I-TAG) */
+};
+
+/* enum ofp_config_flags value OFPC_INVALID_TTL_TO_CONTROLLER
+ * is deprecated in OpenFlow 1.3 */
+
+/* Flags to configure the table. Reserved for future use. */
+enum ofp13_table_config {
+ OFPTC13_DEPRECATED_MASK = 3 /* Deprecated bits */
+};
+
+/* OpenFlow 1.3 specific flags
+ * (struct ofp12_flow_mod, member flags). */
+enum ofp13_flow_mod_flags {
+ OFPFF13_NO_PKT_COUNTS = 1 << 3, /* Don\92t keep track of packet count. */
+ OFPFF13_NO_BYT_COUNTS = 1 << 4 /* Don\92t keep track of byte count. */
+};
+
+/* Common header for all meter bands */
+struct ofp13_meter_band_header {
+ ovs_be16 type; /* One of OFPMBT_*. */
+ ovs_be16 len; /* Length in bytes of this band. */
+ ovs_be32 rate; /* Rate for this band. */
+ ovs_be32 burst_size; /* Size of bursts. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_band_header) == 12);
+
+/* Meter configuration. OFPT_METER_MOD. */
+struct ofp13_meter_mod {
+ ovs_be16 command; /* One of OFPMC_*. */
+ ovs_be16 flags; /* Set of OFPMF_*. */
+ ovs_be32 meter_id; /* Meter instance. */
+ struct ofp13_meter_band_header bands[0]; /* The bands length is inferred
+ from the length field in the
+ header. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_mod) == 8);
+
+/* Meter numbering. Flow meters can use any number up to OFPM_MAX. */
+enum ofp13_meter {
+ /* Last usable meter. */
+ OFPM13_MAX = 0xffff0000,
+ /* Virtual meters. */
+ OFPM13_SLOWPATH = 0xfffffffd, /* Meter for slow datapath. */
+ OFPM13_CONTROLLER = 0xfffffffe, /* Meter for controller connection. */
+ OFPM13_ALL = 0xffffffff, /* Represents all meters for stat requests
+ commands. */
+};
+
+/* Meter commands */
+enum ofp13_meter_mod_command {
+ OFPMC13_ADD, /* New meter. */
+ OFPMC13_MODIFY, /* Modify specified meter. */
+ OFPMC13_DELETE /* Delete specified meter. */
+};
+
+/* Meter configuration flags */
+enum ofp13_meter_flags {
+ OFPMF13_KBPS = 1 << 0, /* Rate value in kb/s (kilo-bit per second). */
+ OFPMF13_PKTPS = 1 << 1, /* Rate value in packet/sec. */
+ OFPMF13_BURST = 1 << 2, /* Do burst size. */
+ OFPMF13_STATS = 1 << 3 /* Collect statistics. */
+};
+
+/* Meter band types */
+enum ofp13_meter_band_type {
+ OFPMBT13_DROP = 1, /* Drop packet. */
+ OFPMBT13_DSCP_REMARK = 2, /* Remark DSCP in the IP header. */
+ OFPMBT13_EXPERIMENTER = 0xFFFF /* Experimenter meter band. */
+};
+
+/* OFPMBT_DROP band - drop packets */
+struct ofp13_meter_band_drop {
+ ovs_be16 type; /* OFPMBT_DROP. */
+ ovs_be16 len; /* Length in bytes of this band. */
+ ovs_be32 rate; /* Rate for dropping packets. */
+ ovs_be32 burst_size; /* Size of bursts. */
+ uint8_t pad[4];
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_band_drop) == 16);
+
+/* OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header */
+struct ofp13_meter_band_dscp_remark {
+ ovs_be16 type; /* OFPMBT_DSCP_REMARK. */
+ ovs_be16 len; /* Length in bytes of this band. */
+ ovs_be32 rate; /* Rate for remarking packets. */
+ ovs_be32 burst_size; /* Size of bursts. */
+ uint8_t prec_level; /* Number of drop precedence level to add. */
+ uint8_t pad[3];
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_band_dscp_remark) == 16);
+
+/* OFPMBT_EXPERIMENTER band - Write actions in action set */
+struct ofp13_meter_band_experimenter {
+ ovs_be16 type; /* OFPMBT_EXPERIMENTER. */
+ ovs_be16 len; /* Length in bytes of this band. */
+ ovs_be32 rate; /* Rate for dropping packets. */
+ ovs_be32 burst_size; /* Size of bursts. */
+ ovs_be32 experimenter; /* Experimenter ID which takes the same form as
+ in struct ofp_experimenter_header. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_band_experimenter) == 16);
+
+/* OF 1.3 adds MORE flag also for requests */
+enum ofp13_multipart_request_flags {
+ OFPMPF13_REQ_MORE = 1 << 0 /* More requests to follow. */
+};
+
+/* OF 1.3 splits table features off the ofp_table_stats */
+/* Body of reply to OFPMP13_TABLE request. */
+struct ofp13_table_stats {
+ uint8_t table_id; /* Identifier of table. Lower numbered tables are
+ consulted first. */
+ uint8_t pad[3]; /* Align to 32-bits. */
+ ovs_be32 active_count; /* Number of active entries. */
+ ovs_be64 lookup_count; /* Number of packets looked up in table. */
+ ovs_be64 matched_count; /* Number of packets that hit table. */
+};
+OFP_ASSERT(sizeof(struct ofp13_table_stats) == 24);
+
+/* Common header for all Table Feature Properties */
+struct ofp13_table_feature_prop_header {
+ ovs_be16 type; /* One of OFPTFPT_*. */
+ ovs_be16 length; /* Length in bytes of this property. */
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_header) == 4);
+
+/* Body for ofp_multipart_request of type OFPMP_TABLE_FEATURES./
+ * Body of reply to OFPMP_TABLE_FEATURES request. */
+struct ofp13_table_features {
+ ovs_be16 length; /* Length is padded to 64 bits. */
+ uint8_t table_id; /* Identifier of table. Lower numbered tables
+ are consulted first. */
+ uint8_t pad[5]; /* Align to 64-bits. */
+ char name[OFP_MAX_TABLE_NAME_LEN];
+ ovs_be64 metadata_match; /* Bits of metadata table can match. */
+ ovs_be64 metadata_write; /* Bits of metadata table can write. */
+ ovs_be32 config; /* Bitmap of OFPTC_* values */
+ ovs_be32 max_entries; /* Max number of entries supported. */
+
+ /* Table Feature Property list */
+ struct ofp13_table_feature_prop_header properties[0];
+};
+OFP_ASSERT(sizeof(struct ofp13_table_features) == 64);
+
+/* Table Feature property types.
+ * Low order bit cleared indicates a property for a regular Flow Entry.
+ * Low order bit set indicates a property for the Table-Miss Flow Entry. */
+enum ofp13_table_feature_prop_type {
+ OFPTFPT13_INSTRUCTIONS = 0, /* Instructions property. */
+ OFPTFPT13_INSTRUCTIONS_MISS = 1, /* Instructions for table-miss. */
+ OFPTFPT13_NEXT_TABLES = 2, /* Next Table property. */
+ OFPTFPT13_NEXT_TABLES_MISS = 3, /* Next Table for table-miss. */
+ OFPTFPT13_WRITE_ACTIONS = 4, /* Write Actions property. */
+ OFPTFPT13_WRITE_ACTIONS_MISS = 5, /* Write Actions for table-miss. */
+ OFPTFPT13_APPLY_ACTIONS = 6, /* Apply Actions property. */
+ OFPTFPT13_APPLY_ACTIONS_MISS = 7, /* Apply Actions for table-miss. */
+ OFPTFPT13_MATCH = 8, /* Match property. */
+ OFPTFPT13_WILDCARDS = 10, /* Wildcards property. */
+ OFPTFPT13_WRITE_SETFIELD = 12, /* Write Set-Field property. */
+ OFPTFPT13_WRITE_SETFIELD_MISS = 13, /* Write Set-Field for table-miss. */
+ OFPTFPT13_APPLY_SETFIELD = 14, /* Apply Set-Field property. */
+ OFPTFPT13_APPLY_SETFIELD_MISS = 15, /* Apply Set-Field for table-miss. */
+ OFPTFPT13_EXPERIMENTER = 0xFFFE, /* Experimenter property. */
+ OFPTFPT13_EXPERIMENTER_MISS = 0xFFFF, /* Experimenter for table-miss. */
+};
+
+/* Instructions property */
+struct ofp13_table_feature_prop_instructions {
+ ovs_be16 type; /* One of OFPTFPT13_INSTRUCTIONS,
+ OFPTFPT13_INSTRUCTIONS_MISS. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ /* Followed by:
+ * - Exactly (length - 4) bytes containing the instruction ids, then
+ * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+ * bytes of all-zero bytes */
+ struct ofp11_instruction instruction_ids[0]; /* List of instructions
+ without any data */
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_instructions) == 4);
+
+/* Next Tables property */
+struct ofp13_table_feature_prop_next_tables {
+ ovs_be16 type; /* One of OFPTFPT13_NEXT_TABLES,
+ OFPTFPT13_NEXT_TABLES_MISS. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ /* Followed by:
+ * - Exactly (length - 4) bytes containing the table_ids, then
+ * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+ * bytes of all-zero bytes */
+ uint8_t next_table_ids[0];
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_next_tables) == 4);
+
+/* Actions property */
+struct ofp13_table_feature_prop_actions {
+ ovs_be16 type; /* One of OFPTFPT13_WRITE_ACTIONS,
+ OFPTFPT13_WRITE_ACTIONS_MISS,
+ OFPTFPT13_APPLY_ACTIONS,
+ OFPTFPT13_APPLY_ACTIONS_MISS. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ /* Followed by:
+ * - Exactly (length - 4) bytes containing the action_ids, then
+ * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+ * bytes of all-zero bytes */
+ struct ofp_action_header action_ids[0]; /* List of actions
+ without any data */
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_actions) == 4);
+
+
+/* Match, Wildcard or Set-Field property */
+struct ofp13_table_feature_prop_oxm {
+ ovs_be16 type; /* One of OFPTFPT13_MATCH, OFPTFPT13_WILDCARDS,
+ OFPTFPT13_WRITE_SETFIELD,
+ OFPTFPT13_WRITE_SETFIELD_MISS,
+ OFPTFPT13_APPLY_SETFIELD,
+ OFPTFPT13_APPLY_SETFIELD_MISS. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ /* Followed by:
+ * - Exactly (length - 4) bytes containing the oxm_ids, then
+ * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+ * bytes of all-zero bytes */
+ ovs_be32 oxm_ids[0]; /* Array of OXM headers */
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_oxm) == 4);
+
+/* Experimenter table feature property */
+struct ofp13_table_feature_prop_experimenter {
+ ovs_be16 type; /* One of OFPTFPT13_EXPERIMENTER,
+ OFPTFPT13_EXPERIMENTER_MISS. */
+ ovs_be16 length; /* Length in bytes of this property. */
+ ovs_be32 experimenter; /* Experimenter ID which takes the same form
+ as in struct ofp_experimenter_header. */
+ ovs_be32 exp_type; /* Experimenter defined. */
+ /* Followed by:
+ * - Exactly (length - 12) bytes containing the experimenter data, then
+ * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+ * bytes of all-zero bytes */
+ ovs_be32 experimenter_data[0];
+};
+OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_experimenter) == 12);
+
+/* Body of reply to OFPMP13_PORT request. If a counter is unsupported, set
+ * the field to all ones. */
+struct ofp13_port_stats {
+ struct ofp11_port_stats ps;
+ ovs_be32 duration_sec; /* Time port has been alive in seconds. */
+ ovs_be32 duration_nsec; /* Time port has been alive in nanoseconds
+ beyond duration_sec. */
+};
+OFP_ASSERT(sizeof(struct ofp13_port_stats) == 112);
+
+/* Body of reply to OFPMP13_QUEUE request */
+struct ofp13_queue_stats {
+ struct ofp11_queue_stats qs;
+ ovs_be32 duration_sec; /* Time queue has been alive in seconds. */
+ ovs_be32 duration_nsec; /* Time queue has been alive in nanoseconds
+ beyond duration_sec. */
+};
+OFP_ASSERT(sizeof(struct ofp13_queue_stats) == 40);
+
+/* Body of reply to OFPMP13_GROUP request */
+struct ofp13_group_stats {
+ struct ofp11_group_stats gs;
+ ovs_be32 duration_sec; /* NEW: Time group has been alive in seconds. */
+ ovs_be32 duration_nsec; /* NEW: Time group has been alive in nanoseconds
+ beyond duration_sec. */
+ /* struct ofp11_bucket_counter bucket_stats[0]; */
+};
+OFP_ASSERT(sizeof(struct ofp13_group_stats) == 40);
+
+/* Body of OFPMP13_METER and OFPMP13_METER_CONFIG requests. */
+struct ofp13_meter_multipart_request {
+ ovs_be32 meter_id; /* Meter instance, or OFPM_ALL. */
+ uint8_t pad[4]; /* Align to 64 bits. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_multipart_request) == 8);
+
+/* Statistics for each meter band */
+struct ofp13_meter_band_stats {
+ ovs_be64 packet_band_count; /* Number of packets in band. */
+ ovs_be64 byte_band_count; /* Number of bytes in band. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_band_stats) == 16);
+
+/* Body of reply to OFPMP13_METER request. Meter statistics. */
+struct ofp13_meter_stats {
+ ovs_be32 meter_id; /* Meter instance. */
+ ovs_be16 len; /* Length in bytes of this stats. */
+ uint8_t pad[6];
+ ovs_be32 flow_count; /* Number of flows bound to meter. */
+ ovs_be64 packet_in_count; /* Number of packets in input. */
+ ovs_be64 byte_in_count; /* Number of bytes in input. */
+ ovs_be32 duration_sec; /* Time meter has been alive in seconds. */
+ ovs_be32 duration_nsec; /* Time meter has been alive in nanoseconds
+ beyond duration_sec. */
+ struct ofp13_meter_band_stats band_stats[0]; /* The band_stats length is
+ inferred from the length field. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_stats) == 40);
+
+/* Body of reply to OFPMP13_METER_CONFIG request. Meter configuration. */
+struct ofp13_meter_config {
+ ovs_be16 length; /* Length of this entry. */
+ ovs_be16 flags; /* Set of OFPMC_* that apply. */
+ ovs_be32 meter_id; /* Meter instance. */
+ struct ofp13_meter_band_header bands[0]; /* The bands length is inferred
+ from the length field. */
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_config) == 8);
+
+/* Body of reply to OFPMP13_METER_FEATURES request. Meter features. */
+struct ofp13_meter_features {
+ ovs_be32 max_meter; /* Maximum number of meters. */
+ ovs_be32 band_types; /* Bitmaps of OFPMBT13_* values supported. */
+ ovs_be32 capabilities; /* Bitmaps of "ofp13_meter_flags". */
+ uint8_t max_bands; /* Maximum bands per meters */
+ uint8_t max_color; /* Maximum color value */
+ uint8_t pad[2];
+};
+OFP_ASSERT(sizeof(struct ofp13_meter_features) == 16);
+
+/* Asynchronous message configuration. */
+/* The body of this is the same as nx_async_config */
+/* OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC. */
+struct ofp13_async_config {
+ ovs_be32 packet_in_mask[2]; /* Bitmasks of OFPR_* values. */
+ ovs_be32 port_status_mask[2]; /* Bitmasks of OFPPR_* values. */
+ ovs_be32 flow_removed_mask[2];/* Bitmasks of OFPRR_* values. */
+};
+OFP_ASSERT(sizeof(struct ofp13_async_config) == 24);
+
+
+/* Packet received on port (datapath -> controller). */
+struct ofp13_packet_in {
+ struct ofp12_packet_in pi;
+ ovs_be64 cookie; /* Cookie of the flow entry that was looked up */
+ /* Followed by:
+ * - Match
+ * - 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.
+ */
+ /* struct ofp12_match match; */
+ /* uint8_t pad[2]; Align to 64 bit + 16 bit */
+ /* uint8_t data[0]; Ethernet frame */
+};
+OFP_ASSERT(sizeof(struct ofp13_packet_in) == 16);
+
+
+#endif /* openflow/openflow-1.3.h */
OFP10_VERSION = 0x01,
OFP11_VERSION = 0x02,
OFP12_VERSION = 0x03,
+ OFP13_VERSION = 0x04
};
#define OFP_MAX_TABLE_NAME_LEN 32
ovs_be32 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. */
+ uint8_t auxiliary_id; /* OF 1.3: Identify auxiliary connections */
+ uint8_t pad[2]; /* Align to 64-bits. */
/* Features. */
ovs_be32 capabilities; /* OFPC_*, OFPC10_*, OFPC11_*, OFPC12_*. */
- ovs_be32 actions; /* Bitmap of supported "ofp_action_type"s. */
+ ovs_be32 actions; /* Bitmap of supported "ofp_action_type"s.
+ * DEPRECATED in OpenFlow 1.1 */
/* Followed by an array of struct ofp10_phy_port or struct ofp11_port
- * structures. The number is inferred from header.length. */
+ * structures. The number is inferred from header.length.
+ * REMOVED in OpenFlow 1.3 */
};
OFP_ASSERT(sizeof(struct ofp_switch_features) == 24);
#include "openflow/openflow-1.0.h"
#include "openflow/openflow-1.1.h"
#include "openflow/openflow-1.2.h"
+#include "openflow/openflow-1.3.h"
#endif /* openflow/openflow.h */
case OFPTYPE_FLOW_MOD_TABLE_ID:
case OFPTYPE_SET_PACKET_IN_FORMAT:
case OFPTYPE_FLOW_AGE:
- case OFPTYPE_SET_ASYNC_CONFIG:
case OFPTYPE_SET_CONTROLLER_ID:
case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
case OFPTYPE_FLOW_MONITOR_CANCEL:
case OFPTYPE_FLOW_MONITOR_PAUSED:
case OFPTYPE_FLOW_MONITOR_RESUMED:
+ case OFPTYPE_GET_ASYNC_REQUEST:
+ case OFPTYPE_GET_ASYNC_REPLY:
+ case OFPTYPE_SET_ASYNC_CONFIG:
+ case OFPTYPE_METER_MOD:
+ case OFPTYPE_GROUP_REQUEST:
+ case OFPTYPE_GROUP_REPLY:
+ case OFPTYPE_GROUP_DESC_REQUEST:
+ case OFPTYPE_GROUP_DESC_REPLY:
+ case OFPTYPE_GROUP_FEATURES_REQUEST:
+ case OFPTYPE_GROUP_FEATURES_REPLY:
+ case OFPTYPE_METER_REQUEST:
+ case OFPTYPE_METER_REPLY:
+ case OFPTYPE_METER_CONFIG_REQUEST:
+ case OFPTYPE_METER_CONFIG_REPLY:
+ case OFPTYPE_METER_FEATURES_REQUEST:
+ case OFPTYPE_METER_FEATURES_REPLY:
+ case OFPTYPE_TABLE_FEATURES_REQUEST:
+ case OFPTYPE_TABLE_FEATURES_REPLY:
default:
if (VLOG_IS_DBG_ENABLED()) {
char *s = ofp_to_string(msg->data, msg->size, 2);
struct ofp_header *oh = (struct ofp_header *)openflow->l2;
switch(oh->version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
set_field_to_ofast(load, openflow);
break;
return &ofperr_of11;
case OFP12_VERSION:
return &ofperr_of12;
+ case OFP13_VERSION:
+ return &ofperr_of13;
default:
return NULL;
}
case OFP10_VERSION:
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
break;
default:
/* OF1.2+(1,12). Invalid packet in packet-out. */
OFPERR_OFPBRC_BAD_PACKET,
+ /* OF1.3+(1,13). Multipart request overflowed the assigned buffer. */
+ OFPERR_OFPBRC_MULTIPART_BUFFER_OVERFLOW,
+
/* NX1.0+(1,256). Invalid NXM flow match. */
OFPERR_NXBRC_NXM_INVALID,
/* NX1.0(1,513), NX1.1(1,513), OF1.2+(11,2). Invalid role. */
OFPERR_OFPRRFC_BAD_ROLE,
+/* ## ---------------------- ## */
+/* ## OFPET_METER_MOD_FAILED ## */
+/* ## ---------------------- ## */
+
+ /* OF1.3+(12). Error in meter. */
+ OFPERR_OFPET_METER_MOD_FAILED,
+
+ /* OF1.3+(12,0). Unspecified error. */
+ OFPERR_OFPMMFC_UNKNOWN,
+
+ /* OF1.3+(12,1). Meter not added because a Meter ADD attempted to
+ * replace an existing Meter. */
+ OFPERR_OFPMMFC_METER_EXISTS,
+
+ /* OF1.3+(12,2). Meter not added because Meter specified is invalid. */
+ OFPERR_OFPMMFC_INVALID_METER,
+
+ /* OF1.3+(12,3). Meter not modified because a Meter MODIFY attempted
+ * to modify a non-existent Meter. */
+ OFPERR_OFPMMFC_UNKNOWN_METER,
+
+ /* OF1.3+(12,4). Unsupported or unknown command. */
+ OFPERR_OFPMMFC_BAD_COMMAND,
+
+ /* OF1.3+(12,5). Flag configuration unsupported. */
+ OFPERR_OFPMMFC_BAD_FLAGS,
+
+ /* OF1.3+(12,6). Rate unsupported. */
+ OFPERR_OFPMMFC_BAD_RATE,
+
+ /* OF1.3+(12,7). Burst size unsupported. */
+ OFPERR_OFPMMFC_BAD_BURST,
+
+ /* OF1.3+(12,8). Band unsupported. */
+ OFPERR_OFPMMFC_BAD_BAND,
+
+ /* OF1.3+(12,9). Band value unsupported. */
+ OFPERR_OFPMMFC_BAD_BAND_VALUE,
+
+ /* OF1.3+(12,10). No more meters available. */
+ OFPERR_OFPMMFC_OUT_OF_METERS,
+
+ /* OF1.3+(12,11). The maximum number of properties for a meter has
+ * been exceeded. */
+ OFPERR_OFPMMFC_OUT_OF_BANDS,
+
+/* ## --------------------------- ## */
+/* ## OFPET_TABLE_FEATURES_FAILED ## */
+/* ## --------------------------- ## */
+
+ /* OF1.3+(13). Setting table features failed. */
+ OFPERR_OFPET_TABLE_FEATURES_FAILED,
+
+ /* OF1.3+(13,0). Specified table does not exist. */
+ OFPERR_OFPTFFC_BAD_TABLE,
+
+ /* OF1.3+(13,1). Invalid metadata mask. */
+ OFPERR_OFPTFFC_BAD_METADATA,
+
+ /* OF1.3+(13,2). Unknown property type. */
+ OFPERR_OFPTFFC_BAD_TYPE,
+
+ /* OF1.3+(13,3). Length problem in properties. */
+ OFPERR_OFPTFFC_BAD_LEN,
+
+ /* OF1.3+(13,4). Unsupported property value. */
+ OFPERR_OFPTFFC_BAD_ARGUMENT,
+
+ /* OF1.3+(13,5). Permissions error. */
+ OFPERR_OFPTFFC_EPERM,
+
/* ## ------------------ ## */
/* ## OFPET_EXPERIMENTER ## */
/* ## ------------------ ## */
hdrs->type == OFPT10_STATS_REPLY);
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
return (hdrs->type == OFPT11_STATS_REQUEST ||
hdrs->type == OFPT11_STATS_REPLY);
}
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
if (hdrs->type == OFPT11_STATS_REQUEST ||
hdrs->type == OFPT11_STATS_REPLY) {
return (hdrs->stat == OFPST_VENDOR
break;
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
assert(hdrs.type == OFPT11_STATS_REQUEST);
hdrs.type = OFPT11_STATS_REPLY;
break;
return &((struct ofp10_stats_msg *) oh)->flags;
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
return &((struct ofp11_stats_msg *) oh)->flags;
default:
NOT_REACHED();
/* OFPT 1.0 (6): struct ofp_switch_features, struct ofp10_phy_port[]. */
OFPRAW_OFPT10_FEATURES_REPLY,
- /* OFPT 1.1+ (6): struct ofp_switch_features, struct ofp11_port[]. */
+ /* OFPT 1.1-1.2 (6): struct ofp_switch_features, struct ofp11_port[]. */
OFPRAW_OFPT11_FEATURES_REPLY,
+ /* OFPT 1.3+ (6): struct ofp_switch_features. */
+ OFPRAW_OFPT13_FEATURES_REPLY,
/* OFPT 1.0+ (7): void. */
OFPRAW_OFPT_GET_CONFIG_REQUEST,
OFPRAW_OFPT11_PACKET_IN,
/* OFPT 1.2 (10): struct ofp12_packet_in, uint8_t[]. */
OFPRAW_OFPT12_PACKET_IN,
+ /* OFPT 1.3 (10): struct ofp13_packet_in, uint8_t[]. */
+ OFPRAW_OFPT13_PACKET_IN,
/* NXT 1.0+ (17): struct nx_packet_in, uint8_t[]. */
OFPRAW_NXT_PACKET_IN,
/* OFPT 1.1+ (21): void. */
OFPRAW_OFPT11_BARRIER_REPLY,
+ /* OFPT 1.3+ (26): void. */
+ OFPRAW_OFPT13_GET_ASYNC_REQUEST,
+ /* OFPT 1.3+ (27): struct ofp13_async_config. */
+ OFPRAW_OFPT13_GET_ASYNC_REPLY,
+ /* OFPT 1.3+ (28): struct ofp13_async_config. */
+ OFPRAW_OFPT13_SET_ASYNC,
+ /* NXT 1.0+ (19): struct nx_async_config. */
+ OFPRAW_NXT_SET_ASYNC_CONFIG,
+
+ /* OFPT 1.3+ (29): struct ofp13_meter_mod. */
+ OFPRAW_OFPT13_METER_MOD,
+
/* Standard statistics. */
/* OFPST 1.0+ (0): void. */
/* OFPST 1.0 (1): uint8_t[]. */
OFPRAW_OFPST10_FLOW_REPLY,
- /* OFPST 1.1+ (1): uint8_t[]. */
+ /* OFPST 1.1-1.2 (1): uint8_t[]. */
OFPRAW_OFPST11_FLOW_REPLY,
+ /* OFPST 1.3+ (1): uint8_t[]. */
+ OFPRAW_OFPST13_FLOW_REPLY,
/* NXST 1.0 (0): uint8_t[]. */
OFPRAW_NXST_FLOW_REPLY,
/* NXST 1.0 (1): struct ofp_aggregate_stats_reply. */
OFPRAW_NXST_AGGREGATE_REPLY,
- /* OFPST 1.0-1.2 (3): void. */
+ /* OFPST 1.0+ (3): void. */
OFPRAW_OFPST_TABLE_REQUEST,
/* OFPST 1.0 (3): struct ofp10_table_stats[]. */
OFPRAW_OFPST11_TABLE_REPLY,
/* OFPST 1.2 (3): struct ofp12_table_stats[]. */
OFPRAW_OFPST12_TABLE_REPLY,
+ /* OFPST 1.3 (3): struct ofp13_table_stats[]. */
+ OFPRAW_OFPST13_TABLE_REPLY,
/* OFPST 1.0 (4): struct ofp10_port_stats_request. */
OFPRAW_OFPST10_PORT_REQUEST,
/* OFPST 1.0 (4): struct ofp10_port_stats[]. */
OFPRAW_OFPST10_PORT_REPLY,
- /* OFPST 1.1+ (4): struct ofp11_port_stats[]. */
+ /* OFPST 1.1-1.2 (4): struct ofp11_port_stats[]. */
OFPRAW_OFPST11_PORT_REPLY,
+ /* OFPST 1.3+ (4): struct ofp13_port_stats[]. */
+ OFPRAW_OFPST13_PORT_REPLY,
/* OFPST 1.0 (5): struct ofp10_queue_stats_request. */
OFPRAW_OFPST10_QUEUE_REQUEST,
/* OFPST 1.0 (5): struct ofp10_queue_stats[]. */
OFPRAW_OFPST10_QUEUE_REPLY,
- /* OFPST 1.1+ (5): struct ofp11_queue_stats[]. */
+ /* OFPST 1.1-1.2 (5): struct ofp11_queue_stats[]. */
OFPRAW_OFPST11_QUEUE_REPLY,
+ /* OFPST 1.3+ (5): struct ofp13_queue_stats[]. */
+ OFPRAW_OFPST13_QUEUE_REPLY,
+
+ /* OFPST 1.1+ (6): struct ofp11_group_stats_request. */
+ OFPRAW_OFPST11_GROUP_REQUEST,
+
+ /* OFPST 1.1-1.2 (6): struct ofp11_group_stats[]. */
+ OFPRAW_OFPST11_GROUP_REPLY,
+ /* OFPST 1.3 (6): struct ofp13_group_stats[]. */
+ OFPRAW_OFPST13_GROUP_REPLY,
+
+ /* OFPST 1.1+ (7): void. */
+ OFPRAW_OFPST11_GROUP_DESC_REQUEST,
+
+ /* OFPST 1.1+ (7): struct ofp11_group_desc_stats[]. */
+ OFPRAW_OFPST11_GROUP_DESC_REPLY,
+
+ /* OFPST 1.2+ (8): void. */
+ OFPRAW_OFPST12_GROUP_FEATURES_REQUEST,
+
+ /* OFPST 1.2+ (8): struct ofp12_group_features_stats. */
+ OFPRAW_OFPST12_GROUP_FEATURES_REPLY,
+
+ /* OFPST 1.3+ (9): struct ofp13_meter_multipart_request. */
+ OFPRAW_OFPST13_METER_REQUEST,
+
+ /* OFPST 1.3+ (9): struct ofp13_meter_stats[]. */
+ OFPRAW_OFPST13_METER_REPLY,
+
+ /* OFPST 1.3+ (10): struct ofp13_meter_multipart_request. */
+ OFPRAW_OFPST13_METER_CONFIG_REQUEST,
+
+ /* OFPST 1.3+ (10): struct ofp13_meter_config[]. */
+ OFPRAW_OFPST13_METER_CONFIG_REPLY,
+
+ /* OFPST 1.3+ (11): void. */
+ OFPRAW_OFPST13_METER_FEATURES_REQUEST,
+
+ /* OFPST 1.3+ (11): struct ofp13_meter_features. */
+ OFPRAW_OFPST13_METER_FEATURES_REPLY,
+
+ /* OFPST 1.3+ (12): struct ofp13_table_features[]. */
+ OFPRAW_OFPST13_TABLE_FEATURES_REQUEST,
+
+ /* OFPST 1.3+ (12): struct ofp13_table_features[]. */
+ OFPRAW_OFPST13_TABLE_FEATURES_REPLY,
/* OFPST 1.0+ (13): void. */
OFPRAW_OFPST_PORT_DESC_REQUEST,
/* NXT 1.0+ (18): void. */
OFPRAW_NXT_FLOW_AGE,
- /* NXT 1.0+ (19): struct nx_async_config. */
- OFPRAW_NXT_SET_ASYNC_CONFIG,
-
/* NXT 1.0+ (20): struct nx_controller_id. */
OFPRAW_NXT_SET_CONTROLLER_ID,
/* Switch configuration messages. */
OFPTYPE_FEATURES_REQUEST, /* OFPRAW_OFPT_FEATURES_REQUEST. */
OFPTYPE_FEATURES_REPLY, /* OFPRAW_OFPT10_FEATURES_REPLY.
- * OFPRAW_OFPT11_FEATURES_REPLY. */
+ * OFPRAW_OFPT11_FEATURES_REPLY.
+ * OFPRAW_OFPT13_FEATURES_REPLY. */
OFPTYPE_GET_CONFIG_REQUEST, /* OFPRAW_OFPT_GET_CONFIG_REQUEST. */
OFPTYPE_GET_CONFIG_REPLY, /* OFPRAW_OFPT_GET_CONFIG_REPLY. */
OFPTYPE_SET_CONFIG, /* OFPRAW_OFPT_SET_CONFIG. */
OFPTYPE_PACKET_IN, /* OFPRAW_OFPT10_PACKET_IN.
* OFPRAW_OFPT11_PACKET_IN.
* OFPRAW_OFPT12_PACKET_IN.
+ * OFPRAW_OFPT13_PACKET_IN.
* OFPRAW_NXT_PACKET_IN. */
OFPTYPE_FLOW_REMOVED, /* OFPRAW_OFPT10_FLOW_REMOVED.
* OFPRAW_OFPT11_FLOW_REMOVED.
OFPTYPE_BARRIER_REPLY, /* OFPRAW_OFPT10_BARRIER_REPLY.
* OFPRAW_OFPT11_BARRIER_REPLY. */
+ /* Asynchronous message configuration. */
+ OFPTYPE_GET_ASYNC_REQUEST, /* OFPRAW_OFPT13_GET_ASYNC_REQUEST. */
+ OFPTYPE_GET_ASYNC_REPLY, /* OFPRAW_OFPT13_GET_ASYNC_REPLY. */
+ OFPTYPE_SET_ASYNC_CONFIG, /* OFPRAW_NXT_SET_ASYNC_CONFIG.
+ * OFPRAW_OFPT13_SET_ASYNC. */
+
+ /* Meters and rate limiters configuration messages. */
+ OFPTYPE_METER_MOD, /* OFPRAW_OFPT13_METER_MOD. */
+
/* Statistics. */
OFPTYPE_DESC_STATS_REQUEST, /* OFPRAW_OFPST_DESC_REQUEST. */
OFPTYPE_DESC_STATS_REPLY, /* OFPRAW_OFPST_DESC_REPLY. */
* OFPRAW_NXST_FLOW_REQUEST. */
OFPTYPE_FLOW_STATS_REPLY, /* OFPRAW_OFPST10_FLOW_REPLY.
* OFPRAW_OFPST11_FLOW_REPLY.
+ * OFPRAW_OFPST13_FLOW_REPLY.
* OFPRAW_NXST_FLOW_REPLY. */
OFPTYPE_AGGREGATE_STATS_REQUEST, /* OFPRAW_OFPST10_AGGREGATE_REQUEST.
* OFPRAW_OFPST11_AGGREGATE_REQUEST.
OFPTYPE_TABLE_STATS_REQUEST, /* OFPRAW_OFPST_TABLE_REQUEST. */
OFPTYPE_TABLE_STATS_REPLY, /* OFPRAW_OFPST10_TABLE_REPLY.
* OFPRAW_OFPST11_TABLE_REPLY.
- * OFPRAW_OFPST12_TABLE_REPLY. */
+ * OFPRAW_OFPST12_TABLE_REPLY.
+ * OFPRAW_OFPST13_TABLE_REPLY. */
OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_REQUEST.
* OFPRAW_OFPST11_PORT_REQUEST. */
OFPTYPE_PORT_STATS_REPLY, /* OFPRAW_OFPST10_PORT_REPLY.
- * OFPRAW_OFPST11_PORT_REPLY. */
+ * OFPRAW_OFPST11_PORT_REPLY.
+ * OFPRAW_OFPST13_PORT_REPLY. */
OFPTYPE_QUEUE_STATS_REQUEST, /* OFPRAW_OFPST10_QUEUE_REQUEST.
* OFPRAW_OFPST11_QUEUE_REQUEST. */
OFPTYPE_QUEUE_STATS_REPLY, /* OFPRAW_OFPST10_QUEUE_REPLY.
- * OFPRAW_OFPST11_QUEUE_REPLY. */
+ * OFPRAW_OFPST11_QUEUE_REPLY.
+ * OFPRAW_OFPST13_QUEUE_REPLY. */
+
+ OFPTYPE_GROUP_REQUEST, /* OFPRAW_OFPST11_GROUP_REQUEST. */
+
+ OFPTYPE_GROUP_REPLY, /* OFPRAW_OFPST11_GROUP_REPLY.
+ * OFPRAW_OFPST13_GROUP_REPLY. */
+
+ OFPTYPE_GROUP_DESC_REQUEST, /* OFPRAW_OFPST11_GROUP_DESC_REQUEST. */
+
+ OFPTYPE_GROUP_DESC_REPLY, /* OFPRAW_OFPST11_GROUP_DESC_REPLY. */
+
+ OFPTYPE_GROUP_FEATURES_REQUEST, /* OFPRAW_OFPST12_GROUP_FEATURES_REQUEST. */
+
+ OFPTYPE_GROUP_FEATURES_REPLY, /* OFPRAW_OFPST12_GROUP_FEATURES_REPLY. */
+
+ OFPTYPE_METER_REQUEST, /* OFPRAW_OFPST13_METER_REQUEST. */
+
+ OFPTYPE_METER_REPLY, /* OFPRAW_OFPST13_METER_REPLY. */
+
+ OFPTYPE_METER_CONFIG_REQUEST, /* OFPRAW_OFPST13_METER_CONFIG_REQUEST. */
+
+ OFPTYPE_METER_CONFIG_REPLY, /* OFPRAW_OFPST13_METER_CONFIG_REPLY. */
+
+ OFPTYPE_METER_FEATURES_REQUEST, /* OFPRAW_OFPST13_METER_FEATURES_REQUEST. */
+
+ OFPTYPE_METER_FEATURES_REPLY, /* OFPRAW_OFPST13_METER_FEATURES_REPLY. */
+
+ OFPTYPE_TABLE_FEATURES_REQUEST, /* OFPRAW_OFPST13_TABLE_FEATURES_REQUEST. */
+
+ OFPTYPE_TABLE_FEATURES_REPLY, /* OFPRAW_OFPST13_TABLE_FEATURES_REPLY. */
+
OFPTYPE_PORT_DESC_STATS_REQUEST, /* OFPRAW_OFPST_PORT_DESC_REQUEST. */
OFPTYPE_PORT_DESC_STATS_REPLY, /* OFPRAW_OFPST10_PORT_DESC_REPLY.
OFPTYPE_FLOW_MOD_TABLE_ID, /* OFPRAW_NXT_FLOW_MOD_TABLE_ID. */
OFPTYPE_SET_PACKET_IN_FORMAT, /* OFPRAW_NXT_SET_PACKET_IN_FORMAT. */
OFPTYPE_FLOW_AGE, /* OFPRAW_NXT_FLOW_AGE. */
- OFPTYPE_SET_ASYNC_CONFIG, /* OFPRAW_NXT_SET_ASYNC_CONFIG. */
OFPTYPE_SET_CONTROLLER_ID, /* OFPRAW_NXT_SET_CONTROLLER_ID. */
/* Flow monitor extension. */
fm->flags |= OFPFF_SEND_FLOW_REM;
} else if (fields & F_FLAGS && !strcmp(name, "check_overlap")) {
fm->flags |= OFPFF_CHECK_OVERLAP;
+ } else if (fields & F_FLAGS && !strcmp(name, "reset_counts")) {
+ fm->flags |= OFPFF12_RESET_COUNTS;
+ } else if (fields & F_FLAGS && !strcmp(name, "no_packet_counts")) {
+ fm->flags |= OFPFF13_NO_PKT_COUNTS;
+ } else if (fields & F_FLAGS && !strcmp(name, "no_byte_counts")) {
+ fm->flags |= OFPFF13_NO_BYT_COUNTS;
} else {
char *value;
}
ds_put_format(string, " dpid:%016"PRIx64"\n", features.datapath_id);
- ds_put_format(string, "n_tables:%"PRIu8", n_buffers:%"PRIu32"\n",
+
+ ds_put_format(string, "n_tables:%"PRIu8", n_buffers:%"PRIu32,
features.n_tables, features.n_buffers);
+ if (features.auxiliary_id) {
+ ds_put_format(string, ", auxiliary_id:%"PRIu8, features.auxiliary_id);
+ }
+ ds_put_char(string, '\n');
ds_put_cstr(string, "capabilities: ");
ofp_print_bit_names(string, features.capabilities,
case OFP11_VERSION:
case OFP12_VERSION:
break;
+ case OFP13_VERSION:
+ return; /* no ports in ofp13_switch_features */
default:
NOT_REACHED();
}
return ds_cstr(&f);
}
+static void
+ofp_print_flow_flags(struct ds *s, uint16_t flags)
+{
+ if (flags & OFPFF_SEND_FLOW_REM) {
+ ds_put_cstr(s, "send_flow_rem ");
+ }
+ if (flags & OFPFF_CHECK_OVERLAP) {
+ ds_put_cstr(s, "check_overlap ");
+ }
+ if (flags & OFPFF12_RESET_COUNTS) {
+ ds_put_cstr(s, "reset_counts ");
+ }
+ if (flags & OFPFF13_NO_PKT_COUNTS) {
+ ds_put_cstr(s, "no_packet_counts ");
+ }
+ if (flags & OFPFF13_NO_BYT_COUNTS) {
+ ds_put_cstr(s, "no_byte_counts ");
+ }
+
+ flags &= ~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP
+ | OFPFF12_RESET_COUNTS
+ | OFPFF13_NO_PKT_COUNTS | OFPFF13_NO_BYT_COUNTS);
+ if (flags) {
+ ds_put_format(s, "flags:0x%"PRIx16" ", flags);
+ }
+}
+
static void
ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh, int verbosity)
{
ds_put_char(s, ' ');
}
if (fm.flags != 0) {
- uint16_t flags = fm.flags;
-
- if (flags & OFPFF_SEND_FLOW_REM) {
- ds_put_cstr(s, "send_flow_rem ");
- }
- if (flags & OFPFF_CHECK_OVERLAP) {
- ds_put_cstr(s, "check_overlap ");
- }
- if (flags & OFPFF10_EMERG) {
- ds_put_cstr(s, "emerg ");
- }
-
- flags &= ~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF10_EMERG);
- if (flags) {
- ds_put_format(s, "flags:0x%"PRIx16" ", flags);
- }
+ ofp_print_flow_flags(s, fm.flags);
}
ofpacts_format(fm.ofpacts, fm.ofpacts_len, s);
if (fs->hard_timeout != OFP_FLOW_PERMANENT) {
ds_put_format(string, "hard_timeout=%"PRIu16", ", fs->hard_timeout);
}
+ if (fs->flags) {
+ ofp_print_flow_flags(string, fs->flags);
+ }
if (fs->idle_age >= 0) {
ds_put_format(string, "idle_age=%d, ", fs->idle_age);
}
{
char name_[OFP_MAX_TABLE_NAME_LEN + 1];
+ /* ofp13_table_stats is different */
+ if (ofp_version > OFP12_VERSION) {
+ return;
+ }
+
ovs_strlcpy(name_, name, sizeof name_);
ds_put_format(string, " %d: %-8s: ", ts->table_id, name_);
ntohll(ts->metadata_write));
}
+static void
+ofp_print_ofpst_table_reply13(struct ds *string, const struct ofp_header *oh,
+ int verbosity)
+{
+ struct ofp13_table_stats *ts;
+ struct ofpbuf b;
+ size_t n;
+
+ ofpbuf_use_const(&b, oh, ntohs(oh->length));
+ ofpraw_pull_assert(&b);
+
+ n = b.size / sizeof *ts;
+ ds_put_format(string, " %zu tables\n", n);
+ if (verbosity < 1) {
+ return;
+ }
+
+ for (;;) {
+ ts = ofpbuf_try_pull(&b, sizeof *ts);
+ if (!ts) {
+ return;
+ }
+ ds_put_format(string,
+ " %d: active=%"PRIu32", lookup=%"PRIu64 \
+ ", matched=%"PRIu64"\n",
+ ts->table_id, ntohl(ts->active_count),
+ ntohll(ts->lookup_count), ntohll(ts->matched_count));
+ }
+}
+
static void
ofp_print_ofpst_table_reply12(struct ds *string, const struct ofp_header *oh,
int verbosity)
int verbosity)
{
switch ((enum ofp_version)oh->version) {
+ case OFP13_VERSION:
+ ofp_print_ofpst_table_reply13(string, oh, verbosity);
+ break;
+
case OFP12_VERSION:
ofp_print_ofpst_table_reply12(string, oh, verbosity);
break;
case OFP12_VERSION:
ds_put_cstr(string, " (OF1.2)");
break;
+ case OFP13_VERSION:
+ ds_put_cstr(string, " (OF1.3)");
+ break;
default:
ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
break;
ofp_print_version(oh, string);
}
+static void
+ofp_print_not_implemented(struct ds *string)
+{
+ ds_put_cstr(string, "NOT IMPLEMENTED YET!\n");
+}
+
static void
ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
struct ds *string, int verbosity)
ofp_header_to_string__(oh, raw, string);
switch (ofptype_from_ofpraw(raw)) {
+
+ /* FIXME: Change the following once they are implemented: */
+ case OFPTYPE_GET_ASYNC_REQUEST:
+ case OFPTYPE_GET_ASYNC_REPLY:
+ case OFPTYPE_METER_MOD:
+ case OFPTYPE_GROUP_REQUEST:
+ case OFPTYPE_GROUP_REPLY:
+ case OFPTYPE_GROUP_DESC_REQUEST:
+ case OFPTYPE_GROUP_DESC_REPLY:
+ case OFPTYPE_GROUP_FEATURES_REQUEST:
+ case OFPTYPE_GROUP_FEATURES_REPLY:
+ case OFPTYPE_METER_REQUEST:
+ case OFPTYPE_METER_REPLY:
+ case OFPTYPE_METER_CONFIG_REQUEST:
+ case OFPTYPE_METER_CONFIG_REPLY:
+ case OFPTYPE_METER_FEATURES_REQUEST:
+ case OFPTYPE_METER_FEATURES_REPLY:
+ case OFPTYPE_TABLE_FEATURES_REQUEST:
+ case OFPTYPE_TABLE_FEATURES_REPLY:
+ ofp_print_not_implemented(string);
+ break;
+
case OFPTYPE_HELLO:
ofp_print_hello(string, oh);
break;
#define N_PROTO_ABBREVS ARRAY_SIZE(proto_abbrevs)
enum ofputil_protocol ofputil_flow_dump_protocols[] = {
+ OFPUTIL_P_OF13_OXM,
OFPUTIL_P_OF12_OXM,
OFPUTIL_P_OF10_NXM,
OFPUTIL_P_OF10_STD,
return OFPUTIL_P_OF10_STD;
case OFP12_VERSION:
return OFPUTIL_P_OF12_OXM;
+ case OFP13_VERSION:
+ return OFPUTIL_P_OF13_OXM;
case OFP11_VERSION:
default:
return 0;
}
/* Returns the OpenFlow protocol version number (e.g. OFP10_VERSION,
- * OFP11_VERSION or OFP12_VERSION) that corresponds to 'protocol'. */
+ * etc.) that corresponds to 'protocol'. */
enum ofp_version
ofputil_protocol_to_ofp_version(enum ofputil_protocol protocol)
{
return OFP10_VERSION;
case OFPUTIL_P_OF12_OXM:
return OFP12_VERSION;
+ case OFPUTIL_P_OF13_OXM:
+ return OFP13_VERSION;
}
NOT_REACHED();
case OFPUTIL_P_OF12_OXM:
return OFPUTIL_P_OF12_OXM;
+ case OFPUTIL_P_OF13_OXM:
+ return OFPUTIL_P_OF13_OXM;
+
default:
NOT_REACHED();
}
case OFPUTIL_P_OF12_OXM:
return ofputil_protocol_set_tid(OFPUTIL_P_OF12_OXM, tid);
+ case OFPUTIL_P_OF13_OXM:
+ return ofputil_protocol_set_tid(OFPUTIL_P_OF13_OXM, tid);
+
default:
NOT_REACHED();
}
case OFPUTIL_P_OF12_OXM:
return "OXM";
+
+ case OFPUTIL_P_OF13_OXM:
+ return "OpenFlow13";
}
/* Check abbreviations. */
if (!strcasecmp(s, "OpenFlow12")) {
return OFP12_VERSION;
}
+ if (!strcasecmp(s, "OpenFlow13")) {
+ return OFP13_VERSION;
+ }
return 0;
}
return "OpenFlow11";
case OFP12_VERSION:
return "OpenFlow12";
+ case OFP13_VERSION:
+ return "OpenFlow13";
default:
NOT_REACHED();
}
/* NXM, OXM, and OF1.1 support bitwise matching on ethernet addresses. */
if (!eth_mask_is_exact(wc->masks.dl_src)
&& !eth_addr_is_zero(wc->masks.dl_src)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
if (!eth_mask_is_exact(wc->masks.dl_dst)
&& !eth_addr_is_zero(wc->masks.dl_dst)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM, OXM, and OF1.1+ support matching metadata. */
if (wc->masks.metadata != htonll(0)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching ARP hardware addresses. */
if (!eth_addr_is_zero(wc->masks.arp_sha) ||
!eth_addr_is_zero(wc->masks.arp_tha)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching IPv6 traffic. */
if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching registers. */
if (!regs_fully_wildcarded(wc)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching tun_id. */
if (wc->masks.tunnel.tun_id != htonll(0)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching fragments. */
if (wc->masks.nw_frag) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching IPv6 flow label. */
if (wc->masks.ipv6_label) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching IP ECN bits. */
if (wc->masks.nw_tos & IP_ECN_MASK) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support matching IP TTL/hop limit. */
if (wc->masks.nw_ttl) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support non-CIDR IPv4 address masks. */
if (!ip_is_cidr(wc->masks.nw_src) || !ip_is_cidr(wc->masks.nw_dst)) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* NXM and OXM support bitwise matching on transport port. */
if ((wc->masks.tp_src && wc->masks.tp_src != htons(UINT16_MAX)) ||
(wc->masks.tp_dst && wc->masks.tp_dst != htons(UINT16_MAX))) {
- return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ return OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
/* Other formats can express this rule. */
return ofputil_encode_nx_set_flow_format(NXFF_OPENFLOW10);
case OFPUTIL_P_OF12_OXM:
- /* There's only one OpenFlow 1.2 protocol and we already verified
- * above that we're not trying to change versions. */
+ case OFPUTIL_P_OF13_OXM:
+ /* There are only one of each OpenFlow 1.2+ protocols and we already
+ * verified above that we're not trying to change versions. */
NOT_REACHED();
case OFPUTIL_P_OF10_STD_TID:
NOT_REACHED();
}
+ if (fm->flags & OFPFF10_EMERG) {
+ /* We do not support the OpenFlow 1.0 emergency flow cache, which
+ * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
+ * There is no good error code, so just state that the flow table
+ * is full.
+ * Moreover, OFPFF10_EMERG overlaps with OFPFF12_RESET_COUNTS,
+ * so this check must be here */
+ return OFPERR_OFPFMFC_TABLE_FULL;
+ }
+
if (protocol & OFPUTIL_P_TID) {
fm->command = command & 0xff;
fm->table_id = command >> 8;
struct ofpbuf *msg;
switch (protocol) {
- case OFPUTIL_P_OF12_OXM: {
+ case OFPUTIL_P_OF12_OXM:
+ case OFPUTIL_P_OF13_OXM: {
struct ofp11_flow_mod *ofm;
- msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD, OFP12_VERSION,
+ msg = ofpraw_alloc(OFPRAW_OFPT11_FLOW_MOD,
+ ofputil_protocol_to_ofp_version(protocol),
NXM_TYPICAL_LEN + fm->ofpacts_len);
ofm = ofpbuf_put_zeros(msg, sizeof *ofm);
if (fm->command == OFPFC_ADD) {
/* Matching of the cookie is only supported through NXM or OF1.1+. */
if (fm->cookie_mask != htonll(0)) {
- usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
}
enum ofpraw raw;
switch (protocol) {
- case OFPUTIL_P_OF12_OXM: {
+ case OFPUTIL_P_OF12_OXM:
+ case OFPUTIL_P_OF13_OXM: {
struct ofp11_flow_stats_request *ofsr;
raw = (fsr->aggregate
? OFPRAW_OFPST11_AGGREGATE_REQUEST
: OFPRAW_OFPST11_FLOW_REQUEST);
- msg = ofpraw_alloc(raw, OFP12_VERSION, NXM_TYPICAL_LEN);
+ msg = ofpraw_alloc(raw, ofputil_protocol_to_ofp_version(protocol),
+ NXM_TYPICAL_LEN);
ofsr = ofpbuf_put_zeros(msg, sizeof *ofsr);
ofsr->table_id = fsr->table_id;
ofsr->out_port = ofputil_port_to_ofp11(fsr->out_port);
usable_protocols = ofputil_usable_protocols(&fsr->match);
if (fsr->cookie_mask != htonll(0)) {
- usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM;
+ usable_protocols &= OFPUTIL_P_OF10_NXM_ANY | OFPUTIL_P_OF12_OXM
+ | OFPUTIL_P_OF13_OXM;
}
return usable_protocols;
}
if (!msg->size) {
return EOF;
- } else if (raw == OFPRAW_OFPST11_FLOW_REPLY) {
+ } else if (raw == OFPRAW_OFPST11_FLOW_REPLY
+ || raw == OFPRAW_OFPST13_FLOW_REPLY) {
const struct ofp11_flow_stats *ofs;
size_t length;
uint16_t padded_match_len;
fs->duration_nsec = ntohl(ofs->duration_nsec);
fs->idle_timeout = ntohs(ofs->idle_timeout);
fs->hard_timeout = ntohs(ofs->hard_timeout);
+ fs->flags = (raw == OFPRAW_OFPST13_FLOW_REPLY) ? ntohs(ofs->flags) : 0;
fs->idle_age = -1;
fs->hard_age = -1;
fs->cookie = ofs->cookie;
fs->hard_age = -1;
fs->packet_count = ntohll(get_32aligned_be64(&ofs->packet_count));
fs->byte_count = ntohll(get_32aligned_be64(&ofs->byte_count));
+ fs->flags = 0;
} else if (raw == OFPRAW_NXST_FLOW_REPLY) {
const struct nx_flow_stats *nfs;
size_t match_len, actions_len, length;
}
fs->packet_count = ntohll(nfs->packet_count);
fs->byte_count = ntohll(nfs->byte_count);
+ fs->flags = 0;
} else {
NOT_REACHED();
}
enum ofpraw raw;
ofpraw_decode_partial(&raw, reply->data, reply->size);
- if (raw == OFPRAW_OFPST11_FLOW_REPLY) {
+ if (raw == OFPRAW_OFPST11_FLOW_REPLY || raw == OFPRAW_OFPST13_FLOW_REPLY) {
struct ofp11_flow_stats *ofs;
ofpbuf_put_uninit(reply, sizeof *ofs);
ofs->priority = htons(fs->priority);
ofs->idle_timeout = htons(fs->idle_timeout);
ofs->hard_timeout = htons(fs->hard_timeout);
+ ofs->flags = (raw == OFPRAW_OFPST13_FLOW_REPLY) ? htons(fs->flags) : 0;
memset(ofs->pad2, 0, sizeof ofs->pad2);
ofs->cookie = fs->cookie;
ofs->packet_count = htonll(unknown_to_zero(fs->packet_count));
struct ofpbuf *msg;
switch (protocol) {
- case OFPUTIL_P_OF12_OXM: {
+ case OFPUTIL_P_OF12_OXM:
+ case OFPUTIL_P_OF13_OXM: {
struct ofp12_flow_removed *ofr;
msg = ofpraw_alloc_xid(OFPRAW_OFPT11_FLOW_REMOVED,
ofpbuf_use_const(&b, oh, ntohs(oh->length));
raw = ofpraw_pull_assert(&b);
- if (raw == OFPRAW_OFPT12_PACKET_IN) {
- const struct ofp12_packet_in *opi;
+ if (raw == OFPRAW_OFPT13_PACKET_IN || raw == OFPRAW_OFPT12_PACKET_IN) {
+ const struct ofp13_packet_in *opi;
struct match match;
int error;
+ size_t packet_in_size;
+
+ if (raw == OFPRAW_OFPT12_PACKET_IN) {
+ packet_in_size = sizeof (struct ofp12_packet_in);
+ } else {
+ packet_in_size = sizeof (struct ofp13_packet_in);
+ }
- opi = ofpbuf_pull(&b, sizeof *opi);
+ opi = ofpbuf_pull(&b, packet_in_size);
error = oxm_pull_match_loose(&b, &match);
if (error) {
return error;
return OFPERR_OFPBRC_BAD_LEN;
}
- pin->reason = opi->reason;
- pin->table_id = opi->table_id;
+ pin->reason = opi->pi.reason;
+ pin->table_id = opi->pi.table_id;
+ pin->buffer_id = ntohl(opi->pi.buffer_id);
+ pin->total_len = ntohs(opi->pi.total_len);
- pin->buffer_id = ntohl(opi->buffer_id);
- pin->total_len = ntohs(opi->total_len);
+ if (raw == OFPRAW_OFPT13_PACKET_IN) {
+ pin->cookie = opi->cookie;
+ }
ofputil_decode_packet_in_finish(pin, &match, &b);
} else if (raw == OFPRAW_OFPT10_PACKET_IN) {
struct ofpbuf *packet;
/* Add OFPT_PACKET_IN. */
- if (protocol == OFPUTIL_P_OF12_OXM) {
- struct ofp12_packet_in *opi;
+ if (protocol == OFPUTIL_P_OF13_OXM || protocol == OFPUTIL_P_OF12_OXM) {
+ struct ofp13_packet_in *opi;
struct match match;
+ enum ofpraw packet_in_raw;
+ enum ofp_version packet_in_version;
+ size_t packet_in_size;
+
+ if (protocol == OFPUTIL_P_OF12_OXM) {
+ packet_in_raw = OFPRAW_OFPT12_PACKET_IN;
+ packet_in_version = OFP12_VERSION;
+ packet_in_size = sizeof (struct ofp12_packet_in);
+ } else {
+ packet_in_raw = OFPRAW_OFPT13_PACKET_IN;
+ packet_in_version = OFP13_VERSION;
+ packet_in_size = sizeof (struct ofp13_packet_in);
+ }
ofputil_packet_in_to_match(pin, &match);
/* The final argument is just an estimate of the space required. */
- packet = ofpraw_alloc_xid(OFPRAW_OFPT12_PACKET_IN, OFP12_VERSION,
+ packet = ofpraw_alloc_xid(packet_in_raw, packet_in_version,
htonl(0), (sizeof(struct flow_metadata) * 2
+ 2 + send_len));
- ofpbuf_put_zeros(packet, sizeof *opi);
+ ofpbuf_put_zeros(packet, packet_in_size);
oxm_put_match(packet, &match);
ofpbuf_put_zeros(packet, 2);
ofpbuf_put(packet, pin->packet, send_len);
opi = packet->l3;
- opi->buffer_id = htonl(pin->buffer_id);
- opi->total_len = htons(pin->total_len);
- opi->reason = pin->reason;
- opi->table_id = pin->table_id;
- } else if (packet_in_format == NXPIF_OPENFLOW10) {
+ opi->pi.buffer_id = htonl(pin->buffer_id);
+ opi->pi.total_len = htons(pin->total_len);
+ opi->pi.reason = pin->reason;
+ opi->pi.table_id = pin->table_id;
+ if (protocol == OFPUTIL_P_OF13_OXM) {
+ opi->cookie = pin->cookie;
+ }
+ } else if (packet_in_format == NXPIF_OPENFLOW10) {
struct ofp_packet_in *opi;
packet = ofpraw_alloc_xid(OFPRAW_OFPT10_PACKET_IN, OFP10_VERSION,
return sizeof(struct ofp10_phy_port);
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
return sizeof(struct ofp11_port);
default:
NOT_REACHED();
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_port *op;
if (b->size + sizeof *op <= UINT16_MAX) {
op = ofpbuf_put_uninit(b, sizeof *op);
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_port *op;
op = ofpmp_append(replies, sizeof *op);
case OFP11_VERSION:
return OFPC_COMMON | OFPC_ARP_MATCH_IP;
case OFP12_VERSION:
+ case OFP13_VERSION:
return OFPC_COMMON | OFPC12_PORT_BLOCKED;
default:
/* Caller needs to check osf->header.version itself */
features->datapath_id = ntohll(osf->datapath_id);
features->n_buffers = ntohl(osf->n_buffers);
features->n_tables = osf->n_tables;
+ features->auxiliary_id = 0;
features->capabilities = ntohl(osf->capabilities) &
ofputil_capabilities_mask(oh->version);
features->capabilities |= OFPUTIL_C_STP;
}
features->actions = decode_action_bits(osf->actions, of10_action_bits);
- } else if (raw == OFPRAW_OFPT11_FEATURES_REPLY) {
+ } else if (raw == OFPRAW_OFPT11_FEATURES_REPLY
+ || raw == OFPRAW_OFPT13_FEATURES_REPLY) {
if (osf->capabilities & htonl(OFPC11_GROUP_STATS)) {
features->capabilities |= OFPUTIL_C_GROUP_STATS;
}
features->actions = 0;
+ if (raw == OFPRAW_OFPT13_FEATURES_REPLY) {
+ features->auxiliary_id = osf->auxiliary_id;
+ }
} else {
return OFPERR_OFPBRC_BAD_VERSION;
}
case OFP12_VERSION:
raw = OFPRAW_OFPT11_FEATURES_REPLY;
break;
+ case OFP13_VERSION:
+ raw = OFPRAW_OFPT13_FEATURES_REPLY;
+ break;
default:
NOT_REACHED();
}
}
osf->actions = encode_action_bits(features->actions, of10_action_bits);
break;
+ case OFP13_VERSION:
+ osf->auxiliary_id = features->auxiliary_id;
+ /* fall through */
case OFP11_VERSION:
case OFP12_VERSION:
if (features->capabilities & OFPUTIL_C_GROUP_STATS) {
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
raw = OFPRAW_OFPT11_PORT_STATUS;
break;
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_port_mod *opm;
b = ofpraw_alloc(OFPRAW_OFPT11_PORT_MOD, ofp_version, 0);
out->matched_count = in->matched_count;
}
+static void
+ofputil_put_ofp13_table_stats(const struct ofp12_table_stats *in,
+ struct ofpbuf *buf)
+{
+ struct ofp13_table_stats *out;
+
+ /* OF 1.3 splits table features off the ofp_table_stats,
+ * so there is not much here. */
+
+ out = ofpbuf_put_uninit(buf, sizeof *out);
+ out->table_id = in->table_id;
+ out->active_count = in->active_count;
+ out->lookup_count = in->lookup_count;
+ out->matched_count = in->matched_count;
+}
+
struct ofpbuf *
ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n,
const struct ofp_header *request)
ofpbuf_put(reply, stats, n * sizeof *stats);
break;
+ case OFP13_VERSION:
+ for (i = 0; i < n; i++) {
+ ofputil_put_ofp13_table_stats(&stats[i], reply);
+ }
+ break;
+
default:
NOT_REACHED();
}
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_packet_out *opo;
size_t len;
enum ofpraw type;
switch (ofp_version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
case OFP11_VERSION:
type = OFPRAW_OFPT11_BARRIER_REQUEST;
return opp ? ofputil_decode_ofp10_phy_port(pp, opp) : EOF;
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
const struct ofp11_port *op = ofpbuf_try_pull(b, sizeof *op);
return op ? ofputil_decode_ofp11_port(pp, op) : EOF;
}
}
/* Encode a dump ports request for 'port', the encoded message
- * will be fore Open Flow version 'ofp_version'. Returns message
+ * will be for Open Flow version 'ofp_version'. Returns message
* as a struct ofpbuf. Returns encoded message on success, NULL on error */
struct ofpbuf *
ofputil_encode_dump_ports_request(enum ofp_version ofp_version, int16_t port)
break;
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_port_stats_request *req;
request = ofpraw_alloc(OFPRAW_OFPST11_PORT_REQUEST, ofp_version, 0);
req = ofpbuf_put_zeros(request, sizeof *req);
ps11->collisions = htonll(ops->stats.collisions);
}
+static void
+ofputil_port_stats_to_ofp13(const struct ofputil_port_stats *ops,
+ struct ofp13_port_stats *ps13)
+{
+ ofputil_port_stats_to_ofp11(ops, &ps13->ps);
+
+ /* OF 1.3 adds duration fields */
+ /* FIXME: Need to implement port alive duration (sec + nsec) */
+ ps13->duration_sec = htonl(~0);
+ ps13->duration_nsec = htonl(~0);
+}
+
+
/* Encode a ports stat for 'ops' and append it to 'replies'. */
void
ofputil_append_port_stat(struct list *replies,
struct ofp_header *oh = msg->data;
switch ((enum ofp_version)oh->version) {
+ case OFP13_VERSION: {
+ struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_port_stats_to_ofp13(ops, reply);
+ break;
+ }
case OFP12_VERSION:
case OFP11_VERSION: {
struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply);
return 0;
}
+static enum ofperr
+ofputil_port_stats_from_ofp13(struct ofputil_port_stats *ops,
+ const struct ofp13_port_stats *ps13)
+{
+ enum ofperr error =
+ ofputil_port_stats_from_ofp11(ops, &ps13->ps);
+ if (!error) {
+ /* FIXME: Get ps13->duration_sec and ps13->duration_nsec,
+ * Add to netdev_stats? */
+ }
+
+ return error;
+}
+
+
/* Returns the number of port stats elements in OFPTYPE_PORT_STATS_REPLY
* message 'oh'. */
size_t
if (!msg->size) {
return EOF;
+ } else if (raw == OFPRAW_OFPST13_PORT_REPLY) {
+ const struct ofp13_port_stats *ps13;
+
+ ps13 = ofpbuf_try_pull(msg, sizeof *ps13);
+ if (!ps13) {
+ goto bad_len;
+ }
+ return ofputil_port_stats_from_ofp13(ps, ps13);
} else if (raw == OFPRAW_OFPST11_PORT_REPLY) {
const struct ofp11_port_stats *ps11;
ps11 = ofpbuf_try_pull(msg, sizeof *ps11);
if (!ps11) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover "
- "bytes at end", msg->size);
- return OFPERR_OFPBRC_BAD_LEN;
+ goto bad_len;
}
return ofputil_port_stats_from_ofp11(ps, ps11);
} else if (raw == OFPRAW_OFPST10_PORT_REPLY) {
ps10 = ofpbuf_try_pull(msg, sizeof *ps10);
if (!ps10) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover "
- "bytes at end", msg->size);
- return OFPERR_OFPBRC_BAD_LEN;
+ goto bad_len;
}
return ofputil_port_stats_from_ofp10(ps, ps10);
} else {
NOT_REACHED();
}
+ bad_len:
+ VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_PORT reply has %zu leftover "
+ "bytes at end", msg->size);
+ return OFPERR_OFPBRC_BAD_LEN;
}
/* Parse a port status request message into a 16 bit OpenFlow 1.0
uint16_t *ofp10_port)
{
switch ((enum ofp_version)request->version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
case OFP11_VERSION: {
const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
struct ofputil_queue_stats_request *oqsr)
{
switch ((enum ofp_version)request->version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
case OFP11_VERSION: {
const struct ofp11_queue_stats_request *qsr11 = ofpmsg_body(request);
switch (ofp_version) {
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_queue_stats_request *req;
request = ofpraw_alloc(OFPRAW_OFPST11_QUEUE_REQUEST, ofp_version, 0);
req = ofpbuf_put_zeros(request, sizeof *req);
return 0;
}
+static enum ofperr
+ofputil_queue_stats_from_ofp13(struct ofputil_queue_stats *oqs,
+ const struct ofp13_queue_stats *qs13)
+{
+ enum ofperr error
+ = ofputil_queue_stats_from_ofp11(oqs, &qs13->qs);
+ if (!error) {
+ /* FIXME: Get qs13->duration_sec and qs13->duration_nsec,
+ * Add to netdev_queue_stats? */
+ }
+
+ return error;
+}
+
/* Converts an OFPST_QUEUE_STATS reply in 'msg' into an abstract
* ofputil_queue_stats in 'qs'.
*
if (!msg->size) {
return EOF;
+ } else if (raw == OFPRAW_OFPST13_QUEUE_REPLY) {
+ const struct ofp13_queue_stats *qs13;
+
+ qs13 = ofpbuf_try_pull(msg, sizeof *qs13);
+ if (!qs13) {
+ goto bad_len;
+ }
+ return ofputil_queue_stats_from_ofp13(qs, qs13);
} else if (raw == OFPRAW_OFPST11_QUEUE_REPLY) {
const struct ofp11_queue_stats *qs11;
qs11 = ofpbuf_try_pull(msg, sizeof *qs11);
if (!qs11) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover "
- "bytes at end", msg->size);
- return OFPERR_OFPBRC_BAD_LEN;
+ goto bad_len;
}
return ofputil_queue_stats_from_ofp11(qs, qs11);
} else if (raw == OFPRAW_OFPST10_QUEUE_REPLY) {
qs10 = ofpbuf_try_pull(msg, sizeof *qs10);
if (!qs10) {
- VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover "
- "bytes at end", msg->size);
- return OFPERR_OFPBRC_BAD_LEN;
+ goto bad_len;
}
return ofputil_queue_stats_from_ofp10(qs, qs10);
} else {
NOT_REACHED();
}
+
+ bad_len:
+ VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_QUEUE reply has %zu leftover "
+ "bytes at end", msg->size);
+ return OFPERR_OFPBRC_BAD_LEN;
}
static void
qs11->tx_errors = htonll(oqs->stats.tx_errors);
}
+static void
+ofputil_queue_stats_to_ofp13(const struct ofputil_queue_stats *oqs,
+ struct ofp13_queue_stats *qs13)
+{
+ ofputil_queue_stats_to_ofp11(oqs, &qs13->qs);
+ /* OF 1.3 adds duration fields */
+ /* FIXME: Need to implement queue alive duration (sec + nsec) */
+ qs13->duration_sec = htonl(~0);
+ qs13->duration_nsec = htonl(~0);
+}
+
/* Encode a queue stat for 'oqs' and append it to 'replies'. */
void
ofputil_append_queue_stat(struct list *replies,
struct ofp_header *oh = msg->data;
switch ((enum ofp_version)oh->version) {
+ case OFP13_VERSION: {
+ struct ofp13_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_queue_stats_to_ofp13(oqs, reply);
+ break;
+ }
+
case OFP12_VERSION:
case OFP11_VERSION: {
- struct ofp11_queue_stats *reply = ofpmp_append(replies, sizeof *reply);;
+ struct ofp11_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
ofputil_queue_stats_to_ofp11(oqs, reply);
break;
}
case OFP10_VERSION: {
- struct ofp10_queue_stats *reply = ofpmp_append(replies, sizeof *reply);;
+ struct ofp10_queue_stats *reply = ofpmp_append(replies, sizeof *reply);
ofputil_queue_stats_to_ofp10(oqs, reply);
break;
}
#define OFPUTIL_P_OF10_STD_ANY (OFPUTIL_P_OF10_STD | OFPUTIL_P_OF10_STD_TID)
#define OFPUTIL_P_OF10_NXM_ANY (OFPUTIL_P_OF10_NXM | OFPUTIL_P_OF10_NXM_TID)
- /* OpenFlow 1.2 protocol (only one variant).
+ /* OpenFlow 1.2+ protocols (only one variant each).
*
- * This uses the standard OpenFlow Extensible Match (OXM) flow format.
+ * These use the standard OpenFlow Extensible Match (OXM) flow format.
*
- * OpenFlow 1.2 always operates with an equivalent of the
+ * OpenFlow 1.2+ always operates with an equivalent of the
* nx_flow_mod_table_id Nicira extension enabled, so there is no "TID"
* variant. */
OFPUTIL_P_OF12_OXM = 1 << 4,
+ OFPUTIL_P_OF13_OXM = 1 << 5,
/* All protocols. */
-#define OFPUTIL_P_ANY ((1 << 5) - 1)
+#define OFPUTIL_P_ANY ((1 << 6) - 1)
/* Protocols in which a specific table may be specified in flow_mods. */
#define OFPUTIL_P_TID (OFPUTIL_P_OF10_STD_TID | \
OFPUTIL_P_OF10_NXM_TID | \
- OFPUTIL_P_OF12_OXM)
+ OFPUTIL_P_OF12_OXM | \
+ OFPUTIL_P_OF13_OXM)
};
/* Protocols to use for flow dumps, from most to least preferred. */
/* Bitmap of OpenFlow versions that Open vSwitch supports. */
#define OFPUTIL_SUPPORTED_VERSIONS \
- ((1u << OFP10_VERSION) | (1u << OFP12_VERSION))
+ ((1u << OFP10_VERSION) | (1u << OFP12_VERSION) | (1u << OFP13_VERSION))
/* Bitmap of OpenFlow versions to enable by default (a subset of
* OFPUTIL_SUPPORTED_VERSIONS). */
uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */
struct ofpact *ofpacts;
size_t ofpacts_len;
+ uint16_t flags; /* Added for OF 1.3 */
};
int ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *,
};
enum ofputil_capabilities {
- /* OpenFlow 1.0, 1.1 and 1.2 share these values for these capabilities. */
+ /* OpenFlow 1.0, 1.1, 1.2, and 1.3 share these capability values. */
OFPUTIL_C_FLOW_STATS = 1 << 0, /* Flow statistics. */
OFPUTIL_C_TABLE_STATS = 1 << 1, /* Table statistics. */
OFPUTIL_C_PORT_STATS = 1 << 2, /* Port statistics. */
/* OpenFlow 1.0 only. */
OFPUTIL_C_STP = 1 << 3, /* 802.1d spanning tree. */
- /* OpenFlow 1.1 and 1.2 share this capability. */
+ /* OpenFlow 1.1, 1.2, and 1.3 share this capability. */
OFPUTIL_C_GROUP_STATS = 1 << 4, /* Group statistics. */
- /* OpenFlow 1.2 only */
+ /* OpenFlow 1.2 and 1.3 share this capability */
OFPUTIL_C_PORT_BLOCKED = 1 << 8, /* Switch will block looping ports */
};
uint64_t datapath_id; /* Datapath unique ID. */
uint32_t n_buffers; /* Max packets buffered at once. */
uint8_t n_tables; /* Number of tables supported by datapath. */
+ uint8_t auxiliary_id; /* Identify auxiliary connections */
enum ofputil_capabilities capabilities;
enum ofputil_action_bitmap actions;
};
case OFPTYPE_GET_CONFIG_REQUEST:
case OFPTYPE_GET_CONFIG_REPLY:
case OFPTYPE_SET_CONFIG:
+ /* FIXME: Change the following once they are implemented: */
+ case OFPTYPE_GET_ASYNC_REQUEST:
+ case OFPTYPE_GET_ASYNC_REPLY:
+ case OFPTYPE_METER_MOD:
+ case OFPTYPE_GROUP_REQUEST:
+ case OFPTYPE_GROUP_REPLY:
+ case OFPTYPE_GROUP_DESC_REQUEST:
+ case OFPTYPE_GROUP_DESC_REPLY:
+ case OFPTYPE_GROUP_FEATURES_REQUEST:
+ case OFPTYPE_GROUP_FEATURES_REPLY:
+ case OFPTYPE_METER_REQUEST:
+ case OFPTYPE_METER_REPLY:
+ case OFPTYPE_METER_CONFIG_REQUEST:
+ case OFPTYPE_METER_CONFIG_REPLY:
+ case OFPTYPE_METER_FEATURES_REQUEST:
+ case OFPTYPE_METER_FEATURES_REPLY:
+ case OFPTYPE_TABLE_FEATURES_REQUEST:
+ case OFPTYPE_TABLE_FEATURES_REPLY:
return false;
case OFPTYPE_PACKET_IN:
if (arp_match_ip) {
features.capabilities |= OFPUTIL_C_ARP_MATCH_IP;
}
-
+ /* FIXME: Fill in proper features.auxiliary_id for auxiliary connections */
+ features.auxiliary_id = 0;
b = ofputil_encode_switch_features(&features, ofconn_get_protocol(ofconn),
oh->xid);
HMAP_FOR_EACH (port, hmap_node, &ofproto->ports) {
buf = ofpraw_alloc_reply(OFPRAW_OFPT_GET_CONFIG_REPLY, oh, 0);
osc = ofpbuf_put_uninit(buf, sizeof *osc);
flags = ofproto->frag_handling;
- if (ofconn_get_invalid_ttl_to_controller(ofconn)) {
+ /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
+ if (oh->version < OFP13_VERSION
+ && ofconn_get_invalid_ttl_to_controller(ofconn)) {
flags |= OFPC_INVALID_TTL_TO_CONTROLLER;
}
osc->flags = htons(flags);
}
}
}
+ /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OF 1.3 */
ofconn_set_invalid_ttl_to_controller(ofconn,
- (flags & OFPC_INVALID_TTL_TO_CONTROLLER));
+ (oh->version < OFP13_VERSION
+ && flags & OFPC_INVALID_TTL_TO_CONTROLLER));
ofconn_set_miss_send_len(ofconn, ntohs(osc->miss_send_len));
&fs.byte_count);
fs.ofpacts = rule->ofpacts;
fs.ofpacts_len = rule->ofpacts_len;
+ fs.flags = 0;
+ if (rule->send_flow_removed) {
+ fs.flags |= OFPFF_SEND_FLOW_REM;
+ /* FIXME: Implement OF 1.3 flags OFPFF13_NO_PKT_COUNTS
+ and OFPFF13_NO_BYT_COUNTS */
+ }
ofputil_append_flow_stats_reply(&fs, &replies);
}
ofconn_send_replies(ofconn, &replies);
return OFPERR_OFPFMFC_OVERLAP;
}
+ /* FIXME: Implement OFPFF12_RESET_COUNTS */
+
rule->ofproto = ofproto;
rule->pending = NULL;
rule->flow_cookie = fm->new_cookie;
rule->hard_timeout = fm->hard_timeout;
rule->table_id = table - ofproto->tables;
rule->send_flow_removed = (fm->flags & OFPFF_SEND_FLOW_REM) != 0;
+ /* FIXME: Implement OF 1.3 flags OFPFF13_NO_PKT_COUNTS
+ and OFPFF13_NO_BYT_COUNTS */
rule->ofpacts = xmemdup(fm->ofpacts, fm->ofpacts_len);
rule->ofpacts_len = fm->ofpacts_len;
rule->evictable = true;
bool actions_changed;
ovs_be64 new_cookie;
+ /* FIXME: Implement OFPFF12_RESET_COUNTS */
+
if (rule_is_modifiable(rule)) {
/* At least one rule is modifiable, don't report EPERM error. */
error = 0;
ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
error = ofputil_decode_flow_mod(&fm, oh, ofconn_get_protocol(ofconn),
&ofpacts);
- if (error) {
- goto exit_free_ofpacts;
- }
-
- if (fm.flags & OFPFF10_EMERG) {
- /* We do not support the OpenFlow 1.0 emergency flow cache, which
- * is not required in OpenFlow 1.0.1 and removed from OpenFlow 1.1.
- * There is no good error code, so just state that the flow table
- * is full. */
- error = OFPERR_OFPFMFC_TABLE_FULL;
- }
if (!error) {
error = ofpacts_check(fm.ofpacts, fm.ofpacts_len,
&fm.match.flow, ofproto->max_ports);
if (error) {
goto exit_free_ofpacts;
}
-
+
/* Record the operation for logging a summary report. */
switch (fm.command) {
case OFPFC_ADD:
case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
return handle_flow_monitor_request(ofconn, oh);
+ /* FIXME: Change the following once they are implemented: */
+ case OFPTYPE_GET_ASYNC_REQUEST:
+ case OFPTYPE_METER_MOD:
+ case OFPTYPE_GROUP_REQUEST:
+ case OFPTYPE_GROUP_DESC_REQUEST:
+ case OFPTYPE_GROUP_FEATURES_REQUEST:
+ case OFPTYPE_METER_REQUEST:
+ case OFPTYPE_METER_CONFIG_REQUEST:
+ case OFPTYPE_METER_FEATURES_REQUEST:
+ case OFPTYPE_TABLE_FEATURES_REQUEST:
+ return OFPERR_OFPBRC_BAD_TYPE;
+
case OFPTYPE_HELLO:
case OFPTYPE_ERROR:
case OFPTYPE_FEATURES_REPLY:
case OFPTYPE_FLOW_MONITOR_PAUSED:
case OFPTYPE_FLOW_MONITOR_RESUMED:
case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
+ case OFPTYPE_GET_ASYNC_REPLY:
+ case OFPTYPE_GROUP_REPLY:
+ case OFPTYPE_GROUP_DESC_REPLY:
+ case OFPTYPE_GROUP_FEATURES_REPLY:
+ case OFPTYPE_METER_REPLY:
+ case OFPTYPE_METER_CONFIG_REPLY:
+ case OFPTYPE_METER_FEATURES_REPLY:
+ case OFPTYPE_TABLE_FEATURES_REPLY:
default:
return OFPERR_OFPBRC_BAD_TYPE;
}
table=1 priority=0 actions=flood
]])
AT_CHECK([ovs-ofctl parse-flows flows.txt], [0],
-[[usable protocols: OpenFlow10+table_id,NXM+table_id,OXM
+[[usable protocols: OpenFlow10+table_id,NXM+table_id,OXM,OpenFlow13
chosen protocol: OpenFlow10+table_id
OFPT_FLOW_MOD (xid=0x1): ADD table:255 actions=learn(table=1,in_port=99,NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],load:NXM_OF_IN_PORT[]->NXM_NX_REG1[16..31])
OFPT_FLOW_MOD (xid=0x2): ADD table:255 actions=learn(table=1,NXM_OF_VLAN_TCI[0..11],NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[],output:NXM_OF_IN_PORT[])
OpenFlow 1.0: -1,-1
OpenFlow 1.1: 3,5
OpenFlow 1.2: 3,5
+OpenFlow 1.3: 3,5
])
AT_CHECK([ovs-ofctl print-error OFPBIC_BAD_EXP_TYPE], [0], [dnl
OpenFlow 1.0: -1,-1
OpenFlow 1.1: 3,5
OpenFlow 1.2: 3,6
+OpenFlow 1.3: 3,6
])
AT_CLEANUP
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
02 06 00 a0 00 00 00 01 00 00 50 54 00 00 00 01 \
-00 00 01 00 02 00 00 00 00 00 00 87 00 00 ff ff \
+00 00 01 00 02 00 00 00 00 00 00 87 00 00 00 00 \
ff ff ff fe 00 00 00 00 50 54 00 00 00 01 00 00 \
62 72 30 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
02 06 00 90 00 00 00 01 00 00 50 54 00 00 00 01 \
-00 00 01 00 02 00 00 00 00 00 00 87 00 00 ff ff \
+00 00 01 00 02 00 00 00 00 00 00 87 00 00 00 00 \
ff ff ff fe 00 00 00 00 50 54 00 00 00 01 00 00 \
62 72 30 00 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
"], [0], [dnl
***decode error: OFPBRC_BAD_LEN***
00000000 02 06 00 90 00 00 00 01-00 00 50 54 00 00 00 01 |..........PT....|
-00000010 00 00 01 00 02 00 00 00-00 00 00 87 00 00 ff ff |................|
+00000010 00 00 01 00 02 00 00 00-00 00 00 87 00 00 00 00 |................|
00000020 ff ff ff fe 00 00 00 00-50 54 00 00 00 01 00 00 |........PT......|
00000030 62 72 30 00 00 00 00 00-00 00 00 00 00 00 00 00 |br0.............|
00000040 00 00 00 01 00 00 00 01-00 00 00 00 00 00 00 00 |................|
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
03 06 00 a0 00 00 00 01 00 00 50 54 00 00 00 01 \
-00 00 01 00 ff 00 00 00 00 00 01 77 00 00 06 ff \
+00 00 01 00 ff 00 00 00 00 00 01 77 00 00 00 00 \
ff ff ff fe 00 00 00 00 50 54 00 00 00 01 00 00 \
62 72 30 0a 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
03 06 00 a0 00 00 00 01 00 00 50 54 00 00 00 01 \
-00 00 01 00 ff 00 00 00 00 00 01 77 00 00 06 ff \
+00 00 01 00 ff 00 00 00 00 00 01 77 00 00 00 00 \
ff ff ff fe 00 00 00 00 50 54 00 00 00 01 00 00 \
62 72 30 0a 00 00 00 00 00 00 00 00 00 00 00 00 \
00 00 00 01 00 00 00 01 00 00 00 00 00 00 00 00 \
OFPT_FEATURES_REPLY (OF1.2) (xid=0x1):
(***truncated to 144 bytes from 160***)
00000000 03 06 00 a0 00 00 00 01-00 00 50 54 00 00 00 01 |..........PT....|
-00000010 00 00 01 00 ff 00 00 00-00 00 01 77 00 00 06 ff |...........w....|
+00000010 00 00 01 00 ff 00 00 00-00 00 01 77 00 00 00 00 |...........w....|
00000020 ff ff ff fe 00 00 00 00-50 54 00 00 00 01 00 00 |........PT......|
00000030 62 72 30 0a 00 00 00 00-00 00 00 00 00 00 00 00 |br0.............|
00000040 00 00 00 01 00 00 00 01-00 00 00 00 00 00 00 00 |................|
])
AT_CLEANUP
+AT_SETUP([OFPT_FEATURES_REPLY - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 06 00 20 00 00 00 01 00 00 50 54 00 00 00 01 \
+00 00 01 00 ff 00 00 00 00 00 01 77 00 00 00 00 \
+"], [0], [dnl
+OFPT_FEATURES_REPLY (OF1.3) (xid=0x1): dpid:0000505400000001
+n_tables:255, n_buffers:256
+capabilities: FLOW_STATS TABLE_STATS PORT_STATS IP_REASM QUEUE_STATS PORT_BLOCKED
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_FEATURES_REPLY - with auxiliary_id - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 06 00 20 00 00 00 01 00 00 50 54 00 00 00 01 \
+00 00 01 00 ff 01 00 00 00 00 01 77 00 00 00 00 \
+"], [0], [dnl
+OFPT_FEATURES_REPLY (OF1.3) (xid=0x1): dpid:0000505400000001
+n_tables:255, n_buffers:256, auxiliary_id:1
+capabilities: FLOW_STATS TABLE_STATS PORT_STATS IP_REASM QUEUE_STATS PORT_BLOCKED
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_GET_CONFIG_REQUEST])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print '0107000800000001'], [0], [dnl
])
AT_CLEANUP
+AT_SETUP([OFPT_PACKET_IN - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 0a 00 54 00 00 00 00 ff ff ff 00 00 2a 00 00 \
+01 02 03 04 05 06 07 08 00 01 00 0c 80 00 00 04 \
+ff ff ff fe 00 00 00 00 00 00 ff ff ff ff ff ff \
+00 23 20 83 c1 5f 80 35 00 01 08 00 06 04 00 03 \
+00 23 20 83 c1 5f 00 00 00 00 00 23 20 83 c1 5f \
+00 00 00 00 \
+"], [0], [dnl
+OFPT_PACKET_IN (OF1.3) (xid=0x0): cookie=0x102030405060708 total_len=42 in_port=LOCAL (via no_match) data_len=42 buffer=0xffffff00
+priority=0,rarp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=00:23:20:83:c1:5f,dl_dst=ff:ff:ff:ff:ff:ff,arp_spa=0.0.0.0,arp_tpa=0.0.0.0,arp_op=3,arp_sha=00:23:20:83:c1:5f,arp_tha=00:23:20:83:c1:5f
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_FLOW_REMOVED - OF1.0])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPT_FLOW_REMOVED - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 0b 00 40 00 00 00 00 fe dc ba 98 76 54 32 10 \
+80 00 01 05 00 00 00 01 00 98 96 80 00 3c 00 78 \
+00 00 00 00 00 12 d6 87 00 00 00 00 6f 68 ba 66 \
+00 01 00 0a 80 00 0c 02 10 09 00 00 00 00 00 00"], [0], [dnl
+OFPT_FLOW_REMOVED (OF1.3) (xid=0x0): dl_vlan=9 reason=hard table_id=5 cookie:0xfedcba9876543210 duration1.01s idle60 hard120 pkts1234567 bytes1869134438
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_PORT_STATUS - OF1.0])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+# The flow is formatted with cls_rule_format() for the low-verbosity case.
+AT_SETUP([OFPT_FLOW_MOD - OF1.3 - flags - low verbosity])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
+04 0e 00 90 00 00 00 02 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 ff 00 00 00 00 00 ff ff \
+ff ff ff ff ff ff ff ff ff ff ff ff 00 1f 00 00 \
+00 01 00 42 80 00 00 04 00 00 00 01 80 00 08 06 \
+50 54 00 00 00 06 80 00 06 06 50 54 00 00 00 05 \
+80 00 0a 02 08 06 80 00 0c 02 00 00 80 00 2a 02 \
+00 02 80 00 2c 04 c0 a8 00 02 80 00 2e 04 c0 a8 \
+00 01 00 00 00 00 00 00 00 04 00 18 00 00 00 00 \
+00 00 00 10 00 00 00 03 00 00 00 00 00 00 00 00 \
+" 2], [0], [dnl
+OFPT_FLOW_MOD (OF1.3) (xid=0x2): ADD table:255 priority=65535,arp,in_port=1,vlan_tci=0x0000/0x1fff,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,arp_spa=192.168.0.2,arp_tpa=192.168.0.1,arp_op=2 send_flow_rem check_overlap reset_counts no_packet_counts no_byte_counts actions=output:3
+], [dnl
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_FLOW_MOD - OF1.2 - set-field ip_src])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPT_PORT_MOD - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 10 00 28 00 00 00 03 00 00 00 03 00 00 00 00 \
+50 54 00 00 00 01 00 00 00 00 00 01 00 00 00 01 \
+00 00 00 00 00 00 00 00 \
+" 3], [0], [dnl
+OFPT_PORT_MOD (OF1.3) (xid=0x3):port: 3: addr:50:54:00:00:00:01
+ config: PORT_DOWN
+ mask: PORT_DOWN
+ advertise: UNCHANGED
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_DESC request])
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
AT_CHECK([ovs-ofctl ofp-print "0110000c0000000100000000"], [0], [dnl
])
AT_CLEANUP
+AT_SETUP([OFPST_FLOW request - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 12 00 38 00 00 00 02 00 01 00 00 00 00 00 00 \
+ff 00 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 01 00 04 00 00 00 00 \
+"], [0], [dnl
+OFPST_FLOW request (OF1.3) (xid=0x2): @&t@
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_FLOW reply - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPST_AGGREGATE request - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 12 00 38 00 00 00 02 00 02 00 00 00 00 00 00 \
+ff 00 00 00 ff ff ff ff ff ff ff ff 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 01 00 04 00 00 00 00 \
+"], [0], [dnl
+OFPST_AGGREGATE request (OF1.3) (xid=0x2): @&t@
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_AGGREGATE reply - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPST_AGGREGATE reply - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 13 00 28 00 00 00 02 00 02 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 79 00 00 00 00 00 00 4b 4f \
+00 00 00 03 00 00 00 00 \
+"], [0], [dnl
+OFPST_AGGREGATE reply (OF1.3) (xid=0x2): packet_count=121 byte_count=19279 flow_count=3
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_TABLE request - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
AT_CHECK([ovs-ofctl ofp-print "0110000c0000000100030000"], [0], [dnl
])
AT_CLEANUP
+AT_SETUP([OFPST_TABLE request - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "04120010000000020003000000000000"], [0], [dnl
+OFPST_TABLE request (OF1.3) (xid=0x2):
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_TABLE reply - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
AT_CHECK([ovs-ofctl ofp-print "\
AT_CHECK([ovs-ofctl ofp-print "$(cat in)"], [0], [expout])
AT_CLEANUP
+AT_SETUP([OFPST_TABLE reply - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 13 00 40 00 00 00 01 00 03 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 0b 00 00 00 00 00 00 02 00 \
+00 00 00 00 00 00 01 00 01 00 00 00 00 00 00 0c \
+00 00 00 00 00 00 02 01 00 00 00 00 00 00 01 01 \
+"], [0], [dnl
+OFPST_TABLE reply (OF1.3) (xid=0x1): 2 tables
+ 0: active=11, lookup=512, matched=256
+ 1: active=12, lookup=513, matched=257
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_PORT request - 1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPST_PORT request - 1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 12 00 18 00 00 00 02 00 04 00 00 00 00 00 00 \
+ff ff ff ff 00 00 00 00 \
+"], [0], [dnl
+OFPST_PORT request (OF1.3) (xid=0x2): port_no=65535
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_PORT reply - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPST_QUEUE request - OF1.3])
+AT_KEYWORDS([ofp-print OFPT_STATS_REQUEST])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 12 00 18 00 00 00 02 00 05 00 00 00 00 00 00 \
+ff ff ff ff ff ff ff ff \
+"], [0], [dnl
+OFPST_QUEUE request (OF1.3) (xid=0x2):port=ANY queue=ALL
+])
+AT_CLEANUP
+
AT_SETUP([OFPST_QUEUE reply - OF1.0])
AT_KEYWORDS([ofp-print OFPT_STATS_REPLY])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CLEANUP
+AT_SETUP([OFPT_BARRIER_REQUEST - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print '04 14 00 08 00 00 00 01'], [0], [dnl
+OFPT_BARRIER_REQUEST (OF1.3) (xid=0x1):
+])
+AT_CLEANUP
+
AT_SETUP([OFPT_BARRIER_REPLY - OF1.0])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print '01 13 00 08 00 00 00 01'], [0], [dnl
])
AT_CLEANUP
-AT_SETUP([OFPT_BARRIER_REPLY] - OF1.1)
+AT_SETUP([OFPT_BARRIER_REPLY - OF1.1])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print '02 15 00 08 00 00 00 01'], [0], [dnl
OFPT_BARRIER_REPLY (OF1.1) (xid=0x1):
])
AT_CLEANUP
-AT_SETUP([OFPT_BARRIER_REPLY] - OF1.2)
+AT_SETUP([OFPT_BARRIER_REPLY - OF1.2])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print '03 15 00 08 00 00 00 01'], [0], [dnl
OFPT_BARRIER_REPLY (OF1.2) (xid=0x1):
])
AT_CLEANUP
+AT_SETUP([OFPT_BARRIER_REPLY - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print '04 15 00 08 00 00 00 01'], [0], [dnl
+OFPT_BARRIER_REPLY (OF1.3) (xid=0x1):
+])
+AT_CLEANUP
+
+
+AT_SETUP([OFPT_SET_ASYNC - OF1.3])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl ofp-print "\
+04 1c 00 20 00 00 00 00 00 00 10 05 00 00 10 07 \
+00 00 00 03 00 00 00 07 00 00 00 00 00 00 00 03 \
+"], [0], [dnl
+OFPT_SET_ASYNC (OF1.3) (xid=0x0):
+ master:
+ PACKET_IN: no_match invalid_ttl 12
+ PORT_STATUS: add delete
+ FLOW_REMOVED: (off)
+
+ slave:
+ PACKET_IN: no_match action invalid_ttl 12
+ PORT_STATUS: add delete modify
+ FLOW_REMOVED: idle hard
+])
+AT_CLEANUP
+
AT_SETUP([NXT_ROLE_REQUEST])
AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print "\
])
AT_CHECK([ovs-ofctl encode-hello 0x1e], [0], [dnl
00000000 04 00 00 08 00 00 00 01-
-OFPT_HELLO (OF 0x04) (xid=0x1):
+OFPT_HELLO (OF1.3) (xid=0x1):
version bitmap: 0x01, 0x02, 0x03, 0x04
])
+AT_CHECK([ovs-ofctl encode-hello 0x3e], [0], [dnl
+00000000 05 00 00 08 00 00 00 01-
+OFPT_HELLO (OF 0x05) (xid=0x1):
+ version bitmap: 0x01, 0x02, 0x03, 0x04, 0x05
+])
dnl Some versions below max version missing.
AT_CHECK([ovs-ofctl encode-hello 0xc], [0], [dnl
AT_CHECK([ovs-ofctl parse-flows flows.txt
], [0], [stdout])
AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
-[[usable protocols: NXM+table_id,OXM
+[[usable protocols: NXM+table_id,OXM,OpenFlow13
chosen protocol: NXM+table_id
NXT_FLOW_MOD: ADD table:255 tcp,tp_src=123 actions=FLOOD
NXT_FLOW_MOD: ADD table:255 in_port=65534,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
])
AT_CHECK([ovs-ofctl -F nxm parse-flows flows.txt], [0], [stdout])
AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0], [dnl
-usable protocols: NXM,OXM
+usable protocols: NXM,OXM,OpenFlow13
chosen protocol: NXM-table_id
NXT_FLOW_MOD: ADD tcp,tp_src=123 actions=FLOOD
NXT_FLOW_MOD: ADD in_port=65534,dl_vlan=9,dl_src=00:0a:e4:25:6b:b0 actions=drop
]])
AT_CHECK([ovs-ofctl -F nxm -mmm parse-flows flows.txt], [0], [stdout], [stderr])
AT_CHECK([[sed 's/ (xid=0x[0-9a-fA-F]*)//' stdout]], [0],
-[[usable protocols: NXM,OXM
+[[usable protocols: NXM,OXM,OpenFlow13
chosen protocol: NXM-table_id
NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800), NXM_OF_IP_PROTO(06), NXM_OF_TCP_SRC(007b) actions=FLOOD
NXT_FLOW_MOD: ADD NXM_OF_IN_PORT(fffe), NXM_OF_ETH_SRC(000ae4256bb0), NXM_OF_VLAN_TCI_W(1009/1fff) actions=drop
dnl such as tunnels and metadata.
AT_SETUP([ovs-ofctl -F option and NXM features])
AT_CHECK([ovs-ofctl -F openflow10 add-flow dummy tun_id=123,actions=drop],
- [1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM) is among the allowed flow formats (OpenFlow10)
+ [1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM,OpenFlow13) is among the allowed flow formats (OpenFlow10)
])
AT_CHECK([ovs-ofctl -F openflow10 add-flow dummy metadata=123,actions=drop],
- [1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM) is among the allowed flow formats (OpenFlow10)
+ [1], [], [ovs-ofctl: none of the usable flow formats (NXM,OXM,OpenFlow13) is among the allowed flow formats (OpenFlow10)
])
AT_CLEANUP
AT_SETUP([ovs-ofctl dump-flows rejects bad -F option])
OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -F openflow10 dump-flows unix:br0.mgmt reg0=0xabcdef], [1], [],
- [ovs-ofctl: none of the usable flow formats (NXM,OXM) is among the allowed flow formats (OpenFlow10)
+ [ovs-ofctl: none of the usable flow formats (NXM,OXM,OpenFlow13) is among the allowed flow formats (OpenFlow10)
])
OVS_VSWITCHD_STOP
AT_CLEANUP
{"name": "Open_vSwitch",
- "version": "6.11.2",
- "cksum": "2033079075 17296",
+ "version": "6.11.3",
+ "cksum": "2234602985 17310",
"tables": {
"Open_vSwitch": {
"columns": {
"min": 0, "max": "unlimited"}},
"protocols": {
"type": {"key": {"type": "string",
- "enum": ["set", ["OpenFlow10", "OpenFlow12"]]},
+ "enum": ["set", ["OpenFlow10", "OpenFlow12", "OpenFlow13"]]},
"min": 0, "max": "unlimited"}},
"fail_mode": {
"type": {"key": {"type": "string",