Skip to content

Commit

Permalink
tests: Add more tests for VLAN match encoding and decoding.
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Simon Horman <[email protected]
  • Loading branch information
blp committed Jul 20, 2012
1 parent b592e72 commit df77824
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 0 deletions.
115 changes: 115 additions & 0 deletions DESIGN
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,121 @@ sends flow_removed message --- --- --- % %
receive the generated messages.)


VLAN Matching
=============

The 802.1Q VLAN header causes more trouble than any other 4 bytes in
networking. More specifically, three versions of OpenFlow and Open
vSwitch have among them four different ways to match the contents and
presence of the VLAN header. The following table describes how each
version works.

Match NXM OF1.0 OF1.1 OF1.2
----- --------- ----------- ----------- ------------
[1] 0000/0000 ????/1,??/? ????/1,??/? 0000/0000,--
[2] 0000/ffff ffff/0,??/? ffff/0,??/? 0000/ffff,--
[3] 1xxx/1fff 0xxx/0,??/1 0xxx/0,??/1 1xxx/ffff,--
[4] z000/f000 ????/1,0y/0 fffe/0,0y/0 1000/1000,0y
[5] zxxx/ffff 0xxx/0,0y/0 0xxx/0,0y/0 1xxx/ffff,0y
[6] 0000/0fff <none> <none> <none>
[7] 0000/f000 <none> <none> <none>
[8] 0000/efff <none> <none> <none>
[9] 1001/1001 <none> <none> 1001/1001,--
[10] 3000/3000 <none> <none> <none>

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). <none> 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.
<none> 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
============

Expand Down
87 changes: 87 additions & 0 deletions tests/ovs-ofctl.at
Original file line number Diff line number Diff line change
Expand Up @@ -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: <any> -> 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])
Expand Down
76 changes: 76 additions & 0 deletions utilities/ovs-ofctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 },

Expand Down

0 comments on commit df77824

Please sign in to comment.