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