[ovs-dev] [PATCH v2 13/16] ofp-actions: Pretend that OpenFlow 1.0 has instructions.

Jarno Rajahalme jrajahalme at nicira.com
Mon Aug 11 17:17:08 UTC 2014


Acked-by: Jarno Rajahalme <jrajahalme at nicira.com>

On Aug 7, 2014, at 4:13 PM, Ben Pfaff <blp at nicira.com> wrote:

> This allows callers to be more uniform, because they don't have to pick
> out whether they should parse actions or instructions based on the OpenFlow
> version in use.  It also allows the Write-Metadata instruction emulation
> in OpenFlow 1.0 to be treated just as in OpenFlow 1.1 in the sense that
> it is allowed in contexts where instructions are allowed in OpenFlow 1.1
> and not elsewhere.  (The changes in the tests reflect this more accurate
> treatment.)
> 
> Signed-off-by: Ben Pfaff <blp at nicira.com>
> ---
> lib/ofp-actions.c     |   84 +++++++++++++++++++++++-----------
> lib/ofp-actions.h     |    3 +-
> lib/ofp-errors.h      |    3 +-
> lib/ofp-parse.c       |    6 ++-
> lib/ofp-util.c        |   52 ++++++---------------
> tests/ofp-actions.at  |  122 ++++++++++++++++++++++++++++++-------------------
> utilities/ovs-ofctl.c |   33 ++++++++++---
> 7 files changed, 182 insertions(+), 121 deletions(-)
> 
> diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
> index edcf25f..fbd5b1f 100644
> --- a/lib/ofp-actions.c
> +++ b/lib/ofp-actions.c
> @@ -671,28 +671,13 @@ ofpacts_from_openflow(const union ofp_action *in, size_t n_in,
>     return 0;
> }
> 
> -/* Attempts to convert 'actions_len' bytes of OpenFlow actions from the
> - * front of 'openflow' into ofpacts.  On success, replaces any existing content
> - * in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
> - * Returns 0 if successful, otherwise an OpenFlow error.
> - *
> - * Actions are processed according to their OpenFlow version which
> - * is provided in the 'version' parameter.
> - *
> - * In most places in OpenFlow 1.1 and 1.2, actions appear encapsulated in
> - * instructions, so you should call ofpacts_pull_openflow_instructions()
> - * instead of this function.
> - *
> - * The parsed actions are valid generically, but they may not be valid in a
> - * specific context.  For example, port numbers up to OFPP_MAX are valid
> - * generically, but specific datapaths may only support port numbers in a
> - * smaller range.  Use ofpacts_check() to additional check whether actions are
> - * valid in a specific context. */
> -enum ofperr
> -ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
> -                              unsigned int actions_len,
> -                              enum ofp_version version,
> -                              struct ofpbuf *ofpacts) {
> +static enum ofperr
> +ofpacts_pull_openflow_actions__(struct ofpbuf *openflow,
> +                                unsigned int actions_len,
> +                                enum ofp_version version,
> +                                uint32_t allowed_ovsinsts,
> +                                struct ofpbuf *ofpacts)
> +{
>     const union ofp_action *actions;
>     enum ofperr error;
> 
> @@ -719,13 +704,41 @@ ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
>         return error;
>     }
> 
> -    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
> +    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
> +                           allowed_ovsinsts);
>     if (error) {
>         ofpbuf_clear(ofpacts);
>     }
>     return error;
> }
> 
> +/* Attempts to convert 'actions_len' bytes of OpenFlow actions from the
> + * front of 'openflow' into ofpacts.  On success, replaces any existing content
> + * in 'ofpacts' by the converted ofpacts; on failure, clears 'ofpacts'.
> + * Returns 0 if successful, otherwise an OpenFlow error.
> + *
> + * Actions are processed according to their OpenFlow version which
> + * is provided in the 'version' parameter.
> + *
> + * In most places in OpenFlow, actions appear encapsulated in instructions, so
> + * you should call ofpacts_pull_openflow_instructions() instead of this
> + * function.
> + *
> + * The parsed actions are valid generically, but they may not be valid in a
> + * specific context.  For example, port numbers up to OFPP_MAX are valid
> + * generically, but specific datapaths may only support port numbers in a
> + * smaller range.  Use ofpacts_check() to additional check whether actions are
> + * valid in a specific context. */
> +enum ofperr
> +ofpacts_pull_openflow_actions(struct ofpbuf *openflow,
> +                              unsigned int actions_len,
> +                              enum ofp_version version,
> +                              struct ofpbuf *ofpacts)
> +{
> +    return ofpacts_pull_openflow_actions__(openflow, actions_len, version,
> +                                           1u << OVSINST_OFPIT11_APPLY_ACTIONS,
> +                                           ofpacts);
> +}
> 
> /* OpenFlow 1.1 actions. */
> 
> @@ -1816,6 +1829,13 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
>     const struct ofp11_instruction *insts[N_OVS_INSTRUCTIONS];
>     enum ofperr error;
> 
> +    if (version == OFP10_VERSION) {
> +        return ofpacts_pull_openflow_actions__(openflow, instructions_len,
> +                                               version,
> +                                               (1u << N_OVS_INSTRUCTIONS) - 1,
> +                                               ofpacts);
> +    }
> +
>     ofpbuf_clear(ofpacts);
> 
>     if (instructions_len % OFP11_INSTRUCTION_ALIGN != 0) {
> @@ -1909,7 +1929,8 @@ ofpacts_pull_openflow_instructions(struct ofpbuf *openflow,
>         ogt->table_id = oigt->table_id;
>     }
> 
> -    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
> +    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
> +                           (1u << N_OVS_INSTRUCTIONS) - 1);
> exit:
>     if (error) {
>         ofpbuf_clear(ofpacts);
> @@ -2257,7 +2278,8 @@ ofpacts_check_consistency(struct ofpact ofpacts[], size_t ofpacts_len,
> /* Verifies that the 'ofpacts_len' bytes of actions in 'ofpacts' are
>  * in the appropriate order as defined by the OpenFlow spec. */
> enum ofperr
> -ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len)
> +ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len,
> +               uint32_t allowed_ovsinsts)
> {
>     const struct ofpact *a;
>     enum ovs_instruction_type inst;
> @@ -2284,6 +2306,12 @@ ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len)
>             }
>             return OFPERR_OFPBAC_UNSUPPORTED_ORDER;
>         }
> +        if (!((1u << next) & allowed_ovsinsts)) {
> +            const char *name = ovs_instruction_name_from_type(next);
> +
> +            VLOG_WARN("%s instruction not allowed here", name);
> +            return OFPERR_OFPBIC_UNSUP_INST;
> +        }
> 
>         inst = next;
>     }
> @@ -3077,7 +3105,11 @@ ofpacts_put_openflow_instructions(const struct ofpact ofpacts[],
> {
>     const struct ofpact *a;
> 
> -    ovs_assert(ofp_version >= OFP11_VERSION);
> +    if (ofp_version == OFP10_VERSION) {
> +        ofpacts_put_openflow_actions(ofpacts, ofpacts_len, openflow,
> +                                     ofp_version);
> +        return;
> +    }
> 
>     OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
>         switch (ovs_instruction_type_from_ofpact_type(a->type)) {
> diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
> index c215ffc..d23f399 100644
> --- a/lib/ofp-actions.h
> +++ b/lib/ofp-actions.h
> @@ -599,7 +599,8 @@ enum ofperr ofpacts_check_consistency(struct ofpact[], size_t ofpacts_len,
>                                       struct flow *, ofp_port_t max_ports,
>                                       uint8_t table_id, uint8_t n_tables,
>                                       enum ofputil_protocol usable_protocols);
> -enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len);
> +enum ofperr ofpacts_verify(const struct ofpact ofpacts[], size_t ofpacts_len,
> +                           uint32_t allowed_ovsinsts);
> enum ofperr ofpact_check_output_port(ofp_port_t port, ofp_port_t max_ports);
> 
> /* Converting ofpacts to OpenFlow. */
> diff --git a/lib/ofp-errors.h b/lib/ofp-errors.h
> index 563c75a..d5c767b 100644
> --- a/lib/ofp-errors.h
> +++ b/lib/ofp-errors.h
> @@ -233,7 +233,8 @@ enum ofperr {
>     /* OF1.1+(3,0).  Unknown instruction. */
>     OFPERR_OFPBIC_UNKNOWN_INST,
> 
> -    /* OF1.1+(3,1).  Switch or table does not support the instruction. */
> +    /* NX1.0(2,257), OF1.1+(3,1).  Switch or table does not support the
> +     * instruction. */
>     OFPERR_OFPBIC_UNSUP_INST,
> 
>     /* OF1.1+(3,2).  Invalid Table-ID specified. */
> diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
> index fa453de..b4da719 100644
> --- a/lib/ofp-parse.c
> +++ b/lib/ofp-parse.c
> @@ -1016,7 +1016,8 @@ str_to_ofpacts(char *str, struct ofpbuf *ofpacts,
>         return error_s;
>     }
> 
> -    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
> +    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
> +                           (1u << OVSINST_OFPIT11_APPLY_ACTIONS));
>     if (error) {
>         ofpbuf_set_size(ofpacts, orig_size);
>         return xstrdup("Incorrect action ordering");
> @@ -1095,7 +1096,8 @@ parse_named_instruction(enum ovs_instruction_type type,
> 
>     /* If write_metadata is specified as an action AND an instruction, ofpacts
>        could be invalid. */
> -    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts));
> +    error = ofpacts_verify(ofpbuf_data(ofpacts), ofpbuf_size(ofpacts),
> +                           (1u << N_OVS_INSTRUCTIONS) - 1);
>     if (error) {
>         return xstrdup("Incorrect instruction ordering");
>     }
> diff --git a/lib/ofp-util.c b/lib/ofp-util.c
> index 261220c..feb8f75 100644
> --- a/lib/ofp-util.c
> +++ b/lib/ofp-util.c
> @@ -1665,12 +1665,6 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
>             return error;
>         }
> 
> -        error = ofpacts_pull_openflow_instructions(&b, ofpbuf_size(&b), oh->version,
> -                                                   ofpacts);
> -        if (error) {
> -            return error;
> -        }
> -
>         /* Translate the message. */
>         fm->priority = ntohs(ofm->priority);
>         if (ofm->command == OFPFC_ADD
> @@ -1731,13 +1725,6 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
>             ofputil_match_from_ofp10_match(&ofm->match, &fm->match);
>             ofputil_normalize_match(&fm->match);
> 
> -            /* Now get the actions. */
> -            error = ofpacts_pull_openflow_actions(&b, ofpbuf_size(&b), oh->version,
> -                                                  ofpacts);
> -            if (error) {
> -                return error;
> -            }
> -
>             /* OpenFlow 1.0 says that exact-match rules have to have the
>              * highest possible priority. */
>             fm->priority = (ofm->match.wildcards & htonl(OFPFW10_ALL)
> @@ -1766,11 +1753,6 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
>             if (error) {
>                 return error;
>             }
> -            error = ofpacts_pull_openflow_actions(&b, ofpbuf_size(&b), oh->version,
> -                                                  ofpacts);
> -            if (error) {
> -                return error;
> -            }
> 
>             /* Translate the message. */
>             command = ntohs(nfm->command);
> @@ -1801,6 +1783,11 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
>         }
>     }
> 
> +    error = ofpacts_pull_openflow_instructions(&b, ofpbuf_size(&b),
> +                                               oh->version, ofpacts);
> +    if (error) {
> +        return error;
> +    }
>     fm->ofpacts = ofpbuf_data(ofpacts);
>     fm->ofpacts_len = ofpbuf_size(ofpacts);
> 
> @@ -2801,6 +2788,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>                                 struct ofpbuf *ofpacts)
> {
>     const struct ofp_header *oh;
> +    size_t instructions_len;
>     enum ofperr error;
>     enum ofpraw raw;
> 
> @@ -2838,13 +2826,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>             VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad match");
>             return EINVAL;
>         }
> -
> -        if (ofpacts_pull_openflow_instructions(msg, length - sizeof *ofs -
> -                                               padded_match_len, oh->version,
> -                                               ofpacts)) {
> -            VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
> -            return EINVAL;
> -        }
> +        instructions_len = length - sizeof *ofs - padded_match_len;
> 
>         fs->priority = ntohs(ofs->priority);
>         fs->table_id = ofs->table_id;
> @@ -2883,11 +2865,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>                          "length %"PRIuSIZE, length);
>             return EINVAL;
>         }
> -
> -        if (ofpacts_pull_openflow_actions(msg, length - sizeof *ofs,
> -                                          oh->version, ofpacts)) {
> -            return EINVAL;
> -        }
> +        instructions_len = length - sizeof *ofs;
> 
>         fs->cookie = get_32aligned_be64(&ofs->cookie);
>         ofputil_match_from_ofp10_match(&ofs->match, &fs->match);
> @@ -2904,7 +2882,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>         fs->flags = 0;
>     } else if (raw == OFPRAW_NXST_FLOW_REPLY) {
>         const struct nx_flow_stats *nfs;
> -        size_t match_len, actions_len, length;
> +        size_t match_len, length;
> 
>         nfs = ofpbuf_try_pull(msg, sizeof *nfs);
>         if (!nfs) {
> @@ -2923,12 +2901,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>         if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL)) {
>             return EINVAL;
>         }
> -
> -        actions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);
> -        if (ofpacts_pull_openflow_actions(msg, actions_len, oh->version,
> -                                          ofpacts)) {
> -            return EINVAL;
> -        }
> +        instructions_len = length - sizeof *nfs - ROUND_UP(match_len, 8);
> 
>         fs->cookie = nfs->cookie;
>         fs->table_id = nfs->table_id;
> @@ -2954,6 +2927,11 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
>         OVS_NOT_REACHED();
>     }
> 
> +    if (ofpacts_pull_openflow_instructions(msg, instructions_len, oh->version,
> +                                           ofpacts)) {
> +        VLOG_WARN_RL(&bad_ofmsg_rl, "OFPST_FLOW reply bad instructions");
> +        return EINVAL;
> +    }
>     fs->ofpacts = ofpbuf_data(ofpacts);
>     fs->ofpacts_len = ofpbuf_size(ofpacts);
> 
> diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
> index 4090ca3..7c22758 100644
> --- a/tests/ofp-actions.at
> +++ b/tests/ofp-actions.at
> @@ -69,10 +69,12 @@ ffff 0018 00002320 0009 000000000000 c426384d49c53d60
> # actions=set_tunnel64:0x885f3298
> ffff 0018 00002320 0009 000000000000 00000000885f3298
> 
> -# actions=write_metadata:0xfedcba9876543210
> +# bad OF1.0 actions: OFPBIC_UNSUP_INST
> +& ofp_actions|WARN|write_metadata instruction not allowed here
> ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
> 
> -# actions=write_metadata:0xfedcba9876543210/0xffff0000ffff0000
> +# bad OF1.0 actions: OFPBIC_UNSUP_INST
> +& ofp_actions|WARN|write_metadata instruction not allowed here
> ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffff0000ffff0000
> 
> # actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
> @@ -129,6 +131,36 @@ AT_CHECK(
>   [0], [expout], [experr])
> AT_CLEANUP
> 
> +AT_SETUP([OpenFlow 1.0 "instruction" translations])
> +AT_KEYWORDS([ofp-actions OF1.0 instruction])
> +AT_DATA([test-data], [dnl
> +dnl Try a couple of ordinary actions to make sure they're accepted,
> +dnl but there's no point in retrying all the actions from the previous test.
> +# actions=LOCAL
> +0000 0008 fffe 04d2
> +
> +# actions=mod_dl_src:00:11:22:33:44:55
> +0004 0010 001122334455 000000000000
> +
> +dnl Now check that write_metadata is accepted.
> +# actions=write_metadata:0xfedcba9876543210
> +ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
> +
> +# actions=write_metadata:0xfedcba9876543210/0xffff0000ffff0000
> +ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffff0000ffff0000
> +
> +])
> +sed '/^[[#&]]/d' < test-data > input.txt
> +sed -n 's/^# //p; /^$/p' < test-data > expout
> +sed -n 's/^& //p' < test-data > experr
> +AT_CAPTURE_FILE([input.txt])
> +AT_CAPTURE_FILE([expout])
> +AT_CAPTURE_FILE([experr])
> +AT_CHECK(
> +  [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-ofp10-instructions < input.txt],
> +  [0], [expout], [experr])
> +AT_CLEANUP
> +
> AT_SETUP([OpenFlow 1.1 action translation])
> AT_KEYWORDS([ofp-actions OF1.1])
> AT_DATA([test-data], [dnl
> @@ -201,53 +233,11 @@ ffff 0018 00002320 0009 000000000000 c426384d49c53d60
> # actions=set_tunnel64:0x885f3298
> ffff 0018 00002320 0009 000000000000 00000000885f3298
> 
> -dnl OpenFlow 1.1 uses OFPIT_WRITE_METADATA to express the NXAST_WRITE_METADATA
> -dnl action instead, so parse-ofp11-actions will recognise and drop this action.
> -# actions=write_metadata:0xfedcba9876543210
> -#  0: ff -> (none)
> -#  1: ff -> (none)
> -#  2: 00 -> (none)
> -#  3: 20 -> (none)
> -#  4: 00 -> (none)
> -#  5: 00 -> (none)
> -#  6: 23 -> (none)
> -#  7: 20 -> (none)
> -#  8: 00 -> (none)
> -#  9: 16 -> (none)
> -# 10: 00 -> (none)
> -# 11: 00 -> (none)
> -# 12: 00 -> (none)
> -# 13: 00 -> (none)
> -# 14: 00 -> (none)
> -# 15: 00 -> (none)
> -# 16: fe -> (none)
> -# 17: dc -> (none)
> -# 18: ba -> (none)
> -# 19: 98 -> (none)
> -# 20: 76 -> (none)
> -# 21: 54 -> (none)
> -# 22: 32 -> (none)
> -# 23: 10 -> (none)
> -# 24: ff -> (none)
> -# 25: ff -> (none)
> -# 26: ff -> (none)
> -# 27: ff -> (none)
> -# 28: ff -> (none)
> -# 29: ff -> (none)
> -# 30: ff -> (none)
> -# 31: ff -> (none)
> +dnl Write-Metadata is only allowed in contexts that allow instructions.
> +& ofp_actions|WARN|write_metadata instruction not allowed here
> +# bad OF1.1 actions: OFPBIC_UNSUP_INST
> ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
> 
> -dnl Write-Metadata duplicated.
> -& ofp_actions|WARN|duplicate write_metadata instruction not allowed, for OpenFlow 1.1+ compatibility
> -# bad OF1.1 actions: OFPBAC_UNSUPPORTED_ORDER
> -ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
> -
> -dnl Write-Metadata in wrong position.
> -& ofp_actions|WARN|invalid instruction ordering: apply_actions must appear before write_metadata, for OpenFlow 1.1+ compatibility
> -# bad OF1.1 actions: OFPBAC_UNSUPPORTED_ORDER
> -ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff ffff 0010 00002320 0002 0000 12345678
> -
> # actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[])
> ffff 0020 00002320 000a 0000 0032 0000 0000 0000 0000 0000 0000 001f 00010004
> 
> @@ -368,6 +358,44 @@ dnl Write-Metadata.
> # actions=write_metadata:0xfedcba9876543210
> 0002 0018 00000000 fedcba9876543210 ffffffffffffffff
> 
> +dnl Write-Metadata as Nicira extension action is transformed into instruction.
> +# actions=write_metadata:0xfedcba9876543210
> +#  1: 04 -> 02
> +#  3: 28 -> 18
> +#  8: ff -> fe
> +#  9: ff -> dc
> +# 10: 00 -> ba
> +# 11: 20 -> 98
> +# 12: 00 -> 76
> +# 13: 00 -> 54
> +# 14: 23 -> 32
> +# 15: 20 -> 10
> +# 16: 00 -> ff
> +# 17: 16 -> ff
> +# 18: 00 -> ff
> +# 19: 00 -> ff
> +# 20: 00 -> ff
> +# 21: 00 -> ff
> +# 22: 00 -> ff
> +# 23: 00 -> ff
> +# 24: fe -> (none)
> +# 25: dc -> (none)
> +# 26: ba -> (none)
> +# 27: 98 -> (none)
> +# 28: 76 -> (none)
> +# 29: 54 -> (none)
> +# 30: 32 -> (none)
> +# 31: 10 -> (none)
> +# 32: ff -> (none)
> +# 33: ff -> (none)
> +# 34: ff -> (none)
> +# 35: ff -> (none)
> +# 36: ff -> (none)
> +# 37: ff -> (none)
> +# 38: ff -> (none)
> +# 39: ff -> (none)
> +0004 0028 00000000 ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff
> +
> dnl Write-Metadata with mask.
> # actions=write_metadata:0xfedcba9876543210/0xff00ff00ff00ff00
> 0002 0018 00000000 fedcba9876543210 ff00ff00ff00ff00
> diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
> index 4dc547d..6235462 100644
> --- a/utilities/ovs-ofctl.c
> +++ b/utilities/ovs-ofctl.c
> @@ -2935,12 +2935,8 @@ print_differences(const char *prefix,
>     }
> }
> 
> -/* "parse-ofp10-actions": reads a series of OpenFlow 1.0 action specifications
> - * as hex bytes from stdin, converts them to ofpacts, prints them as strings
> - * on stdout, and then converts them back to hex bytes and prints any
> - * differences from the input. */
> static void
> -ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
> +ofctl_parse_ofp10_actions__(bool instructions)
> {
>     struct ds in;
> 
> @@ -2962,8 +2958,10 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
>         /* Convert to ofpacts. */
>         ofpbuf_init(&ofpacts, 0);
>         size = ofpbuf_size(&of10_in);
> -        error = ofpacts_pull_openflow_actions(&of10_in, ofpbuf_size(&of10_in),
> -                                              OFP10_VERSION, &ofpacts);
> +        error = (instructions
> +                 ? ofpacts_pull_openflow_instructions
> +                 : ofpacts_pull_openflow_actions)(
> +                     &of10_in, ofpbuf_size(&of10_in), OFP10_VERSION, &ofpacts);
>         if (error) {
>             printf("bad OF1.0 actions: %s\n\n", ofperr_get_name(error));
>             ofpbuf_uninit(&ofpacts);
> @@ -2995,6 +2993,26 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
>     ds_destroy(&in);
> }
> 
> +/* "parse-ofp10-actions": reads a series of OpenFlow 1.0 action specifications
> + * as hex bytes from stdin, converts them to ofpacts, prints them as strings
> + * on stdout, and then converts them back to hex bytes and prints any
> + * differences from the input. */
> +static void
> +ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
> +{
> +    ofctl_parse_ofp10_actions__(false);
> +}
> +
> +/* "parse-ofp10-instructions": reads a series of OpenFlow 1.0 action
> + * specifications as hex bytes from stdin, converts them to ofpacts, prints
> + * them as strings on stdout, and then converts them back to hex bytes and
> + * prints any differences from the input. */
> +static void
> +ofctl_parse_ofp10_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
> +{
> +    ofctl_parse_ofp10_actions__(true);
> +}
> +
> /* "parse-ofp10-match": reads a series of ofp10_match specifications as hex
>  * bytes from stdin, converts them to cls_rules, prints them as strings on
>  * stdout, and then converts them back to hex bytes and prints any differences
> @@ -3570,6 +3588,7 @@ static const struct command all_commands[] = {
>     { "parse-nxm", 0, 0, ofctl_parse_nxm },
>     { "parse-oxm", 1, 1, ofctl_parse_oxm },
>     { "parse-ofp10-actions", 0, 0, ofctl_parse_ofp10_actions },
> +    { "parse-ofp10-instructions", 0, 0, ofctl_parse_ofp10_instructions },
>     { "parse-ofp10-match", 0, 0, ofctl_parse_ofp10_match },
>     { "parse-ofp11-match", 0, 0, ofctl_parse_ofp11_match },
>     { "parse-ofp11-actions", 0, 0, ofctl_parse_ofp11_actions },
> -- 
> 1.7.10.4
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev




More information about the dev mailing list