On Tue, Jul 28, 2015 at 10:05:07PM -0700, Ben Pfaff wrote:
> Until now, OVS has parsed all OF1.1+ group buckets that lack a weight
> as having weight 1.  Unfortunately, OpenFlow says that only "select"
> groups may have a nonzero weight, and requires reporting an error for
> other kinds of groups that have a nonzero weight.  This commit fixes
> the problem by parsing only select groups with a default weight of 1
> and other groups with a default weight of 0.  It also adds the
> OpenFlow-required check for nonzero weights for other kinds of groups.
> 
> This complies with OpenFlow 1.1 and later.  OF1.1 says in section 5.8:
> 
>     If a specified group type is invalid (ie: includes fields such as
>     weight that are undefined for the specified group type) then the
>     switch must refuse to add the group entry and must send an
>     ofp_error_msg with OFPET_GROUP_MOD_FAILED type and
>     OFPGMFC_INVALID_GROUP code.
> 
> Found by OFTest.
> 
> Signed-off-by: Ben Pfaff <b...@nicira.com>
> Acked-by: Flavio Leitner <f...@sysclose.org>

So, the default for "select" remains the same, but for others it's
now zero.  The change isn't a problem because for other kinds of
groups weight isn't defined, so it must return an error which is
included in this patch as well.

And with this patch: 1665 tests were successful.

Although my ack is above, ack again ;)
fbl



> ---
>  lib/ofp-parse.c | 78 
> ++++++++++++++++++++++++++++-----------------------------
>  lib/ofp-print.c |  2 +-
>  lib/ofp-util.c  | 13 +++++++---
>  3 files changed, 49 insertions(+), 44 deletions(-)
> 
> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
> index 8cdda50..ade664b 100644
> --- a/lib/ofp-parse.c
> +++ b/lib/ofp-parse.c
> @@ -1143,7 +1143,7 @@ exit:
>  }
>  
>  static char * OVS_WARN_UNUSED_RESULT
> -parse_bucket_str(struct ofputil_bucket *bucket, char *str_,
> +parse_bucket_str(struct ofputil_bucket *bucket, char *str_, uint8_t 
> group_type,
>                    enum ofputil_protocol *usable_protocols)
>  {
>      char *pos, *key, *value;
> @@ -1151,7 +1151,7 @@ parse_bucket_str(struct ofputil_bucket *bucket, char 
> *str_,
>      struct ds actions;
>      char *error;
>  
> -    bucket->weight = 1;
> +    bucket->weight = group_type == OFPGT11_SELECT ? 1 : 0;
>      bucket->bucket_id = OFPG15_BUCKET_ALL;
>      bucket->watch_port = OFPP_ANY;
>      bucket->watch_group = OFPG11_ANY;
> @@ -1333,40 +1333,19 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod 
> *gm, uint16_t command,
>  
>      *usable_protocols = OFPUTIL_P_OF11_UP;
>  
> -    if (fields & F_BUCKETS) {
> -        char *bkt_str = strstr(string, "bucket=");
> -
> -        if (bkt_str) {
> -            *bkt_str = '\0';
> -        }
> -
> -        while (bkt_str) {
> -            char *next_bkt_str;
> -
> -            bkt_str = strchr(bkt_str + 1, '=');
> -            if (!bkt_str) {
> -                error = xstrdup("must specify bucket content");
> -                goto out;
> -            }
> -            bkt_str++;
> -
> -            next_bkt_str = strstr(bkt_str, "bucket=");
> -            if (next_bkt_str) {
> -                *next_bkt_str = '\0';
> -            }
> -
> -            bucket = xzalloc(sizeof(struct ofputil_bucket));
> -            error = parse_bucket_str(bucket, bkt_str, usable_protocols);
> -            if (error) {
> -                free(bucket);
> -                goto out;
> -            }
> -            list_push_back(&gm->buckets, &bucket->list_node);
> -
> -            bkt_str = next_bkt_str;
> +    /* Strip the buckets off the end of 'string', if there are any, saving a
> +     * pointer for later.  We want to parse the buckets last because the 
> bucket
> +     * type influences bucket defaults. */
> +    char *bkt_str = strstr(string, "bucket=");
> +    if (bkt_str) {
> +        if (!(fields & F_BUCKETS)) {
> +            error = xstrdup("bucket is not needed");
> +            goto out;
>          }
> +        *bkt_str = '\0';
>      }
>  
> +    /* Parse everything before the buckets. */
>      for (name = strtok_r(string, "=, \t\r\n", &save_ptr); name;
>           name = strtok_r(NULL, "=, \t\r\n", &save_ptr)) {
>          char *value;
> @@ -1441,9 +1420,6 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod *gm, 
> uint16_t command,
>                  goto out;
>              }
>              had_type = true;
> -        } else if (!strcmp(name, "bucket")) {
> -            error = xstrdup("bucket is not needed");
> -            goto out;
>          } else if (!strcmp(name, "selection_method")) {
>              if (!(fields & F_GROUP_TYPE)) {
>                  error = xstrdup("selection method is not needed");
> @@ -1504,12 +1480,36 @@ parse_ofp_group_mod_str__(struct ofputil_group_mod 
> *gm, uint16_t command,
>          goto out;
>      }
>  
> -    /* Validate buckets. */
> -    LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
> -        if (bucket->weight != 1 && gm->type != OFPGT11_SELECT) {
> +    /* Now parse the buckets, if any. */
> +    while (bkt_str) {
> +        char *next_bkt_str;
> +
> +        bkt_str = strchr(bkt_str + 1, '=');
> +        if (!bkt_str) {
> +            error = xstrdup("must specify bucket content");
> +            goto out;
> +        }
> +        bkt_str++;
> +
> +        next_bkt_str = strstr(bkt_str, "bucket=");
> +        if (next_bkt_str) {
> +            *next_bkt_str = '\0';
> +        }
> +
> +        bucket = xzalloc(sizeof(struct ofputil_bucket));
> +        error = parse_bucket_str(bucket, bkt_str, gm->type, 
> usable_protocols);
> +        if (error) {
> +            free(bucket);
> +            goto out;
> +        }
> +        list_push_back(&gm->buckets, &bucket->list_node);
> +
> +        if (gm->type != OFPGT11_SELECT && bucket->weight) {
>              error = xstrdup("Only select groups can have bucket weights.");
>              goto out;
>          }
> +
> +        bkt_str = next_bkt_str;
>      }
>      if (gm->type == OFPGT11_INDIRECT && !list_is_short(&gm->buckets)) {
>          error = xstrdup("Indirect groups can have at most one bucket.");
> diff --git a/lib/ofp-print.c b/lib/ofp-print.c
> index 44f3115..b8088f3 100644
> --- a/lib/ofp-print.c
> +++ b/lib/ofp-print.c
> @@ -2376,7 +2376,7 @@ ofp_print_group(struct ds *s, uint32_t group_id, 
> uint8_t type,
>          ds_put_cstr(s, "bucket=");
>  
>          ofp_print_bucket_id(s, "bucket_id:", bucket->bucket_id, ofp_version);
> -        if (bucket->weight != 1) {
> +        if (bucket->weight != (type == OFPGT11_SELECT ? 1 : 0)) {
>              ds_put_format(s, "weight:%"PRIu16",", bucket->weight);
>          }
>          if (bucket->watch_port != OFPP_NONE) {
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 9996e84..0d476dc 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -7822,7 +7822,8 @@ parse_ofp15_group_bucket_prop_watch(const struct ofpbuf 
> *payload,
>  
>  static enum ofperr
>  ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t buckets_length,
> -                           enum ofp_version version, struct ovs_list 
> *buckets)
> +                           enum ofp_version version, uint8_t group_type,
> +                           struct ovs_list *buckets)
>  {
>      struct ofp15_bucket *ob;
>  
> @@ -7835,7 +7836,7 @@ ofputil_pull_ofp15_buckets(struct ofpbuf *msg, size_t 
> buckets_length,
>          size_t ob_len, actions_len, properties_len;
>          ovs_be32 watch_port = ofputil_port_to_ofp11(OFPP_ANY);
>          ovs_be32 watch_group = htonl(OFPG_ANY);
> -        ovs_be16 weight = htons(1);
> +        ovs_be16 weight = htons(group_type == OFPGT11_SELECT ? 1 : 0);
>  
>          ofpbuf_init(&ofpacts, 0);
>  
> @@ -8217,7 +8218,7 @@ ofputil_decode_ofp15_group_desc_reply(struct 
> ofputil_group_desc *gd,
>                       "bucket list length %u", bucket_list_len);
>          return OFPERR_OFPBRC_BAD_LEN;
>      }
> -    error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, version,
> +    error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, version, 
> gd->type,
>                                         &gd->buckets);
>      if (error) {
>          return error;
> @@ -8515,7 +8516,7 @@ ofputil_pull_ofp15_group_mod(struct ofpbuf *msg, enum 
> ofp_version ofp_version,
>  
>      bucket_list_len = ntohs(ogm->bucket_array_len);
>      error = ofputil_pull_ofp15_buckets(msg, bucket_list_len, ofp_version,
> -                                       &gm->buckets);
> +                                       gm->type, &gm->buckets);
>      if (error) {
>          return error;
>      }
> @@ -8592,6 +8593,10 @@ ofputil_decode_group_mod(const struct ofp_header *oh,
>      }
>  
>      LIST_FOR_EACH (bucket, list_node, &gm->buckets) {
> +        if (bucket->weight && gm->type != OFPGT11_SELECT) {
> +            return OFPERR_OFPGMFC_INVALID_GROUP;
> +        }
> +
>          switch (gm->type) {
>          case OFPGT11_ALL:
>          case OFPGT11_INDIRECT:
> -- 
> 2.1.3
> 
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to