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 ovs_list msg_list;
-};
-
-static uint32_t
-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, 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)
{
bundle->id = id;
bundle->flags = flags;
+ bundle->state = BS_OPEN;
list_init(&bundle->msg_list);
return bundle;
}
-static void
-ofp_bundle_remove(struct ofconn *ofconn, struct ofp_bundle *bundle)
+void
+ofp_bundle_remove__(struct ofconn *ofconn, struct ofp_bundle *bundle)
{
struct ofp_bundle_entry *msg;
- struct hmap *bundles;
LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
ofp_bundle_entry_free(msg);
}
- bundles = ofconn_get_bundles(ofconn);
- hmap_remove(bundles, &bundle->node);
-
+ ofconn_remove_bundle(ofconn, bundle);
free(bundle);
}
-void
-ofp_bundle_remove_all(struct ofconn *ofconn)
-{
- struct ofp_bundle *b, *next;
- struct hmap *bundles;
-
- bundles = ofconn_get_bundles(ofconn);
-
- HMAP_FOR_EACH_SAFE (b, next, node, bundles) {
- ofp_bundle_remove(ofconn, b);
- }
-}
-
enum ofperr
ofp_bundle_open(struct ofconn *ofconn, uint32_t id, uint16_t flags)
{
- struct hmap *bundles;
struct ofp_bundle *bundle;
+ enum ofperr error;
- bundles = ofconn_get_bundles(ofconn);
- bundle = ofp_bundle_find(bundles, id);
+ bundle = ofconn_get_bundle(ofconn, id);
if (bundle) {
VLOG_INFO("Bundle %x already exists.", id);
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return OFPERR_OFPBFC_BAD_ID;
}
- /* XXX: Check the limit of open bundles */
-
bundle = ofp_bundle_create(id, flags);
- bundle->state = BS_OPEN;
-
- bundles = ofconn_get_bundles(ofconn);
- hmap_insert(bundles, &bundle->node, bundle_hash(id));
+ error = ofconn_insert_bundle(ofconn, bundle);
+ if (error) {
+ free(bundle);
+ }
- return 0;
+ return error;
}
enum ofperr
ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
{
- struct hmap *bundles;
struct ofp_bundle *bundle;
- bundles = ofconn_get_bundles(ofconn);
- bundle = ofp_bundle_find(bundles, id);
+ bundle = ofconn_get_bundle(ofconn, id);
if (!bundle) {
return OFPERR_OFPBFC_BAD_ID;
}
if (bundle->state == BS_CLOSED) {
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return OFPERR_OFPBFC_BUNDLE_CLOSED;
}
if (bundle->flags != flags) {
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return OFPERR_OFPBFC_BAD_FLAGS;
}
enum ofperr
ofp_bundle_commit(struct ofconn *ofconn, uint32_t id, uint16_t flags)
{
- struct hmap *bundles;
struct ofp_bundle *bundle;
enum ofperr error = 0;
struct ofp_bundle_entry *msg;
- bundles = ofconn_get_bundles(ofconn);
- bundle = ofp_bundle_find(bundles, id);
+ bundle = ofconn_get_bundle(ofconn, id);
if (!bundle) {
return OFPERR_OFPBFC_BAD_ID;
}
}
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return error;
}
enum ofperr
ofp_bundle_discard(struct ofconn *ofconn, uint32_t id)
{
- struct hmap *bundles;
struct ofp_bundle *bundle;
- bundles = ofconn_get_bundles(ofconn);
- bundle = ofp_bundle_find(bundles, id);
+ bundle = ofconn_get_bundle(ofconn, id);
if (!bundle) {
return OFPERR_OFPBFC_BAD_ID;
}
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return 0;
}
ofp_bundle_add_message(struct ofconn *ofconn, uint32_t id, uint16_t flags,
struct ofp_bundle_entry *bmsg)
{
- struct hmap *bundles;
struct ofp_bundle *bundle;
- bundles = ofconn_get_bundles(ofconn);
- bundle = ofp_bundle_find(bundles, id);
+ bundle = ofconn_get_bundle(ofconn, id);
if (!bundle) {
- bundle = ofp_bundle_create(id, flags);
- bundle->state = BS_OPEN;
+ enum ofperr error;
- bundles = ofconn_get_bundles(ofconn);
- hmap_insert(bundles, &bundle->node, bundle_hash(id));
+ bundle = ofp_bundle_create(id, flags);
+ error = ofconn_insert_bundle(ofconn, bundle);
+ if (error) {
+ free(bundle);
+ return error;
+ }
} else if (bundle->state == BS_CLOSED) {
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return OFPERR_OFPBFC_BUNDLE_CLOSED;
} else if (flags != bundle->flags) {
- ofp_bundle_remove(ofconn, bundle);
+ ofp_bundle_remove__(ofconn, bundle);
return OFPERR_OFPBFC_BAD_FLAGS;
}
}
ofconn->last_op = now;
}
+\f
+/* OpenFlow 1.4 bundles. */
+
+static inline uint32_t
+bundle_hash(uint32_t id)
+{
+ return hash_int(id, 0);
+}
-struct hmap *
-ofconn_get_bundles(struct ofconn *ofconn)
+struct ofp_bundle *
+ofconn_get_bundle(struct ofconn *ofconn, uint32_t id)
{
- return &ofconn->bundles;
+ struct ofp_bundle *bundle;
+
+ HMAP_FOR_EACH_IN_BUCKET(bundle, node, bundle_hash(id), &ofconn->bundles) {
+ if (bundle->id == id) {
+ return bundle;
+ }
+ }
+
+ return NULL;
}
+enum ofperr
+ofconn_insert_bundle(struct ofconn *ofconn, struct ofp_bundle *bundle)
+{
+ /* XXX: Check the limit of open bundles */
+
+ hmap_insert(&ofconn->bundles, &bundle->node, bundle_hash(bundle->id));
+
+ return 0;
+}
+
+enum ofperr
+ofconn_remove_bundle(struct ofconn *ofconn, struct ofp_bundle *bundle)
+{
+ hmap_remove(&ofconn->bundles, &bundle->node);
+
+ return 0;
+}
+
+static void
+bundle_remove_all(struct ofconn *ofconn)
+{
+ struct ofp_bundle *b, *next;
+
+ HMAP_FOR_EACH_SAFE (b, next, node, &ofconn->bundles) {
+ ofp_bundle_remove__(ofconn, b);
+ }
+}
\f
/* Private ofconn functions. */
hmap_remove(&ofconn->connmgr->controllers, &ofconn->hmap_node);
}
- ofp_bundle_remove_all(ofconn);
+ bundle_remove_all(ofconn);
hmap_destroy(&ofconn->bundles);
hmap_destroy(&ofconn->monitors);