[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