[ovs-dev] [PATCH v2 1/3] Add basic implementation for OpenFlow 1.4 bundles
Alexandru Copot
alex.mihai.c at gmail.com
Tue Mar 25 16:39:21 UTC 2014
This patch implements the communication part of the bundles functionality.
The actual message pre-validation and commits are not implemented.
Signed-off-by: Alexandru Copot <alex.mihai.c at gmail.com>
Cc: Daniel Baluta <dbaluta at ixiacom.com>
---
Changes since v1: rebase
---
lib/learning-switch.c | 2 +
lib/ofp-errors.h | 52 +++++++++++
lib/ofp-msgs.h | 10 ++
lib/ofp-print.c | 95 +++++++++++++++++++
lib/ofp-util.c | 57 ++++++++++++
lib/ofp-util.h | 20 ++++
lib/rconn.c | 2 +
ofproto/automake.mk | 5 +-
ofproto/bundles.c | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++
ofproto/bundles.h | 53 +++++++++++
ofproto/connmgr.c | 23 +++++
ofproto/connmgr.h | 3 +
ofproto/ofproto.c | 73 +++++++++++++++
13 files changed, 646 insertions(+), 1 deletion(-)
create mode 100644 ofproto/bundles.c
create mode 100644 ofproto/bundles.h
diff --git a/lib/learning-switch.c b/lib/learning-switch.c
index 5620990..adb276f 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(msg->data, msg->size, 2);
diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
index c80a75e..b1bcf7c 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 d8dee5b..bfc94b2 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_add_msg, uint8_t[16][]. */
+ 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 da89405..7483d98 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -2289,6 +2289,9 @@ ofp_print_version(const struct ofp_header *oh,
case OFP13_VERSION:
ds_put_cstr(string, " (OF1.3)");
break;
+ case OFP14_VERSION:
+ ds_put_cstr(string, " (OF1.4)");
+ break;
default:
ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
break;
@@ -2659,6 +2662,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 "UNKNOWN";
+ }
+}
+
+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, (uint32_t)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((const void*)&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)
@@ -2904,6 +2991,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 dae6e78..e962aa6 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -7050,3 +7050,60 @@ 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 = b.l3;
+ 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)
+{
+ struct ofpbuf b;
+ enum ofpraw raw;
+ const struct ofp14_bundle_add_msg *m;
+
+ ofpbuf_use_const(&b, oh, ntohs(oh->length));
+ raw = ofpraw_pull_assert(&b);
+ ovs_assert(raw == OFPRAW_OFPT14_BUNDLE_ADD_MESSAGE);
+
+ m = b.l3;
+ msg->bundle_id = ntohl(m->bundle_id);
+ msg->flags = ntohs(m->flags);
+ memcpy(&msg->msg, &m->message, sizeof(msg->msg));
+
+ return 0;
+}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 298d595..c9afece 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -1128,4 +1128,24 @@ 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;
+ 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 *);
+
+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 72688ba..30dd91d 100644
--- a/lib/rconn.c
+++ b/lib/rconn.c
@@ -1344,6 +1344,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:
diff --git a/ofproto/automake.mk b/ofproto/automake.mk
index 448138b..10ac972 100644
--- a/ofproto/automake.mk
+++ b/ofproto/automake.mk
@@ -43,7 +43,10 @@ ofproto_libofproto_la_SOURCES = \
ofproto/pinsched.c \
ofproto/pinsched.h \
ofproto/tunnel.c \
- ofproto/tunnel.h
+ ofproto/tunnel.h \
+ ofproto/bundles.c \
+ ofproto/bundles.h
+
ofproto_libofproto_la_CPPFLAGS = $(AM_CPPFLAGS)
ofproto_libofproto_la_CFLAGS = $(AM_CFLAGS)
ofproto_libofproto_la_LIBADD = lib/libsflow.la
diff --git a/ofproto/bundles.c b/ofproto/bundles.c
new file mode 100644
index 0000000..41efa12
--- /dev/null
+++ b/ofproto/bundles.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ *
+ * Alexandru Copot <alex.mihai.c at gmail.com>, with support from IXIA.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include "coverage.h"
+#include "fail-open.h"
+#include "in-band.h"
+#include "odp-util.h"
+#include "ofp-actions.h"
+#include "ofp-msgs.h"
+#include "ofp-util.h"
+#include "ofpbuf.h"
+#include "ofproto-provider.h"
+#include "pinsched.h"
+#include "poll-loop.h"
+#include "pktbuf.h"
+#include "rconn.h"
+#include "shash.h"
+#include "simap.h"
+#include "stream.h"
+#include "timeval.h"
+#include "vconn.h"
+#include "vlog.h"
+
+#include "bundles.h"
+
+VLOG_DEFINE_THIS_MODULE(bundles);
+
+enum bundle_state {
+ BS_OPEN,
+ BS_CLOSED
+};
+
+struct ofp_bundle {
+ struct hmap_node node; /* In struct ofconn's "bundles" hmap. */
+ uint32_t id;
+ uint16_t flags;
+ enum bundle_state state;
+
+ /* List of 'struct bundle_message's */
+ struct list msg_list;
+ struct ovs_mutex list_mutex;
+};
+
+struct bundle_message {
+ struct ofp_header msg;
+ struct list node; /* Element in 'struct ofp_bundles's msg_list */
+};
+
+static uint32_t
+ofp_bundle_hash(uint32_t id)
+{
+ return hash_int(id, 0);
+}
+
+static struct ofp_bundle *
+ofp_bundle_find(struct hmap *bundles, uint32_t id)
+{
+ struct ofp_bundle *bundle;
+
+ HMAP_FOR_EACH_IN_BUCKET(bundle, node, ofp_bundle_hash(id), bundles) {
+ if (bundle->id == id)
+ return bundle;
+ }
+
+ return NULL;
+}
+
+static struct ofp_bundle *
+ofp_bundle_create(uint32_t id, uint16_t flags)
+{
+ struct ofp_bundle *bundle;
+
+ bundle = xmalloc(sizeof(*bundle));
+
+ bundle->id = id;
+ bundle->flags = flags;
+
+ list_init(&bundle->msg_list);
+ ovs_mutex_init(&bundle->list_mutex);
+
+ return bundle;
+}
+
+static void
+ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *item)
+{
+ struct bundle_message *msg, *next;
+ struct hmap *bundles;
+
+ LIST_FOR_EACH_SAFE (msg, next, node, &item->msg_list) {
+ list_remove(&msg->node);
+ free(msg);
+ }
+
+ bundles = ofconn_lock_bundles(ofconn);
+ hmap_remove(bundles, &item->node);
+ ofconn_unlock_bundles(ofconn);
+
+ free(item);
+}
+
+enum ofperr
+ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
+{
+ struct hmap *bundles;
+ struct ofp_bundle *bundle;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ bundle = ofp_bundle_find(bundles, id);
+ ofconn_unlock_bundles(ofconn);
+
+ if (bundle) {
+ VLOG_INFO("Bundle %x already exists.\n", id);
+ ofp_bundle_remove(ofconn, bundle);
+
+ return OFPERR_OFPBFC_BAD_ID;
+ }
+
+ /* TODO: Check the limit of open bundles */
+
+ bundle = ofp_bundle_create(id, flags);
+ bundle->state = BS_OPEN;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ hmap_insert(bundles, &bundle->node, hash_int(id, 10));
+ ofconn_unlock_bundles(ofconn);
+
+ return 0;
+}
+
+enum ofperr
+ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
+{
+ struct hmap *bundles;
+ struct ofp_bundle *bundle;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ bundle = ofp_bundle_find(bundles, id);
+ ofconn_unlock_bundles(ofconn);
+
+ if (!bundle) {
+ return OFPERR_OFPBFC_BAD_ID;
+ }
+
+ if (bundle->state == BS_CLOSED) {
+ ofp_bundle_remove(ofconn, bundle);
+ return OFPERR_OFPBFC_BUNDLE_CLOSED;
+ }
+
+ if (bundle->flags != flags) {
+ ofp_bundle_remove(ofconn, bundle);
+ return OFPERR_OFPBFC_BAD_FLAGS;
+ }
+
+ bundle->state = BS_CLOSED;
+ return 0;
+}
+
+enum ofperr
+ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
+{
+ struct hmap *bundles;
+ struct ofp_bundle *bundle;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ bundle = ofp_bundle_find(bundles, id);
+ ofconn_unlock_bundles(ofconn);
+
+ if (!bundle) {
+ return OFPERR_OFPBFC_BAD_ID;
+ }
+ if (bundle->flags != flags) {
+ ofp_bundle_remove(ofconn, bundle);
+ return OFPERR_OFPBFC_BAD_FLAGS;
+ }
+
+ /* TODO: actual commit */
+
+ return 0;
+}
+
+enum ofperr
+ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
+{
+ struct hmap *bundles;
+ struct ofp_bundle *bundle;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ bundle = ofp_bundle_find(bundles, id);
+ ofconn_unlock_bundles(ofconn);
+
+ if (!bundle) {
+ return OFPERR_OFPBFC_BAD_ID;
+ }
+
+ ofp_bundle_remove(ofconn, bundle);
+
+ return 0;
+}
+
+enum ofperr
+ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
+ struct ofp_header *msg)
+{
+ struct hmap *bundles;
+ struct ofp_bundle *bundle;
+ struct bundle_message *bmsg;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ bundle = ofp_bundle_find(bundles, id);
+ ofconn_unlock_bundles(ofconn);
+
+ if (!bundle) {
+ bundle = ofp_bundle_create(id, flags);
+ bundle->state = BS_OPEN;
+
+ bundles = ofconn_lock_bundles(ofconn);
+ hmap_insert(bundles, &bundle->node, hash_int(id, 10));
+ ofconn_unlock_bundles(ofconn);
+ }
+
+ if (bundle->state == BS_CLOSED) {
+ ofp_bundle_remove(ofconn, bundle);
+ return OFPERR_OFPBFC_BUNDLE_CLOSED;
+ }
+
+ bmsg = xmalloc(sizeof(*bmsg));
+ bmsg->msg = *msg;
+
+ ovs_mutex_lock(&bundle->list_mutex);
+ list_push_back(&bundle->msg_list, &bmsg->node);
+ ovs_mutex_unlock(&bundle->list_mutex);
+
+ return 0;
+}
diff --git a/ofproto/bundles.h b/ofproto/bundles.h
new file mode 100644
index 0000000..396d0cb
--- /dev/null
+++ b/ofproto/bundles.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ *
+ * Alexandru Copot <alex.mihai.c at gmail.com>, with support from IXIA.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BUNDLES_H
+#define BUNDLES_H 1
+
+#include <sys/types.h>
+
+#include "ofp-msgs.h"
+#include "connmgr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum ofperr
+ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags);
+
+enum ofperr
+ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags);
+
+
+enum ofperr
+ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags);
+
+enum ofperr
+ofp_bundle_discard(struct ofconn *ofconn, uint32_t id);
+
+enum ofperr
+ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
+ struct ofp_header *msg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 9bc1897..369150d 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -129,6 +129,10 @@ struct ofconn {
* contains an update event of type NXFME_ABBREV and false otherwise.. */
struct list updates OVS_GUARDED_BY(ofproto_mutex);
bool sent_abbrev_update OVS_GUARDED_BY(ofproto_mutex);
+
+ /* Active bundles. Contains "struct ofp_bundle"s. */
+ struct hmap bundles;
+ struct ovs_mutex bundles_mutex;
};
static struct ofconn *ofconn_create(struct connmgr *, struct rconn *,
@@ -1136,6 +1140,22 @@ ofconn_add_opgroup(struct ofconn *ofconn, struct list *ofconn_node)
{
list_push_back(&ofconn->opgroups, ofconn_node);
}
+
+struct hmap *
+ofconn_lock_bundles(struct ofconn *ofconn)
+OVS_ACQUIRES(&ofconn->bundles_mutex)
+{
+ ovs_mutex_lock(&ofconn->bundles_mutex);
+ return &ofconn->bundles;
+}
+
+void
+ofconn_unlock_bundles(struct ofconn *ofconn)
+OVS_RELEASES(&ofconn->bundles_mutex)
+{
+ ovs_mutex_unlock(&ofconn->bundles_mutex);
+}
+
/* Private ofconn functions. */
@@ -1163,6 +1183,9 @@ ofconn_create(struct connmgr *mgr, struct rconn *rconn, enum ofconn_type type,
hmap_init(&ofconn->monitors);
list_init(&ofconn->updates);
+ hmap_init(&ofconn->bundles);
+ ovs_mutex_init(&ofconn->bundles_mutex);
+
ofconn_flush(ofconn);
return ofconn;
diff --git a/ofproto/connmgr.h b/ofproto/connmgr.h
index c4cfd83..0cb893a 100644
--- a/ofproto/connmgr.h
+++ b/ofproto/connmgr.h
@@ -161,6 +161,9 @@ void ofconn_add_opgroup(struct ofconn *, struct list *);
void ofconn_remove_opgroup(struct ofconn *, struct list *,
const struct ofp_header *request, int error);
+struct hmap *ofconn_lock_bundles(struct ofconn *ofconn);
+void ofconn_unlock_bundles(struct ofconn *ofconn);
+
/* Sending asynchronous messages. */
void connmgr_send_port_status(struct connmgr *, struct ofconn *source,
const struct ofputil_phy_port *, uint8_t reason);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 277c1d7..cb3df89 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -58,6 +58,7 @@
#include "unaligned.h"
#include "unixctl.h"
#include "vlog.h"
+#include "bundles.h"
VLOG_DEFINE_THIS_MODULE(ofproto);
@@ -5840,6 +5841,72 @@ handle_table_mod(struct ofconn *ofconn, const struct ofp_header *oh)
}
static enum ofperr
+handle_bundle_control(struct ofconn *ofconn, const struct ofp_header *oh)
+{
+ enum ofperr error;
+ struct ofputil_bundle_ctrl_msg bctrl;
+ struct ofpbuf *buf;
+ struct ofputil_bundle_ctrl_msg reply;
+
+ error = ofputil_decode_bundle_ctrl(oh, &bctrl);
+ if (error) {
+ return error;
+ }
+ reply.flags = 0;
+ reply.bundle_id = bctrl.bundle_id;
+
+ switch (bctrl.type) {
+ case OFPBCT_OPEN_REQUEST:
+ error = ofp_bundle_open(ofconn, bctrl.bundle_id, bctrl.flags);
+ reply.type = OFPBCT_OPEN_REPLY;
+ break;
+ case OFPBCT_CLOSE_REQUEST:
+ error = ofp_bundle_close(ofconn, bctrl.bundle_id, bctrl.flags);
+ reply.type = OFPBCT_CLOSE_REPLY;;
+ break;
+ case OFPBCT_COMMIT_REQUEST:
+ error = ofp_bundle_commit(ofconn, bctrl.bundle_id, bctrl.flags);
+ reply.type = OFPBCT_COMMIT_REPLY;
+ break;
+ case OFPBCT_DISCARD_REQUEST:
+ error = ofp_bundle_discard(ofconn, bctrl.bundle_id);
+ reply.type = OFPBCT_DISCARD_REPLY;
+ break;
+
+ case OFPBCT_OPEN_REPLY:
+ case OFPBCT_CLOSE_REPLY:
+ case OFPBCT_COMMIT_REPLY:
+ case OFPBCT_DISCARD_REPLY:
+ return OFPERR_OFPBFC_BAD_TYPE;
+ break;
+ }
+
+ if (!error) {
+ buf = ofputil_encode_bundle_ctrl_reply(oh, &reply);
+ ofconn_send_reply(ofconn, buf);
+ }
+ return error;
+}
+
+
+static enum ofperr
+handle_bundle_add(struct ofconn *ofconn, const struct ofp_header *oh)
+{
+ enum ofperr error;
+ struct ofputil_bundle_add_msg badd;
+
+ error = ofputil_decode_bundle_add(oh, &badd);
+ if (error) {
+ return error;
+ }
+
+ error = ofp_bundle_add_message(ofconn, badd.bundle_id,
+ badd.flags, &badd.msg);
+
+ return error;
+}
+
+static enum ofperr
handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
OVS_EXCLUDED(ofproto_mutex)
{
@@ -5971,6 +6038,12 @@ handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg)
case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
return handle_queue_get_config_request(ofconn, oh);
+ case OFPTYPE_BUNDLE_CONTROL:
+ return handle_bundle_control(ofconn, oh);
+
+ case OFPTYPE_BUNDLE_ADD_MESSAGE:
+ return handle_bundle_add(ofconn, oh);
+
case OFPTYPE_HELLO:
case OFPTYPE_ERROR:
case OFPTYPE_FEATURES_REPLY:
--
1.9.1
More information about the dev
mailing list