summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexandru Copot <alex.mihai.c@gmail.com>2014-05-02 09:54:27 +0300
committerBen Pfaff <blp@nicira.com>2014-05-02 09:41:33 -0700
commit777af88d50b8271a8cc8f0a79d17022944481506 (patch)
tree3f6d419d949582706c3771a9d33dfe5be521c998 /lib
parent17a40d3404df4aa6393dd126cb6f0ae99b72031a (diff)
downloadopenvswitch-777af88d50b8271a8cc8f0a79d17022944481506.tar.gz
Add basic implementation for OpenFlow 1.4 bundles
This is only the communication part of the bundles functionality. The actual message pre-validation and commits are not implemented. We also enable OF1.4 for all the tests. Signed-off-by: Alexandru Copot <alex.mihai.c@gmail.com> Cc: Daniel Baluta <dbaluta@ixiacom.com> [blp@nicira.com made ofputil_decode_bundle_add() more obviously correct] Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/learning-switch.c2
-rw-r--r--lib/ofp-errors.h52
-rw-r--r--lib/ofp-msgs.h10
-rw-r--r--lib/ofp-print.c92
-rw-r--r--lib/ofp-util.c80
-rw-r--r--lib/ofp-util.h23
-rw-r--r--lib/rconn.c2
7 files changed, 261 insertions, 0 deletions
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index c818a3213..ca579116f 100644
--- a/lib/learning-switch.c
+++ b/lib/learning-switch.c
@@ -398,6 +398,8 @@ lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg)
case OFPTYPE_METER_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+ case OFPTYPE_BUNDLE_CONTROL:
+ case OFPTYPE_BUNDLE_ADD_MESSAGE:
default:
if (VLOG_IS_DBG_ENABLED()) {
char *s = ofp_to_string(ofpbuf_data(msg), ofpbuf_size(msg), 2);
diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
index c80a75eb0..b1bcf7cc1 100644
--- a/lib/ofp-errors.h
+++ b/lib/ofp-errors.h
@@ -557,6 +557,58 @@ enum ofperr {
/* OF1.3+(13,5). Permissions error. */
OFPERR_OFPTFFC_EPERM,
+/* ## -------------------- ## */
+/* ## OFPET_BUNDLE_FAILED ## */
+/* ## -------------------- ## */
+
+ /* OF1.4+(17,0). Unspecified error. */
+ OFPERR_OFPBFC_UNKNOWN,
+
+ /* OF1.4+(17,1). Permissions error. */
+ OFPERR_OFPBFC_EPERM,
+
+ /* OF1.4+(17,2). Bundle ID doesn't exist. */
+ OFPERR_OFPBFC_BAD_ID,
+
+ /* OF1.4+(17,3). Bundle ID already exists. */
+ OFPERR_OFPBFC_BUNDLE_EXIST,
+
+ /* OF1.4+(17,4). Bundle ID is closed. */
+ OFPERR_OFPBFC_BUNDLE_CLOSED,
+
+ /* OF1.4+(17,5). Too many bundle IDs. */
+ OFPERR_OFPBFC_OUT_OF_BUNDLES,
+
+ /* OF1.4+(17,6). Unsupported of unknown message control type. */
+ OFPERR_OFPBFC_BAD_TYPE,
+
+ /* OF1.4+(17,7). Unsupported, unknown, or inconsistent flags. */
+ OFPERR_OFPBFC_BAD_FLAGS,
+
+ /* OF1.4+(17,8). Length problem in included message. */
+ OFPERR_OFPBFC_MSG_BAD_LEN,
+
+ /* OF1.4+(17,9). Inconsistent or duplicate XID. */
+ OFPERR_OFPBFC_MSG_BAD_XID,
+
+ /* OF1.4+(17,10). Unsupported message in this bundle. */
+ OFPERR_OFPBFC_MSG_UNSUP,
+
+ /* OF1.4+(17,11). Unsupported message combination in this bundle. */
+ OFPERR_OFPBFC_MSG_CONFLICT,
+
+ /* OF1.4+(17,12). Cant handle this many messages in bundle. */
+ OFPERR_OFPBFC_MSG_TOO_MANY,
+
+ /* OF1.4+(17,13). One message in bundle failed. */
+ OFPERR_OFPBFC_MSG_FAILED,
+
+ /* OF1.4+(17,14). Bundle is taking too long. */
+ OFPERR_OFPBFC_TIMEOUT,
+
+ /* OF1.4+(17,15). Bundle is locking the resource. */
+ OFPERR_OFPBFC_BUNDLE_IN_PROGRESS,
+
/* ## ------------------ ## */
/* ## OFPET_EXPERIMENTER ## */
/* ## ------------------ ## */
diff --git a/lib/ofp-msgs.h b/lib/ofp-msgs.h
index d8dee5b53..ded904265 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -233,6 +233,12 @@ enum ofpraw {
/* OFPT 1.4+ (30): struct ofp14_role_status, uint8_t[8][]. */
OFPRAW_OFPT14_ROLE_STATUS,
+ /* OFPT 1.4+ (33): struct ofp14_bundle_ctrl_msg, uint8_t[8][]. */
+ OFPRAW_OFPT14_BUNDLE_CONTROL,
+
+ /* OFPT 1.4+ (34): struct ofp14_bundle_ctrl_msg, uint8_t[]. */
+ OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE,
+
/* Standard statistics. */
/* OFPST 1.0+ (0): void. */
@@ -508,6 +514,10 @@ enum ofptype {
/* Controller role change event messages. */
OFPTYPE_ROLE_STATUS, /* OFPRAW_OFPT14_ROLE_STATUS. */
+ OFPTYPE_BUNDLE_CONTROL, /* OFPRAW_OFPT14_BUNDLE_CONTROL. */
+
+ OFPTYPE_BUNDLE_ADD_MESSAGE, /* OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE. */
+
/* Statistics. */
OFPTYPE_DESC_STATS_REQUEST, /* OFPRAW_OFPST_DESC_REQUEST. */
OFPTYPE_DESC_STATS_REPLY, /* OFPRAW_OFPST_DESC_REPLY. */
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 38e228c9d..a2e515d2d 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -2668,6 +2668,90 @@ ofp_print_table_features(struct ds *s, const struct ofp_header *oh)
}
}
+static const char *
+bundle_flags_to_name(uint32_t bit)
+{
+ switch (bit) {
+ case OFPBF_ATOMIC:
+ return "atomic";
+ case OFPBF_ORDERED:
+ return "ordered";
+ default:
+ return NULL;
+ }
+}
+
+static void
+ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
+{
+ int error;
+ struct ofputil_bundle_ctrl_msg bctrl;
+
+ error = ofputil_decode_bundle_ctrl(oh, &bctrl);
+ if (error) {
+ ofp_print_error(s, error);
+ return;
+ }
+
+ ds_put_char(s, '\n');
+
+ ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id);
+ switch (bctrl.type) {
+ case OFPBCT_OPEN_REQUEST:
+ ds_put_cstr(s, "OPEN_REQUEST");
+ break;
+ case OFPBCT_OPEN_REPLY:
+ ds_put_cstr(s, "OPEN_REPLY");
+ break;
+ case OFPBCT_CLOSE_REQUEST:
+ ds_put_cstr(s, "CLOSE_REQUEST");
+ break;
+ case OFPBCT_CLOSE_REPLY:
+ ds_put_cstr(s, "CLOSE_REPLY");
+ break;
+ case OFPBCT_COMMIT_REQUEST:
+ ds_put_cstr(s, "COMMIT_REQUEST");
+ break;
+ case OFPBCT_COMMIT_REPLY:
+ ds_put_cstr(s, "COMMIT_REPLY");
+ break;
+ case OFPBCT_DISCARD_REQUEST:
+ ds_put_cstr(s, "DISCARD_REQUEST");
+ break;
+ case OFPBCT_DISCARD_REPLY:
+ ds_put_cstr(s, "DISCARD_REPLY");
+ break;
+ }
+
+ ds_put_cstr(s, " flags=");
+ ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' ');
+}
+
+static void
+ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh, int verbosity)
+{
+ int error;
+ struct ofputil_bundle_add_msg badd;
+ char *msg;
+
+ error = ofputil_decode_bundle_add(oh, &badd);
+ if (error) {
+ ofp_print_error(s, error);
+ return;
+ }
+
+ ds_put_char(s, '\n');
+ ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id);
+ ds_put_cstr(s, " flags=");
+ ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' ');
+
+ ds_put_char(s, '\n');
+ msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), verbosity);
+ if (msg) {
+ ds_put_cstr(s, msg);
+ }
+}
+
static void
ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
struct ds *string, int verbosity)
@@ -2913,6 +2997,14 @@ ofp_to_string__(const struct ofp_header *oh, enum ofpraw raw,
case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
ofp_print_nxst_flow_monitor_reply(string, msg);
break;
+
+ case OFPTYPE_BUNDLE_CONTROL:
+ ofp_print_bundle_ctrl(string, msg);
+ break;
+
+ case OFPTYPE_BUNDLE_ADD_MESSAGE:
+ ofp_print_bundle_add(string, msg, verbosity);
+ break;
}
}
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 3484394c5..d17811348 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -7054,3 +7054,83 @@ ofputil_append_queue_stat(struct list *replies,
OVS_NOT_REACHED();
}
}
+
+enum ofperr
+ofputil_decode_bundle_ctrl(const struct ofp_header *oh,
+ struct ofputil_bundle_ctrl_msg *msg)
+{
+ struct ofpbuf b;
+ enum ofpraw raw;
+ const struct ofp14_bundle_ctrl_msg *m;
+
+ ofpbuf_use_const(&b, oh, ntohs(oh->length));
+ raw = ofpraw_pull_assert(&b);
+ ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_CONTROL);
+
+ m = ofpbuf_l3(&b);
+ msg->bundle_id = ntohl(m->bundle_id);
+ msg->type = ntohs(m->type);
+ msg->flags = ntohs(m->flags);
+
+ return 0;
+}
+
+struct ofpbuf *
+ofputil_encode_bundle_ctrl_reply(const struct ofp_header *oh,
+ struct ofputil_bundle_ctrl_msg *msg)
+{
+ struct ofpbuf *buf;
+ struct ofp14_bundle_ctrl_msg *m;
+
+ buf = ofpraw_alloc_reply(OFPRAW_OFPT14_BUNDLE_CONTROL, oh, 0);
+ m = ofpbuf_put_zeros(buf, sizeof *m);
+
+ m->bundle_id = htonl(msg->bundle_id);
+ m->type = htons(msg->type);
+ m->flags = htons(msg->flags);
+
+ return buf;
+}
+
+enum ofperr
+ofputil_decode_bundle_add(const struct ofp_header *oh,
+ struct ofputil_bundle_add_msg *msg)
+{
+ const struct ofp14_bundle_ctrl_msg *m;
+ struct ofpbuf b;
+ enum ofpraw raw;
+ size_t inner_len;
+
+ ofpbuf_use_const(&b, oh, ntohs(oh->length));
+ raw = ofpraw_pull_assert(&b);
+ ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE);
+
+ m = ofpbuf_pull(&b, sizeof *m);
+ msg->bundle_id = ntohl(m->bundle_id);
+ msg->flags = ntohs(m->flags);
+
+ msg->msg = ofpbuf_data(&b);
+ inner_len = ntohs(msg->msg->length);
+ if (inner_len < sizeof(struct ofp_header) || inner_len > ofpbuf_size(&b)) {
+ return OFPERR_OFPBFC_MSG_BAD_LEN;
+ }
+
+ return 0;
+}
+
+struct ofpbuf *
+ofputil_encode_bundle_add(enum ofp_version ofp_version,
+ struct ofputil_bundle_add_msg *msg)
+{
+ struct ofpbuf *request;
+ struct ofp14_bundle_ctrl_msg *m;
+
+ request = ofpraw_alloc(OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE, ofp_version, 0);
+ m = ofpbuf_put_zeros(request, sizeof *m);
+
+ m->bundle_id = htonl(msg->bundle_id);
+ m->flags = htons(msg->flags);
+ ofpbuf_put(request, msg->msg, ntohs(msg->msg->length));
+
+ return request;
+}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 7c2803461..782e512a2 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -1137,4 +1137,27 @@ void ofputil_append_group_desc_reply(const struct ofputil_group_desc *,
struct list *replies);
struct ofpbuf *ofputil_encode_group_desc_request(enum ofp_version);
+struct ofputil_bundle_ctrl_msg {
+ uint32_t bundle_id;
+ uint16_t type;
+ uint16_t flags;
+};
+
+struct ofputil_bundle_add_msg {
+ uint32_t bundle_id;
+ uint16_t flags;
+ const struct ofp_header *msg;
+};
+
+enum ofperr ofputil_decode_bundle_ctrl(const struct ofp_header *,
+ struct ofputil_bundle_ctrl_msg *);
+
+struct ofpbuf *ofputil_encode_bundle_ctrl_reply(const struct ofp_header *,
+ struct ofputil_bundle_ctrl_msg *);
+
+struct ofpbuf *ofputil_encode_bundle_add(enum ofp_version ofp_version,
+ struct ofputil_bundle_add_msg *msg);
+
+enum ofperr ofputil_decode_bundle_add(const struct ofp_header *,
+ struct ofputil_bundle_add_msg *);
#endif /* ofp-util.h */
diff --git a/lib/rconn.c b/lib/rconn.c
index cb3cdd5d4..2c49ca850 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -1350,6 +1350,8 @@ is_admitted_msg(const struct ofpbuf *b)
case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
+ case OFPTYPE_BUNDLE_CONTROL:
+ case OFPTYPE_BUNDLE_ADD_MESSAGE:
return false;
case OFPTYPE_PACKET_IN: