Handle (draft) OpenFlow 1.5 insert and remove group commands of group mod messages.
ONF-JIRA: EXT-350 Signed-off-by: Simon Horman <simon.hor...@netronome.com> --- v3 * No change 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 947969c..aa6ed87 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -5795,7 +5795,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 @@ -5827,6 +5911,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(); @@ -5932,6 +6028,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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev