From df778240e1e311f7eba9dfda4f5f8bf0f915ae5f Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 19 Jul 2012 22:17:10 -0700 Subject: [PATCH] tests: Add more tests for VLAN match encoding and decoding. Signed-off-by: Ben Pfaff Acked-by: Simon Horman + [7] 0000/f000 + [8] 0000/efff + [9] 1001/1001 1001/1001,-- + [10] 3000/3000 + +Each column is interpreted as follows. + + - Match: See the list below. + + - NXM: xxxx/yyyy means NXM_OF_VLAN_TCI_W with value xxxx and mask + yyyy. A mask of 0000 is equivalent to omitting + NXM_OF_VLAN_TCI(_W), a mask of ffff is equivalent to + NXM_OF_VLAN_TCI. + + - OF1.0 and OF1.1: wwww/x,yy/z means dl_vlan wwww, OFPFW_DL_VLAN + x, dl_vlan_pcp yy, and OFPFW_DL_VLAN_PCP z. ? means that the + given nibble is ignored (and conventionally 0 for wwww or z, + conventionally 1 for x or z). means that the given match + is not supported. + + - OF1.2: xxxx/yyyy,zz means OXM_OF_VLAN_VID_W with value xxxx and + mask yyyy, and OXM_OF_VLAN_PCP (which is not maskable) with + value zz. A mask of 0000 is equivalent to omitting + OXM_OF_VLAN_VID(_W), a mask of ffff is equivalent to + OXM_OF_VLAN_VID. -- means that OXM_OF_VLAN_PCP is omitted. + means that the given match is not supported. + +The matches are: + + [1] Matches any packet, that is, one without an 802.1Q header or with + an 802.1Q header with any TCI value. + + [2] Matches only packets without an 802.1Q header. + + NXM: Any match with (vlan_tci == 0) and (vlan_tci_mask & 0x1000) + != 0 is equivalent to the one listed in the table. + + OF1.0: The spec doesn't define behavior if dl_vlan is set to + 0xffff and OFPFW_DL_VLAN_PCP is not set. + + OF1.1: The spec says explicitly to ignore dl_vlan_pcp when + dl_vlan is set to 0xffff. + + OF1.2: The spec doesn't say what should happen if (vlan_vid == 0) + and (vlan_vid_mask & 0x1000) != 0 but (vlan_vid_mask != 0x1000), + but it would be straightforward to also interpret as [2]. + + [3] Matches only packets that have an 802.1Q header with VID xxx (and + any PCP). + + [4] Matches only packets that have an 802.1Q header with PCP y (and + any VID). + + NXM: z is ((y << 1) | 1). + + OF1.0: The spec isn't very clear, but OVS implements it this way. + + OF1.2: Presumably other masks such that (vlan_vid_mask & 0x1fff) + == 0x1000 would also work, but the spec doesn't define their + behavior. + + [5] Matches only packets that have an 802.1Q header with VID xxx and + PCP y. + + NXM: z is ((y << 1) | 1). + + OF1.2: Presumably other masks such that (vlan_vid_mask & 0x1fff) + == 0x1fff would also work. + + [6] Matches packets with no 802.1Q header or with an 802.1Q header + with a VID of 0. Only possible with NXM. + + [7] Matches packets with no 802.1Q header or with an 802.1Q header + with a PCP of 0. Only possible with NXM. + + [8] Matches packets with no 802.1Q header or with an 802.1Q header + with both VID and PCP of 0. Only possible with NXM. + + [9] Matches only packets that have an 802.1Q header with an + odd-numbered VID (and any PCP). Only possible with NXM and + OF1.2. (This is just an example; one can match on any desired + VID bit pattern.) + +[10] Matches only packets that have an 802.1Q header with an + odd-numbered PCP (and any VID). Only possible with NXM. (This + is just an example; one can match on any desired VID bit + pattern.) + +Additional notes: + + - OF1.2: The top three bits of OXM_OF_VLAN_VID are fixed to zero, + so bits 13, 14, and 15 in the masks listed in the table may be + set to arbitrary values, as long as the corresponding value bits + are also zero. The suggested ffff mask for [2], [3], and [5] + allows a shorter OXM representation (the mask is omitted) than + the minimal 1fff mask. + + Flow Cookies ============ diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at index d6ade557..08026ec8 100644 --- a/tests/ovs-ofctl.at +++ b/tests/ovs-ofctl.at @@ -1645,6 +1645,93 @@ OXM_OF_IN_PORT(00000001), OXM_OF_ETH_TYPE(0800) ]) AT_CLEANUP +dnl Check all of the patterns mentioned in the "VLAN Matching" section +dnl in the DESIGN file at top level. +AT_SETUP([ovs-ofctl check-vlan]) +AT_KEYWORDS([VLAN]) + +dnl [1] +AT_CHECK([ovs-ofctl check-vlan 0000 0000], [0], [dnl + -> 0000/0000 +NXM: -> 0000/0000 +OF1.0: 0000/1,00/1 -> 0000/0000 +OF1.1: 0000/1,00/1 -> 0000/0000 +]) + +dnl [2] +AT_CHECK([ovs-ofctl check-vlan 0000 ffff], [0], [dnl +vlan_tci=0x0000 -> 0000/ffff +NXM: NXM_OF_VLAN_TCI(0000) -> 0000/ffff +OF1.0: ffff/0,00/1 -> 0000/ffff +OF1.1: ffff/0,00/1 -> 0000/ffff +]) + +dnl [3] +AT_CHECK([ovs-ofctl check-vlan 1abc 1fff], [0], [dnl +dl_vlan=2748 -> 1abc/1fff +NXM: NXM_OF_VLAN_TCI_W(1abc/1fff) -> 1abc/1fff +OF1.0: 0abc/0,00/1 -> 1abc/1fff +OF1.1: 0abc/0,00/1 -> 1abc/1fff +]) + +dnl [4] +AT_CHECK([ovs-ofctl check-vlan b000 f000], [0], [dnl +dl_vlan_pcp=5 -> b000/f000 +NXM: NXM_OF_VLAN_TCI_W(b000/f000) -> b000/f000 +OF1.0: 0000/1,05/0 -> b000/f000 +OF1.1: fffe/0,05/0 -> b000/f000 +]) + +dnl [5] +AT_CHECK([ovs-ofctl check-vlan babc ffff], [0], [dnl +dl_vlan=2748,dl_vlan_pcp=5 -> babc/ffff +NXM: NXM_OF_VLAN_TCI(babc) -> babc/ffff +OF1.0: 0abc/0,05/0 -> babc/ffff +OF1.1: 0abc/0,05/0 -> babc/ffff +]) + +dnl [6] +AT_CHECK([ovs-ofctl check-vlan 0000 0fff], [0], [dnl +vlan_tci=0x0000/0x0fff -> 0000/0fff +NXM: NXM_OF_VLAN_TCI_W(0000/0fff) -> 0000/0fff +OF1.0: 0000/0,00/1 -> 1000/1fff +OF1.1: 0000/0,00/1 -> 1000/1fff +]) + +dnl [7] +AT_CHECK([ovs-ofctl check-vlan 0000 f000], [0], [dnl +vlan_tci=0x0000/0xf000 -> 0000/f000 +NXM: NXM_OF_VLAN_TCI_W(0000/f000) -> 0000/f000 +OF1.0: ffff/0,00/1 -> 0000/ffff +OF1.1: ffff/0,00/1 -> 0000/ffff +]) + +dnl [8] +AT_CHECK([ovs-ofctl check-vlan 0000 efff], [0], [dnl +vlan_tci=0x0000/0xefff -> 0000/efff +NXM: NXM_OF_VLAN_TCI_W(0000/efff) -> 0000/efff +OF1.0: 0000/0,00/0 -> 1000/ffff +OF1.1: 0000/0,00/0 -> 1000/ffff +]) + +dnl [9] +AT_CHECK([ovs-ofctl check-vlan 1001 1001], [0], [dnl +vlan_tci=0x1001/0x1001 -> 1001/1001 +NXM: NXM_OF_VLAN_TCI_W(1001/1001) -> 1001/1001 +OF1.0: 0001/0,00/1 -> 1001/1fff +OF1.1: 0001/0,00/1 -> 1001/1fff +]) + +dnl [10] +AT_CHECK([ovs-ofctl check-vlan 3000 3000], [0], [dnl +vlan_tci=0x3000/0x3000 -> 3000/3000 +NXM: NXM_OF_VLAN_TCI_W(3000/3000) -> 3000/3000 +OF1.0: 0000/1,01/0 -> 3000/f000 +OF1.1: fffe/0,01/0 -> 3000/f000 +]) +AT_CHECK +AT_CLEANUP + dnl Check that "-F openflow10" rejects a flow_mod with unsupported features, dnl such as tunnels and metadata. AT_SETUP([ovs-ofctl -F option and NXM features]) diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 39c3dae9..e5c52555 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -2528,6 +2528,81 @@ ofctl_parse_ofp11_instructions(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) ds_destroy(&in); } +/* "check-vlan VLAN_TCI VLAN_TCI_MASK": converts the specified vlan_tci and + * mask values to and from various formats and prints the results. */ +static void +ofctl_check_vlan(int argc OVS_UNUSED, char *argv[]) +{ + struct cls_rule rule; + + char *string_s; + struct ofputil_flow_mod fm; + + struct ofpbuf nxm; + struct cls_rule nxm_rule; + int nxm_match_len; + char *nxm_s; + + struct ofp10_match of10_match; + struct cls_rule of10_rule; + + struct ofp11_match of11_match; + struct cls_rule of11_rule; + + enum ofperr error; + + cls_rule_init_catchall(&rule, OFP_DEFAULT_PRIORITY); + rule.flow.vlan_tci = htons(strtoul(argv[1], NULL, 16)); + rule.wc.vlan_tci_mask = htons(strtoul(argv[2], NULL, 16)); + + /* Convert to and from string. */ + string_s = cls_rule_to_string(&rule); + printf("%s -> ", string_s); + fflush(stdout); + parse_ofp_str(&fm, -1, string_s, false); + printf("%04"PRIx16"/%04"PRIx16"\n", + ntohs(fm.cr.flow.vlan_tci), + ntohs(fm.cr.wc.vlan_tci_mask)); + + /* Convert to and from NXM. */ + ofpbuf_init(&nxm, 0); + nxm_match_len = nx_put_match(&nxm, false, &rule, htonll(0), htonll(0)); + nxm_s = nx_match_to_string(nxm.data, nxm_match_len); + error = nx_pull_match(&nxm, nxm_match_len, 0, &nxm_rule, NULL, NULL); + printf("NXM: %s -> ", nxm_s); + if (error) { + printf("%s\n", ofperr_to_string(error)); + } else { + printf("%04"PRIx16"/%04"PRIx16"\n", + ntohs(nxm_rule.flow.vlan_tci), + ntohs(nxm_rule.wc.vlan_tci_mask)); + } + free(nxm_s); + ofpbuf_uninit(&nxm); + + /* Convert to and from OpenFlow 1.0. */ + ofputil_cls_rule_to_ofp10_match(&rule, &of10_match); + ofputil_cls_rule_from_ofp10_match(&of10_match, 0, &of10_rule); + printf("OF1.0: %04"PRIx16"/%d,%02"PRIx8"/%d -> %04"PRIx16"/%04"PRIx16"\n", + ntohs(of10_match.dl_vlan), + (of10_match.wildcards & htonl(OFPFW10_DL_VLAN)) != 0, + of10_match.dl_vlan_pcp, + (of10_match.wildcards & htonl(OFPFW10_DL_VLAN_PCP)) != 0, + ntohs(of10_rule.flow.vlan_tci), + ntohs(of10_rule.wc.vlan_tci_mask)); + + /* Convert to and from OpenFlow 1.1. */ + ofputil_cls_rule_to_ofp11_match(&rule, &of11_match); + ofputil_cls_rule_from_ofp11_match(&of11_match, 0, &of11_rule); + printf("OF1.1: %04"PRIx16"/%d,%02"PRIx8"/%d -> %04"PRIx16"/%04"PRIx16"\n", + ntohs(of11_match.dl_vlan), + (of11_match.wildcards & htonl(OFPFW11_DL_VLAN)) != 0, + of11_match.dl_vlan_pcp, + (of11_match.wildcards & htonl(OFPFW11_DL_VLAN_PCP)) != 0, + ntohs(of11_rule.flow.vlan_tci), + ntohs(of11_rule.wc.vlan_tci_mask)); +} + /* "print-error ENUM": Prints the type and code of ENUM for every OpenFlow * version. */ static void @@ -2609,6 +2684,7 @@ static const struct command all_commands[] = { { "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 }, + { "check-vlan", 2, 2, ofctl_check_vlan }, { "print-error", 1, 1, ofctl_print_error }, { "ofp-print", 1, 2, ofctl_ofp_print }, -- 2.30.2