[ovs-dev] [learning v2 06/19] ofp-util: New function for parsing key-value pairs.

Ethan Jackson ethan at nicira.com
Wed Sep 7 14:12:12 PDT 2011


Looks good.

Ethan

On Fri, Aug 19, 2011 at 15:28, Ben Pfaff <blp at nicira.com> wrote:
> This will soon have a new user, but it's a worthwhile cleanup on its own.
> ---
>  lib/ofp-parse.c |   63 ++++---------------------------------------------
>  lib/ofp-util.c  |   69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  lib/ofp-util.h  |    3 ++
>  3 files changed, 78 insertions(+), 57 deletions(-)
>
> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
> index 7e38565..77d3f19 100644
> --- a/lib/ofp-parse.c
> +++ b/lib/ofp-parse.c
> @@ -495,80 +495,29 @@ parse_named_action(enum ofputil_action_code code, struct ofpbuf *b, char *arg)
>  static void
>  str_to_action(char *str, struct ofpbuf *b)
>  {
> -    bool drop = false;
> +    char *pos, *act, *arg;
>     int n_actions;
> -    char *pos;
>
>     pos = str;
>     n_actions = 0;
> -    for (;;) {
> -        char empty_string[] = "";
> -        char *act, *arg;
> -        size_t actlen;
> +    while (ofputil_parse_key_value(&pos, &act, &arg)) {
>         uint16_t port;
>         int code;
>
> -        pos += strspn(pos, ", \t\r\n");
> -        if (*pos == '\0') {
> -            break;
> -        }
> -
> -        if (drop) {
> -            ovs_fatal(0, "Drop actions must not be followed by other actions");
> -        }
> -
> -        act = pos;
> -        actlen = strcspn(pos, ":(, \t\r\n");
> -        if (act[actlen] == ':') {
> -            /* The argument can be separated by a colon. */
> -            size_t arglen;
> -
> -            arg = act + actlen + 1;
> -            arglen = strcspn(arg, ", \t\r\n");
> -            pos = arg + arglen + (arg[arglen] != '\0');
> -            arg[arglen] = '\0';
> -        } else if (act[actlen] == '(') {
> -            /* The argument can be surrounded by balanced parentheses.  The
> -             * outermost set of parentheses is removed. */
> -            int level = 1;
> -            size_t arglen;
> -
> -            arg = act + actlen + 1;
> -            for (arglen = 0; level > 0; arglen++) {
> -                switch (arg[arglen]) {
> -                case '\0':
> -                    ovs_fatal(0, "unbalanced parentheses in argument to %s "
> -                              "action", act);
> -
> -                case '(':
> -                    level++;
> -                    break;
> -
> -                case ')':
> -                    level--;
> -                    break;
> -                }
> -            }
> -            arg[arglen - 1] = '\0';
> -            pos = arg + arglen;
> -        } else {
> -            /* There might be no argument at all. */
> -            arg = empty_string;
> -            pos = act + actlen + (act[actlen] != '\0');
> -        }
> -        act[actlen] = '\0';
> -
>         code = ofputil_action_code_from_name(act);
>         if (code >= 0) {
>             parse_named_action(code, b, arg);
>         } else if (!strcasecmp(act, "drop")) {
>             /* A drop action in OpenFlow occurs by just not setting
>              * an action. */
> -            drop = true;
>             if (n_actions) {
>                 ovs_fatal(0, "Drop actions must not be preceded by other "
>                           "actions");
> +            } else if (ofputil_parse_key_value(&pos, &act, &arg)) {
> +                ovs_fatal(0, "Drop actions must not be followed by other "
> +                          "actions");
>             }
> +            break;
>         } else if (!strcasecmp(act, "CONTROLLER")) {
>             struct ofp_action_output *oao;
>             oao = put_output_action(b, OFPP_CONTROLLER);
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 5cc1d40..a97a0e3 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -2735,3 +2735,72 @@ ofputil_actions_clone(const union ofp_action *actions, size_t n)
>  {
>     return n ? xmemdup(actions, n * sizeof *actions) : NULL;
>  }
> +
> +/* Parses a key or a key-value pair from '*stringp'.
> + *
> + * On success: Stores the key into '*keyp'.  Stores the value, if present, into
> + * '*valuep', otherwise an empty string.  Advances '*stringp' past the end of
> + * the key-value pair, preparing it for another call.  '*keyp' and '*valuep'
> + * are substrings of '*stringp' created by replacing some of its bytes by null
> + * terminators.  Returns true.
> + *
> + * If '*stringp' is just white space or commas, sets '*keyp' and '*valuep' to
> + * NULL and returns false. */
> +bool
> +ofputil_parse_key_value(char **stringp, char **keyp, char **valuep)
> +{
> +    char *pos, *key, *value;
> +    size_t key_len;
> +
> +    pos = *stringp;
> +    pos += strspn(pos, ", \t\r\n");
> +    if (*pos == '\0') {
> +        *keyp = *valuep = NULL;
> +        return false;
> +    }
> +
> +    key = pos;
> +    key_len = strcspn(pos, ":=(, \t\r\n");
> +    if (key[key_len] == ':' || key[key_len] == '=') {
> +        /* The value can be separated by a colon. */
> +        size_t value_len;
> +
> +        value = key + key_len + 1;
> +        value_len = strcspn(value, ", \t\r\n");
> +        pos = value + value_len + (value[value_len] != '\0');
> +        value[value_len] = '\0';
> +    } else if (key[key_len] == '(') {
> +        /* The value can be surrounded by balanced parentheses.  The outermost
> +         * set of parentheses is removed. */
> +        int level = 1;
> +        size_t value_len;
> +
> +        value = key + key_len + 1;
> +        for (value_len = 0; level > 0; value_len++) {
> +            switch (value[value_len]) {
> +            case '\0':
> +                ovs_fatal(0, "unbalanced parentheses in argument to %s", key);
> +
> +            case '(':
> +                level++;
> +                break;
> +
> +            case ')':
> +                level--;
> +                break;
> +            }
> +        }
> +        value[value_len - 1] = '\0';
> +        pos = value + value_len;
> +    } else {
> +        /* There might be no value at all. */
> +        value = key + key_len;  /* Will become the empty string below. */
> +        pos = key + key_len + (key[key_len] != '\0');
> +    }
> +    key[key_len] = '\0';
> +
> +    *stringp = pos;
> +    *keyp = key;
> +    *valuep = value;
> +    return true;
> +}
> diff --git a/lib/ofp-util.h b/lib/ofp-util.h
> index a658df1..ecd77cc 100644
> --- a/lib/ofp-util.h
> +++ b/lib/ofp-util.h
> @@ -547,4 +547,7 @@ int ofputil_decode_error_msg(const struct ofp_header *, size_t *payload_ofs);
>  void ofputil_format_error(struct ds *, int error);
>  char *ofputil_error_to_string(int error);
>
> +/* Handy utility for parsing flows and actions. */
> +bool ofputil_parse_key_value(char **stringp, char **keyp, char **valuep);
> +
>  #endif /* ofp-util.h */
> --
> 1.7.4.4
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>



More information about the dev mailing list