Acked-by: Jarno Rajahalme <jrajaha...@nicira.com> On Aug 7, 2014, at 4:14 PM, Ben Pfaff <b...@nicira.com> wrote:
> Until now, there were four of these commands: parse-ofp10-actions, > parse-ofp10-instructions, parse-ofp11-actions, parse-ofp11-instructions. > This is painful to add support for new OpenFlow versions and has a ton of > cut-and-paste code. This commit generalizes the code to improve on both > of those points. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > tests/ofp-actions.at | 34 +++---- > utilities/ovs-ofctl.c | 242 ++++++++++++++----------------------------------- > 2 files changed, 86 insertions(+), 190 deletions(-) > > diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at > index 73b7dc6..9c6f228 100644 > --- a/tests/ofp-actions.at > +++ b/tests/ofp-actions.at > @@ -69,11 +69,11 @@ ffff 0018 00002320 0009 000000000000 c426384d49c53d60 > # actions=set_tunnel64:0x885f3298 > ffff 0018 00002320 0009 000000000000 00000000885f3298 > > -# bad OF1.0 actions: OFPBIC_UNSUP_INST > +# bad OpenFlow10 actions: OFPBIC_UNSUP_INST > & ofp_actions|WARN|write_metadata instruction not allowed here > ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff > > -# bad OF1.0 actions: OFPBIC_UNSUP_INST > +# bad OpenFlow10 actions: OFPBIC_UNSUP_INST > & ofp_actions|WARN|write_metadata instruction not allowed here > ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffff0000ffff0000 > > @@ -127,7 +127,7 @@ AT_CAPTURE_FILE([input.txt]) > AT_CAPTURE_FILE([expout]) > AT_CAPTURE_FILE([experr]) > AT_CHECK( > - [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-ofp10-actions < input.txt], > + [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-actions OpenFlow10 < > input.txt], > [0], [expout], [experr]) > AT_CLEANUP > > @@ -157,7 +157,7 @@ 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], > + [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-instructions OpenFlow10 < > input.txt], > [0], [expout], [experr]) > AT_CLEANUP > > @@ -235,7 +235,7 @@ ffff 0018 00002320 0009 000000000000 00000000885f3298 > > 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 > +# bad OpenFlow11 actions: OFPBIC_UNSUP_INST > ffff 0020 00002320 0016 000000000000 fedcba9876543210 ffffffffffffffff > > # actions=multipath(eth_src,50,modulo_n,1,0,NXM_NX_REG0[]) > @@ -289,7 +289,7 @@ AT_CAPTURE_FILE([input.txt]) > AT_CAPTURE_FILE([expout]) > AT_CAPTURE_FILE([experr]) > AT_CHECK( > - [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-ofp11-actions < input.txt], > + [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-actions OpenFlow11 < > input.txt], > [0], [expout], [experr]) > AT_CLEANUP > > @@ -325,16 +325,16 @@ dnl Check that an empty Apply-Actions instruction gets > dropped. > 0004 0008 00000000 > > dnl Duplicate instruction type: > -# bad OF1.1 instructions: OFPBIC_DUP_INST > +# bad OpenFlow11 instructions: OFPBIC_DUP_INST > 0004 0008 00000000 0004 0008 00000000 > > dnl Instructions not multiple of 8 in length. > & ofp_actions|WARN|OpenFlow message instructions length 9 is not a multiple > of 8 > -# bad OF1.1 instructions: OFPBIC_BAD_LEN > +# bad OpenFlow11 instructions: OFPBIC_BAD_LEN > 0004 0009 01 00000000 > > dnl Goto-Table instruction too long. > -# bad OF1.1 instructions: OFPBIC_BAD_LEN > +# bad OpenFlow11 instructions: OFPBIC_BAD_LEN > 0001 0010 01 000000 0000000000000000 > > dnl Goto-Table 1 instruction non-zero padding > @@ -343,7 +343,7 @@ dnl Goto-Table 1 instruction non-zero padding > 0001 0008 01 000001 > > dnl Goto-Table 1 instruction go back to the previous table. > -# bad OF1.1 instructions: OFPBRC_BAD_TABLE_ID > +# bad OpenFlow11 instructions: OFPBRC_BAD_TABLE_ID > 2,0001 0008 01 000000 > > dnl Goto-Table 1 > @@ -397,15 +397,15 @@ dnl Write-Metadata with mask. > 0002 0018 00000000 fedcba9876543210 ff00ff00ff00ff00 > > dnl Write-Metadata too short. > -# bad OF1.1 instructions: OFPBIC_BAD_LEN > +# bad OpenFlow11 instructions: OFPBIC_BAD_LEN > 0002 0010 00000000 fedcba9876543210 > > dnl Write-Metadata too long. > -# bad OF1.1 instructions: OFPBIC_BAD_LEN > +# bad OpenFlow11 instructions: OFPBIC_BAD_LEN > 0002 0020 00000000 fedcba9876543210 ffffffffffffffff 0000000000000000 > > dnl Write-Metadata duplicated. > -# bad OF1.1 instructions: OFPBIC_DUP_INST > +# bad OpenFlow11 instructions: OFPBIC_DUP_INST > 0002 0018 00000000 fedcba9876543210 ff00ff00ff00ff00 0002 0018 00000000 > fedcba9876543210 ff00ff00ff00ff00 > > dnl Write-Metadata in wrong position (OpenFlow 1.1+ disregards the order > @@ -465,7 +465,7 @@ dnl Check that an empty Write-Actions instruction gets > dropped. > 0003 0008 00000000 > > dnl Clear-Actions too-long > -# bad OF1.1 instructions: OFPBIC_BAD_LEN > +# bad OpenFlow11 instructions: OFPBIC_BAD_LEN > 0005 0010 00000000 0000000000000000 > > dnl Clear-Actions non-zero padding > @@ -483,11 +483,11 @@ dnl Clear-Actions > 0005 0008 00000000 > > dnl Experimenter actions not supported yet. > -# bad OF1.1 instructions: OFPBIC_BAD_EXPERIMENTER > +# bad OpenFlow11 instructions: OFPBIC_BAD_EXPERIMENTER > ffff 0008 01 000000 > > dnl Bad instruction number (0 not assigned). > -# bad OF1.1 instructions: OFPBIC_UNKNOWN_INST > +# bad OpenFlow11 instructions: OFPBIC_UNKNOWN_INST > 0000 0008 01 000000 > > ]) > @@ -498,7 +498,7 @@ AT_CAPTURE_FILE([input.txt]) > AT_CAPTURE_FILE([expout]) > AT_CAPTURE_FILE([experr]) > AT_CHECK( > - [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-ofp11-instructions < > input.txt], > + [ovs-ofctl '-vPATTERN:console:%c|%p|%m' parse-instructions OpenFlow11 < > input.txt], > [0], [expout], [experr]) > AT_CLEANUP > > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > index c05197a..cd8f840 100644 > --- a/utilities/ovs-ofctl.c > +++ b/utilities/ovs-ofctl.c > @@ -2936,39 +2936,70 @@ print_differences(const char *prefix, > } > > static void > -ofctl_parse_ofp10_actions__(bool instructions) > +ofctl_parse_actions__(const char *version_s, bool instructions) > { > + enum ofp_version version; > struct ds in; > > + version = ofputil_version_from_string(version_s); > + if (!version) { > + ovs_fatal(0, "%s: not a valid OpenFlow version", version_s); > + } > + > ds_init(&in); > while (!ds_get_preprocessed_line(&in, stdin, NULL)) { > - struct ofpbuf of10_out; > - struct ofpbuf of10_in; > + struct ofpbuf of_out; > + struct ofpbuf of_in; > struct ofpbuf ofpacts; > + const char *table_id; > + char *actions; > enum ofperr error; > size_t size; > struct ds s; > > + /* Parse table_id separated with the follow-up actions by ",", if > + * any. */ > + actions = ds_cstr(&in); > + table_id = NULL; > + if (strstr(actions, ",")) { > + table_id = strsep(&actions, ","); > + } > + > /* Parse hex bytes. */ > - ofpbuf_init(&of10_in, 0); > - if (ofpbuf_put_hex(&of10_in, ds_cstr(&in), NULL)[0] != '\0') { > + ofpbuf_init(&of_in, 0); > + if (ofpbuf_put_hex(&of_in, actions, NULL)[0] != '\0') { > ovs_fatal(0, "Trailing garbage in hex data"); > } > > /* Convert to ofpacts. */ > ofpbuf_init(&ofpacts, 0); > - size = ofpbuf_size(&of10_in); > + size = ofpbuf_size(&of_in); > error = (instructions > ? ofpacts_pull_openflow_instructions > : ofpacts_pull_openflow_actions)( > - &of10_in, ofpbuf_size(&of10_in), OFP10_VERSION, > &ofpacts); > + &of_in, ofpbuf_size(&of_in), version, &ofpacts); > + if (!error && instructions) { > + /* Verify actions, enforce consistency. */ > + enum ofputil_protocol protocol; > + struct flow flow; > + > + memset(&flow, 0, sizeof flow); > + protocol = ofputil_protocols_from_ofp_version(version); > + error = ofpacts_check_consistency(ofpbuf_data(&ofpacts), > + ofpbuf_size(&ofpacts), > + &flow, OFPP_MAX, > + table_id ? atoi(table_id) : 0, > + 255, protocol); > + } > if (error) { > - printf("bad OF1.0 actions: %s\n\n", ofperr_get_name(error)); > + printf("bad %s %s: %s\n\n", > + version_s, instructions ? "instructions" : "actions", > + ofperr_get_name(error)); > ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of10_in); > + ofpbuf_uninit(&of_in); > continue; > } > - ofpbuf_push_uninit(&of10_in, size); > + ofpbuf_push_uninit(&of_in, size); > > /* Print cls_rule. */ > ds_init(&s); > @@ -2978,39 +3009,46 @@ ofctl_parse_ofp10_actions__(bool instructions) > ds_destroy(&s); > > /* Convert back to ofp10 actions and print differences from input. */ > - ofpbuf_init(&of10_out, 0); > - ofpacts_put_openflow_actions(ofpbuf_data(&ofpacts), > ofpbuf_size(&ofpacts), &of10_out, > - OFP10_VERSION); > + ofpbuf_init(&of_out, 0); > + if (instructions) { > + ofpacts_put_openflow_instructions( ofpbuf_data(&ofpacts), > + ofpbuf_size(&ofpacts), > + &of_out, version); > + } else { > + ofpacts_put_openflow_actions( ofpbuf_data(&ofpacts), > + ofpbuf_size(&ofpacts), > + &of_out, version); > + } > > - print_differences("", ofpbuf_data(&of10_in), ofpbuf_size(&of10_in), > - ofpbuf_data(&of10_out), ofpbuf_size(&of10_out)); > + print_differences("", ofpbuf_data(&of_in), ofpbuf_size(&of_in), > + ofpbuf_data(&of_out), ofpbuf_size(&of_out)); > putchar('\n'); > > ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of10_in); > - ofpbuf_uninit(&of10_out); > + ofpbuf_uninit(&of_in); > + ofpbuf_uninit(&of_out); > } > 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. */ > +/* "parse-actions VERSION": reads a series of action specifications for the > + * given OpenFlow VERSION 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_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) > { > - ofctl_parse_ofp10_actions__(false); > + ofctl_parse_actions__(argv[1], 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. */ > +/* "parse-actions VERSION": reads a series of instruction specifications for > + * the given OpenFlow VERSION 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_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) > { > - ofctl_parse_ofp10_actions__(true); > + ofctl_parse_actions__(argv[1], true); > } > > /* "parse-ofp10-match": reads a series of ofp10_match specifications as hex > @@ -3141,146 +3179,6 @@ ofctl_parse_ofp11_match(int argc OVS_UNUSED, char > *argv[] OVS_UNUSED) > ds_destroy(&in); > } > > -/* "parse-ofp11-actions": reads a series of OpenFlow 1.1 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_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) > -{ > - struct ds in; > - > - ds_init(&in); > - while (!ds_get_preprocessed_line(&in, stdin, NULL)) { > - struct ofpbuf of11_out; > - struct ofpbuf of11_in; > - struct ofpbuf ofpacts; > - enum ofperr error; > - size_t size; > - struct ds s; > - > - /* Parse hex bytes. */ > - ofpbuf_init(&of11_in, 0); > - if (ofpbuf_put_hex(&of11_in, ds_cstr(&in), NULL)[0] != '\0') { > - ovs_fatal(0, "Trailing garbage in hex data"); > - } > - > - /* Convert to ofpacts. */ > - ofpbuf_init(&ofpacts, 0); > - size = ofpbuf_size(&of11_in); > - error = ofpacts_pull_openflow_actions(&of11_in, > ofpbuf_size(&of11_in), > - OFP11_VERSION, &ofpacts); > - if (error) { > - printf("bad OF1.1 actions: %s\n\n", ofperr_get_name(error)); > - ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of11_in); > - continue; > - } > - ofpbuf_push_uninit(&of11_in, size); > - > - /* Print cls_rule. */ > - ds_init(&s); > - ds_put_cstr(&s, "actions="); > - ofpacts_format(ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts), &s); > - puts(ds_cstr(&s)); > - ds_destroy(&s); > - > - /* Convert back to ofp11 actions and print differences from input. */ > - ofpbuf_init(&of11_out, 0); > - ofpacts_put_openflow_actions(ofpbuf_data(&ofpacts), > ofpbuf_size(&ofpacts), &of11_out, > - OFP11_VERSION); > - > - print_differences("", ofpbuf_data(&of11_in), ofpbuf_size(&of11_in), > - ofpbuf_data(&of11_out), ofpbuf_size(&of11_out)); > - putchar('\n'); > - > - ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of11_in); > - ofpbuf_uninit(&of11_out); > - } > - ds_destroy(&in); > -} > - > -/* "parse-ofp11-instructions": reads a series of OpenFlow 1.1 instruction > - * 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_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) > -{ > - struct ds in; > - > - ds_init(&in); > - while (!ds_get_preprocessed_line(&in, stdin, NULL)) { > - struct ofpbuf of11_out; > - struct ofpbuf of11_in; > - struct ofpbuf ofpacts; > - enum ofperr error; > - size_t size; > - struct ds s; > - const char *table_id; > - char *instructions; > - > - /* Parse table_id separated with the follow-up instructions by ",", > if > - * any. */ > - instructions = ds_cstr(&in); > - table_id = NULL; > - if (strstr(instructions, ",")) { > - table_id = strsep(&instructions, ","); > - } > - > - /* Parse hex bytes. */ > - ofpbuf_init(&of11_in, 0); > - if (ofpbuf_put_hex(&of11_in, instructions, NULL)[0] != '\0') { > - ovs_fatal(0, "Trailing garbage in hex data"); > - } > - > - /* Convert to ofpacts. */ > - ofpbuf_init(&ofpacts, 0); > - size = ofpbuf_size(&of11_in); > - error = ofpacts_pull_openflow_instructions(&of11_in, > ofpbuf_size(&of11_in), > - OFP11_VERSION, &ofpacts); > - if (!error) { > - /* Verify actions, enforce consistency. */ > - struct flow flow; > - memset(&flow, 0, sizeof flow); > - error = ofpacts_check_consistency(ofpbuf_data(&ofpacts), > ofpbuf_size(&ofpacts), > - &flow, OFPP_MAX, > - table_id ? atoi(table_id) : 0, > - 255, OFPUTIL_P_OF11_STD); > - } > - if (error) { > - printf("bad OF1.1 instructions: %s\n\n", ofperr_get_name(error)); > - ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of11_in); > - continue; > - } > - ofpbuf_push_uninit(&of11_in, size); > - > - /* Print cls_rule. */ > - ds_init(&s); > - ds_put_cstr(&s, "actions="); > - ofpacts_format(ofpbuf_data(&ofpacts), ofpbuf_size(&ofpacts), &s); > - puts(ds_cstr(&s)); > - ds_destroy(&s); > - > - /* Convert back to ofp11 instructions and print differences from > - * input. */ > - ofpbuf_init(&of11_out, 0); > - ofpacts_put_openflow_instructions(ofpbuf_data(&ofpacts), > ofpbuf_size(&ofpacts), > - &of11_out, OFP13_VERSION); > - > - print_differences("", ofpbuf_data(&of11_in), ofpbuf_size(&of11_in), > - ofpbuf_data(&of11_out), ofpbuf_size(&of11_out)); > - putchar('\n'); > - > - ofpbuf_uninit(&ofpacts); > - ofpbuf_uninit(&of11_in); > - ofpbuf_uninit(&of11_out); > - } > - ds_destroy(&in); > -} > - > /* "parse-pcap PCAP": read packets from PCAP and print their flows. */ > static void > ofctl_parse_pcap(int argc OVS_UNUSED, char *argv[]) > @@ -3587,12 +3485,10 @@ static const struct command all_commands[] = { > { "parse-nx-match", 0, 0, ofctl_parse_nxm }, > { "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-actions", 1, 1, ofctl_parse_actions }, > + { "parse-instructions", 1, 1, ofctl_parse_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 }, > - { "parse-ofp11-instructions", 0, 0, ofctl_parse_ofp11_instructions }, > { "parse-pcap", 1, 1, ofctl_parse_pcap }, > { "check-vlan", 2, 2, ofctl_check_vlan }, > { "print-error", 1, 1, ofctl_print_error }, > -- > 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