Acked-by: Jarno Rajahalme <jrajaha...@nicira.com> On Aug 7, 2014, at 4:13 PM, Ben Pfaff <b...@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 <b...@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@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev