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

Ben Pfaff blp at nicira.com
Mon Aug 11 19:48:40 UTC 2014


Thanks, applied to master.

On Mon, Aug 11, 2014 at 10:17:08AM -0700, Jarno Rajahalme wrote:
> 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