Implement Vacancy Events for OFPMP_TABLE_DESC.
[cascardo/ovs.git] / ofproto / bundles.c
index f6ad608..003b20b 100644 (file)
 
 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)
 {
@@ -86,88 +51,73 @@ 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,
+                    bool success)
 {
     struct ofp_bundle_entry *msg;
-    struct hmap *bundles;
 
     LIST_FOR_EACH_POP (msg, node, &bundle->msg_list) {
+        if (success && msg->type == OFPTYPE_FLOW_MOD) {
+            /* Tell connmgr about successful flow mods. */
+            ofconn_report_flow_mod(ofconn, msg->ofm.fm.command);
+        }
         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, false);
 
         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, false);
         return OFPERR_OFPBFC_BUNDLE_CLOSED;
     }
 
     if (bundle->flags != flags) {
-        ofp_bundle_remove(ofconn, bundle);
+        ofp_bundle_remove__(ofconn, bundle, false);
         return OFPERR_OFPBFC_BAD_FLAGS;
     }
 
@@ -175,47 +125,18 @@ ofp_bundle_close(struct ofconn *ofconn, uint32_t id, uint16_t flags)
     return 0;
 }
 
-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);
-
-    if (!bundle) {
-        return OFPERR_OFPBFC_BAD_ID;
-    }
-    if (bundle->flags != flags) {
-        error = OFPERR_OFPBFC_BAD_FLAGS;
-    } else {
-        LIST_FOR_EACH (msg, node, &bundle->msg_list) {
-            /* XXX: actual commit */
-            error = OFPERR_OFPBFC_MSG_FAILED;
-        }
-    }
-
-    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, false);
 
     return 0;
 }
@@ -224,23 +145,24 @@ enum ofperr
 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, false);
         return OFPERR_OFPBFC_BUNDLE_CLOSED;
     } else if (flags != bundle->flags) {
-        ofp_bundle_remove(ofconn, bundle);
+        ofp_bundle_remove__(ofconn, bundle, false);
         return OFPERR_OFPBFC_BAD_FLAGS;
     }