From 96628ae85fe26ac86d35bca5f4c288e56048c3d6 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 17 Jul 2012 09:39:23 -0700 Subject: [PATCH] tests: Add detailed test for OF1.0 match decoding and encoding. This follows the form of the OF1.1 match decoding and encoding test that I wrote a while back, which seems to be a good form to use. Signed-off-by: Ben Pfaff Tested-by: Simon Horman --- tests/ovs-ofctl.at | 207 ++++++++++++++++++++++++++++++++++++++++++ utilities/ovs-ofctl.c | 67 ++++++++++++-- 2 files changed, 266 insertions(+), 8 deletions(-) diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index 73e2e906..4ce2fa52 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -726,6 +726,213 @@ nx_pull_match() returned error OFPBMC_BAD_FIELD ]) AT_CLEANUP +AT_SETUP([ovs-ofctl parse-ofp10-match]) +AT_KEYWORDS([OF1.0]) +AT_DATA([test-data], [dnl +# in_port=65534 +003820fe fffe 000000000000 000000000000 0000 00 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_src=00:01:02:03:04:05 +003820fb 0000 000102030405 000000000000 0000 00 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_dst=10:20:30:40:50:60 +003820f7 0000 000000000000 102030405060 0000 00 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_vlan=291 +003820fd 0000 000000000000 000000000000 0123 00 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_vlan_pcp=5 +002820ff 0000 000000000000 000000000000 0000 05 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_vlan=291,dl_vlan_pcp=4 +002820fd 0000 000000000000 000000000000 0123 04 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# vlan_tci=0x0000 +003820fd 0000 000000000000 000000000000 ffff 00 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +dnl dl_vlan_pcp doesn't make sense when dl_vlan is "none", so +dnl OVS ignores it and drops it on output. +# vlan_tci=0x0000 +# 1: 28 -> 38 +# 20: 05 -> 00 +002820fd 0000 000000000000 000000000000 ffff 05 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +dnl Invalid VID and PCP discards out-of-range bits: +# dl_vlan=256,dl_vlan_pcp=7 +# 18: f1 -> 01 +# 20: ff -> 07 +002820fd 0000 000000000000 000000000000 f100 ff 00 0000 00 00 0000 dnl +00000000 00000000 0000 0000 + +# dl_type=0x1234 +003820ef 0000 000000000000 000000000000 0000 00 00 1234 00 00 0000 dnl +00000000 00000000 0000 0000 + +# ip,nw_proto=5 +003820cf 0000 000000000000 000000000000 0000 00 00 0800 00 05 0000 dnl +00000000 00000000 0000 0000 + +dnl Ignore nw_proto if not IP or ARP: +# dl_type=0x1234,nw_proto=5 +# normal: 3: cf -> ef +# normal: 25: 05 -> 00 +& ofp_util|INFO|normalization changed ofp_match, details: +& ofp_util|INFO| pre: dl_type=0x1234,nw_proto=5 +& ofp_util|INFO|post: dl_type=0x1234 +003820cf 0000 000000000000 000000000000 0000 00 00 1234 00 05 0000 dnl +00000000 00000000 0000 0000 + +# ip,nw_tos=252 +001820ef 0000 000000000000 000000000000 0000 00 00 0800 fc 00 0000 dnl +00000000 00000000 0000 0000 + +dnl Ignore nw_tos if not IP: +# arp,nw_tos=4 +# 24: 05 -> 04 +# normal: 1: 18 -> 38 +# normal: 24: 04 -> 00 +& ofp_util|INFO|normalization changed ofp_match, details: +& ofp_util|INFO| pre: arp,nw_tos=4 +& ofp_util|INFO|post: arp +001820ef 0000 000000000000 000000000000 0000 00 00 0806 05 00 0000 dnl +00000000 00000000 0000 0000 + +dnl Low 2 bits of invalid TOS are forced to 0: +# ip,nw_tos=48 +# 24: 31 -> 30 +001820ef 0000 000000000000 000000000000 0000 00 00 0800 31 00 0000 dnl +00000000 00000000 0000 0000 + +# arp,arp_op=2 +003820cf 0000 000000000000 000000000000 0000 00 00 0806 00 02 0000 dnl +00000000 00000000 0000 0000 + +# ip,nw_src=192.168.128.85 +003800ef 0000 000000000000 000000000000 0000 00 00 0800 00 00 0000 dnl +c0a88055 00000000 0000 0000 + +# ip,nw_src=192.168.128.0/24 +# 31: 55 -> 00 +003808ef 0000 000000000000 000000000000 0000 00 00 0800 00 00 0000 dnl +c0a88055 00000000 0000 0000 + +# ip,nw_dst=192.168.128.85 +003020ef 0000 000000000000 000000000000 0000 00 00 0800 00 00 0000 dnl +00000000 c0a88055 0000 0000 + +# ip,nw_dst=192.168.128.0/24 +# 35: 55 -> 00 +003220ef 0000 000000000000 000000000000 0000 00 00 0800 00 00 0000 dnl +00000000 c0a88055 0000 0000 + +# arp,nw_src=192.168.128.85 +003800ef 0000 000000000000 000000000000 0000 00 00 0806 00 00 0000 dnl +c0a88055 00000000 0000 0000 + +# arp,nw_src=192.168.128.0/24 +# 31: 55 -> 00 +003808ef 0000 000000000000 000000000000 0000 00 00 0806 00 00 0000 dnl +c0a88055 00000000 0000 0000 + +# arp,nw_dst=192.168.128.85 +003020ef 0000 000000000000 000000000000 0000 00 00 0806 00 00 0000 dnl +00000000 c0a88055 0000 0000 + +# arp,nw_dst=192.168.128.0/24 +# 35: 55 -> 00 +003220ef 0000 000000000000 000000000000 0000 00 00 0806 00 00 0000 dnl +00000000 c0a88055 0000 0000 + +dnl Ignore nw_src if not IP or ARP: +# dl_type=0x1234,nw_src=192.168.128.0/24 +# 31: 55 -> 00 +# normal: 2: 08 -> 20 +# normal: 28: c0 -> 00 +# normal: 29: a8 -> 00 +# normal: 30: 80 -> 00 +& ofp_util|INFO|normalization changed ofp_match, details: +& ofp_util|INFO| pre: dl_type=0x1234,nw_src=192.168.128.0/24 +& ofp_util|INFO|post: dl_type=0x1234 +003808ef 0000 000000000000 000000000000 0000 00 00 1234 00 00 0000 dnl +c0a88055 00000000 0000 0000 + +dnl Ignore nw_dst if not IP or ARP: +# dl_type=0x1234,nw_dst=192.168.128.0/24 +# 35: 55 -> 00 +# normal: 1: 32 -> 38 +# normal: 32: c0 -> 00 +# normal: 33: a8 -> 00 +# normal: 34: 80 -> 00 +& ofp_util|INFO|normalization changed ofp_match, details: +& ofp_util|INFO| pre: dl_type=0x1234,nw_dst=192.168.128.0/24 +& ofp_util|INFO|post: dl_type=0x1234 +003220ef 0000 000000000000 000000000000 0000 00 00 1234 00 00 0000 dnl +00000000 c0a88055 0000 0000 + +# tcp,tp_src=443 +0038208f 0000 000000000000 000000000000 0000 00 00 0800 00 06 0000 dnl +00000000 00000000 01bb 0000 + +# tcp,tp_dst=443 +0038204f 0000 000000000000 000000000000 0000 00 00 0800 00 06 0000 dnl +00000000 00000000 0000 01bb + +# udp,tp_src=443 +0038208f 0000 000000000000 000000000000 0000 00 00 0800 00 11 0000 dnl +00000000 00000000 01bb 0000 + +# udp,tp_dst=443 +0038204f 0000 000000000000 000000000000 0000 00 00 0800 00 11 0000 dnl +00000000 00000000 0000 01bb + +# icmp,icmp_type=5 +0038208f 0000 000000000000 000000000000 0000 00 00 0800 00 01 0000 dnl +00000000 00000000 0005 0000 + +# icmp,icmp_code=8 +0038204f 0000 000000000000 000000000000 0000 00 00 0800 00 01 0000 dnl +00000000 00000000 0000 0008 + +dnl Ignore tp_src if not TCP or UDP: +# ip,nw_proto=21,tp_src=443 +# normal: 3: 8f -> cf +# normal: 36: 01 -> 00 +# normal: 37: bb -> 00 +& ofp_util|INFO|normalization changed ofp_match, details: +& ofp_util|INFO| pre: ip,nw_proto=21,tp_src=443 +& ofp_util|INFO|post: ip,nw_proto=21 +0038208f 0000 000000000000 000000000000 0000 00 00 0800 00 15 0000 dnl +00000000 00000000 01bb 0000 + +dnl Ignore tp_dst if not TCP or UDP: +# ip,nw_proto=21,tp_dst=443 +# normal: 3: 4f -> cf +# normal: 38: 01 -> 00 +# normal: 39: bb -> 00 +dnl The normalization details are suppressed here due to rate-limiting. +0038204f 0000 000000000000 000000000000 0000 00 00 0800 00 15 0000 dnl +00000000 00000000 0000 01bb + +]) +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-match < input.txt], + [0], [expout], [experr]) +AT_CLEANUP + AT_SETUP([ovs-ofctl parse-ofp11-match]) AT_KEYWORDS([OF1.1]) AT_DATA([test-data], [dnl diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 4ad1acb4..39c3dae9 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -2233,7 +2233,8 @@ ofctl_parse_oxm(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) } static void -print_differences(const void *a_, size_t a_len, +print_differences(const char *prefix, + const void *a_, size_t a_len, const void *b_, size_t b_len) { const uint8_t *a = a_; @@ -2242,14 +2243,15 @@ print_differences(const void *a_, size_t a_len, for (i = 0; i < MIN(a_len, b_len); i++) { if (a[i] != b[i]) { - printf("%2zu: %02"PRIx8" -> %02"PRIx8"\n", i, a[i], b[i]); + printf("%s%2zu: %02"PRIx8" -> %02"PRIx8"\n", + prefix, i, a[i], b[i]); } } for (i = a_len; i < b_len; i++) { - printf("%2zu: (none) -> %02"PRIx8"\n", i, b[i]); + printf("%s%2zu: (none) -> %02"PRIx8"\n", prefix, i, b[i]); } for (i = b_len; i < a_len; i++) { - printf("%2zu: %02"PRIx8" -> (none)\n", i, a[i]); + printf("%s%2zu: %02"PRIx8" -> (none)\n", prefix, i, a[i]); } } @@ -2299,7 +2301,7 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ofpbuf_init(&of10_out, 0); ofpacts_put_openflow10(ofpacts.data, ofpacts.size, &of10_out); - print_differences(of10_in.data, of10_in.size, + print_differences("", of10_in.data, of10_in.size, of10_out.data, of10_out.size); putchar('\n'); @@ -2310,6 +2312,54 @@ ofctl_parse_ofp10_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ds_destroy(&in); } +/* "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 + * from the input. */ +static void +ofctl_parse_ofp10_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) +{ + struct ds in; + + ds_init(&in); + while (!ds_get_preprocessed_line(&in, stdin)) { + struct ofpbuf match_in; + struct ofp10_match match_out; + struct ofp10_match match_normal; + struct cls_rule rule; + + /* Parse hex bytes. */ + ofpbuf_init(&match_in, 0); + if (ofpbuf_put_hex(&match_in, ds_cstr(&in), NULL)[0] != '\0') { + ovs_fatal(0, "Trailing garbage in hex data"); + } + if (match_in.size != sizeof(struct ofp10_match)) { + ovs_fatal(0, "Input is %zu bytes, expected %zu", + match_in.size, sizeof(struct ofp10_match)); + } + + /* Convert to cls_rule and print. */ + ofputil_cls_rule_from_ofp10_match(match_in.data, OFP_DEFAULT_PRIORITY, + &rule); + cls_rule_print(&rule); + + /* Convert back to ofp10_match and print differences from input. */ + ofputil_cls_rule_to_ofp10_match(&rule, &match_out); + print_differences("", match_in.data, match_in.size, + &match_out, sizeof match_out); + + /* Normalize, then convert and compare again. */ + ofputil_normalize_rule(&rule); + ofputil_cls_rule_to_ofp10_match(&rule, &match_normal); + print_differences("normal: ", &match_out, sizeof match_out, + &match_normal, sizeof match_normal); + putchar('\n'); + + ofpbuf_uninit(&match_in); + } + ds_destroy(&in); +} + /* "parse-ofp11-match": reads a series of ofp11_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 @@ -2351,7 +2401,7 @@ ofctl_parse_ofp11_match(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) /* Convert back to ofp11_match and print differences from input. */ ofputil_cls_rule_to_ofp11_match(&rule, &match_out); - print_differences(match_in.data, match_in.size, + print_differences("", match_in.data, match_in.size, &match_out, sizeof match_out); putchar('\n'); @@ -2407,7 +2457,7 @@ ofctl_parse_ofp11_actions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ofpbuf_init(&of11_out, 0); ofpacts_put_openflow11_actions(ofpacts.data, ofpacts.size, &of11_out); - print_differences(of11_in.data, of11_in.size, + print_differences("", of11_in.data, of11_in.size, of11_out.data, of11_out.size); putchar('\n'); @@ -2467,7 +2517,7 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ofpacts_put_openflow11_instructions(ofpacts.data, ofpacts.size, &of11_out); - print_differences(of11_in.data, of11_in.size, + print_differences("", of11_in.data, of11_in.size, of11_out.data, of11_out.size); putchar('\n'); @@ -2555,6 +2605,7 @@ static const struct command all_commands[] = { { "parse-nxm", 0, 0, ofctl_parse_nxm }, { "parse-oxm", 0, 0, ofctl_parse_oxm }, { "parse-ofp10-actions", 0, 0, ofctl_parse_ofp10_actions }, + { "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 }, -- 2.30.2