summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJarno Rajahalme <jarno.rajahalme@nsn.com>2012-11-27 17:44:22 +0200
committerBen Pfaff <blp@nicira.com>2012-11-27 09:37:50 -0800
commit2e1ae2005ed347d2dfebd23fff40c54a1a2a6716 (patch)
treee8bfc3b61bd60017b5da871dfd0a0a62f7f8690d /lib
parent6ed3b860fe806fce26dfc760cb428a9a5432d329 (diff)
downloadopenvswitch-2e1ae2005ed347d2dfebd23fff40c54a1a2a6716.tar.gz
Initial OpenFlow 1.3 support
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>
Diffstat (limited to 'lib')
-rw-r--r--lib/learning-switch.c19
-rw-r--r--lib/nx-match.c1
-rw-r--r--lib/ofp-errors.c3
-rw-r--r--lib/ofp-errors.h74
-rw-r--r--lib/ofp-msgs.c4
-rw-r--r--lib/ofp-msgs.h135
-rw-r--r--lib/ofp-parse.c6
-rw-r--r--lib/ofp-print.c126
-rw-r--r--lib/ofp-util.c336
-rw-r--r--lib/ofp-util.h22
-rw-r--r--lib/rconn.c18
11 files changed, 640 insertions, 104 deletions
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 5df05f35c..0e0d779b2 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -366,13 +366,30 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
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);
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 837db8d3f..a3a8bc389 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1202,6 +1202,7 @@ nxm_reg_load_to_nxast(const struct ofpact_reg_load *load,
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;
diff --git a/lib/ofp-errors.c b/lib/ofp-errors.c
index 2c71312ec..9fd48fe79 100644
--- a/lib/ofp-errors.c
+++ b/lib/ofp-errors.c
@@ -31,6 +31,8 @@ ofperr_domain_from_version(enum ofp_version version)
return &ofperr_of11;
case OFP12_VERSION:
return &ofperr_of12;
+ case OFP13_VERSION:
+ return &ofperr_of13;
default:
return NULL;
}
@@ -257,6 +259,7 @@ ofperr_encode_hello(enum ofperr error, enum ofp_version ofp_version,
case OFP10_VERSION:
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
break;
default:
diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
index ffac8aa4a..e9fedb9e0 100644
--- a/lib/ofp-errors.h
+++ b/lib/ofp-errors.h
@@ -130,6 +130,9 @@ enum ofperr {
/* 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,
@@ -492,6 +495,77 @@ enum ofperr {
/* 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 ## */
/* ## ------------------ ## */
diff --git a/lib/ofp-msgs.c b/lib/ofp-msgs.c
index 00e1a8448..d0f5da69c 100644
--- a/lib/ofp-msgs.c
+++ b/lib/ofp-msgs.c
@@ -265,6 +265,7 @@ ofphdrs_is_stat(const struct ofphdrs *hdrs)
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);
}
@@ -291,6 +292,7 @@ ofphdrs_len(const struct ofphdrs *hdrs)
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
@@ -704,6 +706,7 @@ ofpraw_stats_request_to_reply(enum ofpraw raw, uint8_t version)
break;
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
assert(hdrs.type == OFPT11_STATS_REQUEST);
hdrs.type = OFPT11_STATS_REPLY;
break;
@@ -880,6 +883,7 @@ ofpmp_flags__(const struct ofp_header *oh)
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();
diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h
index 557524dcf..496d120a4 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -128,8 +128,10 @@ enum ofpraw {
/* 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,
@@ -146,6 +148,8 @@ enum ofpraw {
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,
@@ -188,6 +192,18 @@ enum ofpraw {
/* 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. */
@@ -205,8 +221,10 @@ enum ofpraw {
/* 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,
@@ -222,7 +240,7 @@ enum ofpraw {
/* 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[]. */
@@ -231,6 +249,8 @@ enum ofpraw {
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,
@@ -239,8 +259,10 @@ enum ofpraw {
/* 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,
@@ -249,8 +271,54 @@ enum ofpraw {
/* 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,
@@ -283,9 +351,6 @@ enum ofpraw {
/* 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,
@@ -360,7 +425,8 @@ enum ofptype {
/* 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. */
@@ -369,6 +435,7 @@ enum ofptype {
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.
@@ -391,6 +458,15 @@ enum ofptype {
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. */
@@ -399,6 +475,7 @@ enum ofptype {
* 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.
@@ -408,15 +485,48 @@ enum ofptype {
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.
@@ -429,7 +539,6 @@ enum ofptype {
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. */
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 1d71370d4..d64d461ea 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -858,6 +858,12 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
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;
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 1e35fba79..fcc6d254a 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -492,8 +492,13 @@ ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
}
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,
@@ -510,6 +515,8 @@ ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
case OFP11_VERSION:
case OFP12_VERSION:
break;
+ case OFP13_VERSION:
+ return; /* no ports in ofp13_switch_features */
default:
NOT_REACHED();
}
@@ -673,6 +680,33 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity)
}
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)
{
struct ofputil_flow_mod fm;
@@ -771,22 +805,7 @@ 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);
@@ -1028,6 +1047,9 @@ ofp_print_flow_stats(struct ds *string, struct ofputil_flow_stats *fs)
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);
}
@@ -1166,6 +1188,11 @@ ofp_print_one_ofpst_table_reply(struct ds *string, enum ofp_version ofp_version,
{
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_);
@@ -1210,6 +1237,36 @@ ofp_print_one_ofpst_table_reply(struct ds *string, enum ofp_version ofp_version,
}
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)
{
@@ -1316,6 +1373,10 @@ ofp_print_ofpst_table_reply(struct ds *string, const struct ofp_header *oh,
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;
@@ -1722,6 +1783,9 @@ ofp_print_version(const struct ofp_header *oh,
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;
@@ -1738,6 +1802,12 @@ ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
}
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)
{
@@ -1745,6 +1815,28 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
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;
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index bab6b2ce2..0b96eb6d9 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -588,6 +588,7 @@ static const struct proto_abbrev proto_abbrevs[] = {
#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,
@@ -607,6 +608,8 @@ ofputil_protocol_from_ofp_version(enum ofp_version version)
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;
@@ -614,7 +617,7 @@ ofputil_protocol_from_ofp_version(enum ofp_version version)
}
/* 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)
{
@@ -626,6 +629,8 @@ 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();
@@ -664,6 +669,9 @@ ofputil_protocol_set_tid(enum ofputil_protocol protocol, bool enable)
case OFPUTIL_P_OF12_OXM:
return OFPUTIL_P_OF12_OXM;
+ case OFPUTIL_P_OF13_OXM:
+ return OFPUTIL_P_OF13_OXM;
+
default:
NOT_REACHED();
}
@@ -698,6 +706,9 @@ ofputil_protocol_set_base(enum ofputil_protocol cur,
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();
}
@@ -728,6 +739,9 @@ ofputil_protocol_to_string(enum ofputil_protocol protocol)
case OFPUTIL_P_OF12_OXM:
return "OXM";
+
+ case OFPUTIL_P_OF13_OXM:
+ return "OpenFlow13";
}
/* Check abbreviations. */
@@ -860,6 +874,9 @@ ofputil_version_from_string(const char *s)
if (!strcasecmp(s, "OpenFlow12")) {
return OFP12_VERSION;
}
+ if (!strcasecmp(s, "OpenFlow13")) {
+ return OFP13_VERSION;
+ }
return 0;
}
@@ -928,6 +945,8 @@ ofputil_version_to_string(enum ofp_version ofp_version)
return "OpenFlow11";
case OFP12_VERSION:
return "OpenFlow12";
+ case OFP13_VERSION:
+ return "OpenFlow13";
default:
NOT_REACHED();
}
@@ -1008,68 +1027,81 @@ ofputil_usable_protocols(const struct match *match)
/* 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. */
@@ -1269,8 +1301,9 @@ ofputil_encode_set_protocol(enum ofputil_protocol current,
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:
@@ -1511,6 +1544,16 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
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;
@@ -1544,10 +1587,12 @@ ofputil_encode_flow_mod(const struct ofputil_flow_mod *fm,
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) {
@@ -1644,7 +1689,8 @@ ofputil_flow_mod_usable_protocols(const struct ofputil_flow_mod *fms,
/* 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;
}
}
@@ -1764,13 +1810,15 @@ ofputil_encode_flow_stats_request(const struct ofputil_flow_stats_request *fsr,
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);
@@ -1835,7 +1883,8 @@ ofputil_flow_stats_request_usable_protocols(
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;
}
@@ -1878,7 +1927,8 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
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;
@@ -1914,6 +1964,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
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;
@@ -1953,6 +2004,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
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;
@@ -1999,6 +2051,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
}
fs->packet_count = ntohll(nfs->packet_count);
fs->byte_count = ntohll(nfs->byte_count);
+ fs->flags = 0;
} else {
NOT_REACHED();
}
@@ -2031,7 +2084,7 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
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);
@@ -2048,6 +2101,7 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
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));
@@ -2247,7 +2301,8 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
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,
@@ -2341,12 +2396,19 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
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;
@@ -2356,11 +2418,14 @@ ofputil_decode_packet_in(struct ofputil_packet_in *pin,
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) {
@@ -2440,27 +2505,43 @@ ofputil_encode_packet_in(const struct ofputil_packet_in *pin,
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,
@@ -2729,6 +2810,7 @@ ofputil_get_phy_port_size(enum ofp_version ofp_version)
return sizeof(struct ofp10_phy_port);
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
return sizeof(struct ofp11_port);
default:
NOT_REACHED();
@@ -2791,7 +2873,8 @@ ofputil_put_phy_port(enum ofp_version ofp_version,
}
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);
@@ -2820,7 +2903,8 @@ ofputil_append_port_desc_stats_reply(enum ofp_version ofp_version,
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_port *op;
op = ofpmp_append(replies, sizeof *op);
@@ -2889,6 +2973,7 @@ ofputil_capabilities_mask(enum ofp_version ofp_version)
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 */
@@ -2916,6 +3001,7 @@ ofputil_decode_switch_features(const struct ofp_header *oh,
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);
@@ -2929,11 +3015,15 @@ ofputil_decode_switch_features(const struct ofp_header *oh,
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;
}
@@ -3010,6 +3100,9 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features,
case OFP12_VERSION:
raw = OFPRAW_OFPT11_FEATURES_REPLY;
break;
+ case OFP13_VERSION:
+ raw = OFPRAW_OFPT13_FEATURES_REPLY;
+ break;
default:
NOT_REACHED();
}
@@ -3029,6 +3122,9 @@ ofputil_encode_switch_features(const struct ofputil_switch_features *features,
}
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) {
@@ -3102,6 +3198,7 @@ ofputil_encode_port_status(const struct ofputil_port_status *ps,
case OFP11_VERSION:
case OFP12_VERSION:
+ case OFP13_VERSION:
raw = OFPRAW_OFPT11_PORT_STATUS;
break;
@@ -3185,7 +3282,8 @@ ofputil_encode_port_mod(const struct ofputil_port_mod *pm,
}
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);
@@ -3309,6 +3407,22 @@ ofputil_put_ofp11_table_stats(const struct ofp12_table_stats *in,
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)
@@ -3335,6 +3449,12 @@ ofputil_encode_table_stats_reply(const struct ofp12_table_stats stats[], int n,
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();
}
@@ -3631,7 +3751,8 @@ ofputil_encode_packet_out(const struct ofputil_packet_out *po,
}
case OFP11_VERSION:
- case OFP12_VERSION: {
+ case OFP12_VERSION:
+ case OFP13_VERSION: {
struct ofp11_packet_out *opo;
size_t len;
@@ -3689,6 +3810,7 @@ ofputil_encode_barrier_request(enum ofp_version ofp_version)
enum ofpraw type;
switch (ofp_version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
case OFP11_VERSION:
type = OFPRAW_OFPT11_BARRIER_REQUEST;
@@ -3920,7 +4042,8 @@ ofputil_pull_phy_port(enum ofp_version ofp_version, struct ofpbuf *b,
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;
}
@@ -4219,7 +4342,7 @@ ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
}
/* 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)
@@ -4235,7 +4358,8 @@ 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);
@@ -4289,6 +4413,19 @@ ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops,
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,
@@ -4298,6 +4435,11 @@ 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);
@@ -4368,6 +4510,21 @@ ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
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
@@ -4408,14 +4565,20 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
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) {
@@ -4423,15 +4586,17 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
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
@@ -4442,6 +4607,7 @@ ofputil_decode_port_stats_request(const struct ofp_header *request,
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);
@@ -4466,6 +4632,7 @@ ofputil_decode_queue_stats_request(const struct ofp_header *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);
@@ -4500,7 +4667,8 @@ ofputil_encode_queue_stats_request(enum ofp_version ofp_version,
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);
@@ -4572,6 +4740,20 @@ ofputil_queue_stats_from_ofp11(struct ofputil_queue_stats *oqs,
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'.
*
@@ -4597,14 +4779,20 @@ ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg)
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) {
@@ -4612,14 +4800,17 @@ ofputil_decode_queue_stats(struct ofputil_queue_stats *qs, struct ofpbuf *msg)
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
@@ -4645,6 +4836,17 @@ ofputil_queue_stats_to_ofp11(const struct ofputil_queue_stats *oqs,
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,
@@ -4654,15 +4856,21 @@ 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;
}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index ed1a5382c..d35488741 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -77,22 +77,24 @@ enum ofputil_protocol {
#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. */
@@ -130,7 +132,7 @@ void ofputil_format_version_bitmap_names(struct ds *msg, uint32_t bitmap);
/* 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). */
@@ -263,6 +265,7 @@ struct ofputil_flow_stats {
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 *,
@@ -399,7 +402,7 @@ struct ofputil_phy_port {
};
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. */
@@ -412,10 +415,10 @@ enum ofputil_capabilities {
/* 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 */
};
@@ -455,6 +458,7 @@ struct ofputil_switch_features {
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;
};
diff --git a/lib/rconn.c b/lib/rconn.c
index a6b634bc7..45a0acd61 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -1123,6 +1123,24 @@ is_admitted_msg(const struct ofpbuf *b)
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: