Signed-off-by: Alexandru Copot <alex.miha...@gmail.com> Cc: Daniel Baluta <dbal...@ixiacom.com> --- 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 4c48ca6..b9f4077 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -2292,6 +2292,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; @@ -2508,6 +2511,90 @@ ofp_print_group_mod(struct ds *s, const struct ofp_header *oh) ofp_print_group(s, gm.group_id, gm.type, &gm.buckets); } +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) @@ -2753,6 +2840,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 9a563eb..4edb11f 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -6721,3 +6721,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 a4143ad..6ca2507 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -1050,4 +1050,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 1308820..6ff7f44 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.miha...@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.miha...@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 033ab7d..c5a6efb 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 3c9216f..bb7caf7 100644 --- a/ofproto/connmgr.h +++ b/ofproto/connmgr.h @@ -146,6 +146,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 19e7091..9e06daa 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -57,6 +57,7 @@ #include "unaligned.h" #include "unixctl.h" #include "vlog.h" +#include "bundles.h" VLOG_DEFINE_THIS_MODULE(ofproto); @@ -5838,6 +5839,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) { @@ -5969,6 +6036,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.0 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev