[ovs-dev] [PATCH v2 11/13] ofproto: handle (draft) OpenFlow 1.5 insert and remove group commands

Simon Horman simon.horman at netronome.com
Tue Nov 11 03:39:27 UTC 2014


Handle (draft) OpenFlow 1.5 insert and remove group commands
of group mod messages.

ONF-JIRA: EXT-350
Signed-off-by: Simon Horman <simon.horman at netronome.com>

---
v2
* As suggested by Ben Pfaff
  - Use ONF-JIRA: EXT-350 annotation in changelog
---
 ofproto/ofproto.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 6be338a..c52b940 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -5779,7 +5779,91 @@ add_group(struct ofproto *ofproto, struct ofputil_group_mod *gm)
     return error;
 }
 
-/* Implements OFPGC11_MODIFY.  Returns 0 on success or an OpenFlow error code
+static enum ofperr
+copy_buckets_for_insert_bucket(const struct ofgroup *ofgroup,
+                               struct ofgroup *new_ofgroup,
+                               uint32_t command_bucket_id)
+{
+    struct ofputil_bucket *last = NULL;
+
+    if (command_bucket_id <= OFPG15_BUCKET_MAX) {
+        /* Check here to ensure that a bucket corresponding to
+         * command_bucket_id exists in the old bucket list.
+         *
+         * The subsequent search of below of new_ofgroup covers
+         * both buckets in the old bucket list and buckets added
+         * by the insert buckets group mod message this function processes. */
+        if (!ofputil_bucket_find(&ofgroup->buckets, command_bucket_id)) {
+            return OFPERR_OFPGMFC_UNKNOWN_BUCKET;
+        }
+
+        if (!list_is_empty(&new_ofgroup->buckets)) {
+            last = ofputil_bucket_list_back(&new_ofgroup->buckets);
+        }
+    }
+
+    ofputil_bucket_clone_list(&new_ofgroup->buckets, &ofgroup->buckets, NULL);
+
+    if (ofputil_bucket_check_duplicate_id(&ofgroup->buckets)) {
+            VLOG_WARN_RL(&rl, "Duplicate bucket id");
+            return OFPERR_OFPGMFC_BUCKET_EXISTS;
+    }
+
+    /* Rearrange list according to command_bucket_id */
+    if (command_bucket_id == OFPG15_BUCKET_LAST) {
+        struct ofputil_bucket *new_first;
+        const struct ofputil_bucket *first;
+
+        first = ofputil_bucket_list_front(&ofgroup->buckets);
+        new_first = ofputil_bucket_find(&new_ofgroup->buckets,
+                                        first->bucket_id);
+
+        list_splice(new_ofgroup->buckets.next, &new_first->list_node,
+                    &new_ofgroup->buckets);
+    } else if (command_bucket_id <= OFPG15_BUCKET_MAX && last) {
+        struct ofputil_bucket *after;
+
+        /* Presence of bucket is checked above so after should never be NULL */
+        after = ofputil_bucket_find(&new_ofgroup->buckets, command_bucket_id);
+
+        list_splice(after->list_node.next, new_ofgroup->buckets.next,
+                    last->list_node.next);
+    }
+
+    return 0;
+}
+
+static enum ofperr
+copy_buckets_for_remove_bucket(const struct ofgroup *ofgroup,
+                               struct ofgroup *new_ofgroup,
+                               uint32_t command_bucket_id)
+{
+    const struct ofputil_bucket *skip = NULL;
+
+    if (command_bucket_id == OFPG15_BUCKET_ALL) {
+        return 0;
+    }
+
+    if (!list_is_empty(&ofgroup->buckets)) {
+        if (command_bucket_id == OFPG15_BUCKET_FIRST) {
+            skip = ofputil_bucket_list_front(&ofgroup->buckets);
+        } else if (command_bucket_id == OFPG15_BUCKET_LAST) {
+            skip = ofputil_bucket_list_back(&ofgroup->buckets);
+        } else {
+            skip = ofputil_bucket_find(&ofgroup->buckets, command_bucket_id);
+            if (!skip) {
+                return OFPERR_OFPGMFC_UNKNOWN_BUCKET;
+            }
+        }
+    }
+
+    ofputil_bucket_clone_list(&new_ofgroup->buckets, &ofgroup->buckets, skip);
+
+    return 0;
+}
+
+/* Implements OFPGC11_MODIFY, OFPGC15_INSERT_BUCKET and
+ * OFPGC15_REMOVE_BUCKET.  Returns 0 on success or an OpenFlow error code
  * on failure.
  *
  * Note that the group is re-created and then replaces the old group in
@@ -5811,6 +5895,18 @@ modify_group(struct ofproto *ofproto, struct ofputil_group_mod *gm)
         goto out;
     }
 
+    /* Manipulate bucket list for bucket commands */
+    if (gm->command == OFPGC15_INSERT_BUCKET) {
+        error = copy_buckets_for_insert_bucket(ofgroup, new_ofgroup,
+                                               gm->command_bucket_id);
+    } else if (gm->command == OFPGC15_REMOVE_BUCKET) {
+        error = copy_buckets_for_remove_bucket(ofgroup, new_ofgroup,
+                                               gm->command_bucket_id);
+    }
+    if (error) {
+        goto out;
+    }
+
     /* The group creation time does not change during modification. */
     *CONST_CAST(long long int *, &(new_ofgroup->created)) = ofgroup->created;
     *CONST_CAST(long long int *, &(new_ofgroup->modified)) = time_msec();
@@ -5916,6 +6012,18 @@ handle_group_mod(struct ofconn *ofconn, const struct ofp_header *oh)
         delete_group(ofproto, gm.group_id);
         return 0;
 
+    case OFPGC15_INSERT_BUCKET:
+        return modify_group(ofproto, &gm);
+
+    case OFPGC15_REMOVE_BUCKET:
+        if (!list_is_empty(&gm.buckets)) {
+            VLOG_WARN_RL(&rl, "%s: Buckets not permitted for group mod type "
+                         "OFPGC15_REMOVE_BUCKET (%d)",
+                         ofproto->name, OFPGC15_REMOVE_BUCKET);
+            return OFPERR_OFPGMFC_BAD_BUCKET;
+        }
+        return modify_group(ofproto, &gm);
+
     default:
         if (gm.command > OFPGC11_DELETE) {
             VLOG_WARN_RL(&rl, "%s: Invalid group_mod command type %d",
-- 
2.1.1




More information about the dev mailing list