diff mbox

[ovs-dev,2/2] ovs-fields: New manpage to document Open vSwitch and OpenFlow fields.

Message ID 20161228211028.16167-2-blp@ovn.org
State Accepted
Headers show

Commit Message

Ben Pfaff Dec. 28, 2016, 9:10 p.m. UTC
From: Ben Pfaff <blp@nicira.com>

There is still plenty of opportunity for improvement, but this new
ovs-fields(7) manpage is much more comprehensive than ovs-ofctl(8)
could be.

Signed-off-by: Ben Pfaff <blp@ovn.org>
---
 Documentation/ref/index.rst     |    4 +
 build-aux/extract-ofp-fields    |  359 +++-
 include/openvswitch/meta-flow.h |  205 +-
 lib/automake.mk                 |   17 +-
 lib/meta-flow.xml               | 4163 +++++++++++++++++++++++++++++++++++++++
 ovn/ovn-architecture.7.xml      |    2 +-
 ovn/utilities/ovn-trace.8.xml   |    2 +-
 python/build/nroff.py           |   62 +-
 utilities/ovs-ofctl.8.in        |  993 +---------
 vswitchd/vswitch.xml            |    6 +-
 10 files changed, 4573 insertions(+), 1240 deletions(-)
 create mode 100644 lib/meta-flow.xml

Comments

Justin Pettit Jan. 25, 2017, 1:11 a.m. UTC | #1
> On Dec 28, 2016, at 1:10 PM, Ben Pfaff <blp@ovn.org> wrote:
> 
> From: Ben Pfaff <blp@nicira.com>
> 
> There is still plenty of opportunity for improvement, but this new
> ovs-fields(7) manpage is much more comprehensive than ovs-ofctl(8)
> could be.
> 
> Signed-off-by: Ben Pfaff <blp@ovn.org>
> ---
> Documentation/ref/index.rst     |    4 +
> build-aux/extract-ofp-fields    |  359 +++-
> include/openvswitch/meta-flow.h |  205 +-
> lib/automake.mk                 |   17 +-
> lib/meta-flow.xml               | 4163 +++++++++++++++++++++++++++++++++++++++
> ovn/ovn-architecture.7.xml      |    2 +-
> ovn/utilities/ovn-trace.8.xml   |    2 +-
> python/build/nroff.py           |   62 +-
> utilities/ovs-ofctl.8.in        |  993 +---------
> vswitchd/vswitch.xml            |    6 +-
> 10 files changed, 4573 insertions(+), 1240 deletions(-)
> create mode 100644 lib/meta-flow.xml

Since the documentation formatted well, I'm going to assume extract-ofp-fields and nroff.py are written perfectly and without error.

> diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
> new file mode 100644
> index 0000000..1b646f5
> --- /dev/null
> +++ b/lib/meta-flow.xml

For everyone else's benefit, I printed out the ovs-fields man page and directly marked the page with feedback, which I handed to Ben.  I'm sure he'd be happy to scan all 57 pages for anyone interested.

> diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
> index af1eb2b..a3a29b1 100644
> --- a/utilities/ovs-ofctl.8.in
> +++ b/utilities/ovs-ofctl.8.in
> 
> ...
> +\fBovs\-fields\fR(7) describes the supported fields and how to match
> +them.  In addition to match fields, commands that operate on flow
> +accept a few addition key-value pairs:

s/flow/flows
s/addition/additional

> +.IP "\fBduration=\fR..."
> +.IQ "\fBn_packet=\fR..."
> +.IQ "\fBn_bytes=\fR..."
> +These ``fields'' are ignored to allow output from the \fBdump\-flows\fR
> command to be used as input for other commands that parse flows.

I actually found the previous way this was written clearer.

This was a lot of work.  Thanks for doing it!

--Justin
Justin Pettit Jan. 25, 2017, 1:13 a.m. UTC | #2
> On Jan 24, 2017, at 5:11 PM, Justin Pettit <jpettit@ovn.org> wrote:
> 
> This was a lot of work.  Thanks for doing it!
> 
> --Justin

Whoops!

Acked-by: Justin Pettit <jpettit@ovn.org>

--Justin
Ben Pfaff Jan. 25, 2017, 9:59 p.m. UTC | #3
On Tue, Jan 24, 2017 at 05:13:15PM -0800, Justin Pettit wrote:
> 
> > On Jan 24, 2017, at 5:11 PM, Justin Pettit <jpettit@ovn.org> wrote:
> > 
> > This was a lot of work.  Thanks for doing it!
> > 
> > --Justin
> 
> Whoops!
> 
> Acked-by: Justin Pettit <jpettit@ovn.org>

Thanks.  I applied these to master and branch-2.7.
diff mbox

Patch

diff --git a/Documentation/ref/index.rst b/Documentation/ref/index.rst
index 27d975a..49121b7 100644
--- a/Documentation/ref/index.rst
+++ b/Documentation/ref/index.rst
@@ -109,6 +109,10 @@  Man Pages
      - `(pdf) <http://openvswitch.org/support/dist-docs/ovs-dpctl-top.8.pdf>`__
      - `(html) <http://openvswitch.org/support/dist-docs/ovs-dpctl-top.8.html>`__
      - `(plain text) <http://openvswitch.org/support/dist-docs/ovs-dpctl-top.8.txt>`__
+   * - ovs-fields(7)
+     - `(pdf) <http://openvswitch.org/support/dist-docs/ovs-fields.7.pdf>`__
+     - `(html) <http://openvswitch.org/support/dist-docs/ovs-fields.7.html>`__
+     - `(plain text) <http://openvswitch.org/support/dist-docs/ovs-fields.7.txt>`__
    * - ovs-l3ping(8)
      - `(pdf) <http://openvswitch.org/support/dist-docs/ovs-l3ping.8.pdf>`__
      - `(html) <http://openvswitch.org/support/dist-docs/ovs-l3ping.8.html>`__
diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
index 8d43e4b..c37020a 100755
--- a/build-aux/extract-ofp-fields
+++ b/build-aux/extract-ofp-fields
@@ -1,8 +1,11 @@ 
 #! /usr/bin/python
 
+import getopt
 import sys
 import os.path
 import re
+import xml.dom.minidom
+import build.nroff
 
 line = ""
 
@@ -13,6 +16,7 @@  VERSION = {"1.0": 0x01,
            "1.3": 0x04,
            "1.4": 0x05,
            "1.5": 0x06}
+VERSION_REVERSE = dict((v,k) for k, v in VERSION.iteritems())
 
 TYPES = {"u8":       (1,   False),
          "be16":     (2,   False),
@@ -174,8 +178,7 @@  def parse_oxm(s, prefix, n_bytes):
     if oxm_class == 0xffff:
         oxm_length += 4
 
-    header = ("NXM_HEADER(0x%x,0x%x,%s,0,%d)"
-              % (oxm_vendor, oxm_class, oxm_type, oxm_length))
+    header = (oxm_vendor, oxm_class, int(oxm_type), oxm_length)
 
     if of_version:
         if of_version not in VERSION:
@@ -183,6 +186,8 @@  def parse_oxm(s, prefix, n_bytes):
         of_version_nr = VERSION[of_version]
         if of_version_nr < VERSION['1.2']:
             fatal("%s: claimed version %s predates OXM" % (name, of_version))
+    elif prefix == 'OXM':
+        fatal("%s: missing OpenFlow version number" % name)
     else:
         of_version_nr = 0
 
@@ -257,13 +262,14 @@  def parse_field(mff, comment):
     fmt = FORMATTING.get(d['Formatting'])
     if not fmt:
         fatal("%s: unknown format %s" % (mff, d['Formatting']))
+    f['formatting'] = d['Formatting']
     if f['n_bytes'] < fmt[1] or f['n_bytes'] > fmt[2]:
         fatal("%s: %d-byte field can't be formatted as %s"
               % (mff, f['n_bytes'], d['Formatting']))
     f['string'] = fmt[0]
 
-    f['prereqs'] = PREREQS.get(d['Prerequisites'])
-    if not f['prereqs']:
+    f['prereqs'] = d['Prerequisites']
+    if f['prereqs'] not in PREREQS:
         fatal("%s: unknown prerequisites %s" % (mff, d['Prerequisites']))
 
     if d['Access'] == 'read-only':
@@ -302,8 +308,14 @@  def protocols_to_c(protocols):
         assert False
 
 
-def make_meta_flow(fields):
-    output = []
+def autogen_c_comment():
+    return [
+"/* Generated automatically; do not modify!    -*- buffer-read-only: t -*- */",
+""]
+
+def make_meta_flow(meta_flow_h):
+    fields = extract_ofp_fields(meta_flow_h)
+    output = autogen_c_comment()
     for f in fields:
         output += ["{"]
         output += ["    %s," % f['mff']]
@@ -323,7 +335,7 @@  def make_meta_flow(fields):
         else:
             rw = 'false'
         output += ["    %s, %s, %s, %s,"
-                   % (f['mask'], f['string'], f['prereqs'], rw)]
+                   % (f['mask'], f['string'], PREREQS[f['prereqs']], rw)]
 
         oxm = f['OXM']
         of10 = f['OF1.0']
@@ -378,21 +390,30 @@  def make_meta_flow(fields):
     return output
 
 
-def make_nx_match(fields):
-    output = []
+def make_nx_match(meta_flow_h):
+    fields = extract_ofp_fields(meta_flow_h)
+    output = autogen_c_comment()
     print("static struct nxm_field_index all_nxm_fields[] = {")
     for f in fields:
         # Sort by OpenFlow version number (nx-match.c depends on this).
         for oxm in sorted(f['OXM'], key=lambda x: x[2]):
+            header = ("NXM_HEADER(0x%x,0x%x,%s,0,%d)" % oxm[0])
             print("""{ .nf = { %s, %d, "%s", %s } },""" % (
-                oxm[0], oxm[2], oxm[1], f['mff']))
+                header, oxm[2], oxm[1], f['mff']))
     print("};")
     return output
 
 
-def extract_ofp_fields(mode):
+def extract_ofp_fields(fn):
+    global file_name
+    global input_file
+    global line_number
     global line
 
+    file_name = fn
+    input_file = open(file_name)
+    line_number = 0
+
     fields = []
 
     while True:
@@ -495,37 +516,297 @@  def extract_ofp_fields(mode):
     if n_errors:
         sys.exit(1)
 
-    print("""\
-/* Generated automatically; do not modify!    "-*- buffer-read-only: t -*- */
-""")
-
-    if mode == '--meta-flow':
-        output = make_meta_flow(fields)
-    elif mode == '--nx-match':
-        output = make_nx_match(fields)
+    return fields
+
+## ------------------------ ##
+## Documentation Generation ##
+## ------------------------ ##
+
+def field_to_xml(field_node, f, body, summary):
+    f["used"] = True
+
+    # Summary.
+    if field_node.hasAttribute('internal'):
+        return
+
+    min_of_version = None
+    min_ovs_version = None
+    for header, name, of_version_nr, ovs_version_s in f['OXM']:
+        if (not name.startswith('NXM')
+            and (min_ovs_version is None or of_version_nr < min_of_version)):
+            min_of_version = of_version_nr
+        ovs_version = [int(x) for x in ovs_version_s.split('.')]
+        if min_ovs_version is None or ovs_version < min_ovs_version:
+            min_ovs_version = ovs_version
+    summary += ["\\fB%s\\fR" % f["name"]]
+    if f["extra_name"]:
+        summary += [" aka \\fB%s\\fR" % f["extra_name"]]
+    summary += [";%d" % f["n_bytes"]]
+    if f["n_bits"] != 8 * f["n_bytes"]:
+        summary += [" (low %d bits)" % f["n_bits"]]
+    summary += [";%s;" % {"MFM_NONE": "no", "MFM_FULLY": "yes"}[f["mask"]]]
+    summary += ["%s;" % {True: "yes", False: "no"}[f["writable"]]]
+    summary += ["%s;" % f["prereqs"]]
+    support = []
+    if min_of_version is not None:
+        support += ["OF%s+" % VERSION_REVERSE[min_of_version]]
+    if min_ovs_version is not None:
+        support += ["OVS %s+" % '.'.join([str(x) for x in min_ovs_version])]
+    summary += ' and '.join(support)
+    summary += ["\n"]
+
+    # Full description.
+    if field_node.hasAttribute('hidden'):
+        return
+
+    title = field_node.attributes['title'].nodeValue
+
+    body += [""".PP
+\\fB%s Field\\fR
+.TS
+tab(;);
+l lx.
+""" % title]
+
+    body += ["Name:;\\fB%s\\fR" % f["name"]]
+    if f["extra_name"]:
+        body += [" (aka \\fB%s\\fR)" % f["extra_name"]]
+    body += ['\n']
+
+    body += ["Width:;"]
+    if f["n_bits"] != 8 * f["n_bytes"]:
+        body += ["%d bits (only the least-significant %d bits "
+                 "may be nonzero)" % (f["n_bytes"] * 8, f["n_bits"])]
+    elif f["n_bits"] <= 128:
+        body += ["%d bits" % f["n_bits"]]
     else:
-        assert False
+        body += ["%d bits (%d bytes)" % (f["n_bits"], f["n_bits"] / 8)]
+    body += ['\n']
+
+    body += ["Format:;%s\n" % f["formatting"]]
+
+    masks = {"MFM_NONE": "not maskable",
+             "MFM_FULLY": "arbitrary bitwise masks"}
+    body += ["Masking:;%s\n" % masks[f["mask"]]]
+    body += ["Prerequisites:;%s\n" % f["prereqs"]]
+
+    access = {True: "read/write",
+              False: "read-only"}[f["writable"]]
+    body += ["Access:;%s\n" % access]
+
+    of10 = {None: "not supported",
+            "exact match": "yes (exact match only)",
+            "CIDR mask": "yes (CIDR match only)"}
+    body += ["OpenFlow 1.0:;%s\n" % of10[f["OF1.0"]]]
+
+    of11 = {None: "not supported",
+            "exact match": "yes (exact match only)",
+            "bitwise mask": "yes"}
+    body += ["OpenFlow 1.1:;%s\n" % of11[f["OF1.1"]]]
+
+    oxms = []
+    for header, name, of_version_nr, ovs_version in [x for x in sorted(f['OXM'], key=lambda x: x[2]) if not x[1].startswith('NXM')]:
+        of_version = VERSION_REVERSE[of_version_nr]
+        oxms += [r"\fB%s\fR (%d) since OpenFlow %s and Open vSwitch %s" % (name, header[2], of_version, ovs_version)]
+    if not oxms:
+        oxms = ['none']
+    body += ['OXM:;T{\n%s\nT}\n' % r'\[char59] '.join(oxms)]
+
+    nxms = []
+    for header, name, of_version_nr, ovs_version in [x for x in sorted(f['OXM'], key=lambda x: x[2]) if x[1].startswith('NXM')]:
+        nxms += [r"\fB%s\fR (%d) since Open vSwitch %s" % (name, header[2], ovs_version)]
+    if not nxms:
+        nxms = ['none']
+    body += ['NXM:;T{\n%s\nT}\n' % r'\[char59] '.join(nxms)]
+
+    body += [".TE\n"]
+
+    body += ['.PP\n']
+    body += [build.nroff.block_xml_to_nroff(field_node.childNodes)]
+
+def group_xml_to_nroff(group_node, fields):
+    title = group_node.attributes['title'].nodeValue
+
+    summary = []
+    body = []
+    for node in group_node.childNodes:
+        if node.nodeType == node.ELEMENT_NODE and node.tagName == 'field':
+            id_ = node.attributes['id'].nodeValue
+            field_to_xml(node, fields[id_], body, summary)
+        else:
+            body += [build.nroff.block_xml_to_nroff([node])]
+
+    content = [
+        '.bp\n',
+        '.SH \"%s\"\n' % build.nroff.text_to_nroff(title.upper() + " FIELDS"),
+        '.SS "Summary:"\n',
+        '.TS\n',
+        'tab(;);\n',
+        'l l l l l l l.\n',
+        'Name;Bytes;Mask;RW?;Prereqs;Support\n',
+        '\_;\_;\_;\_;\_;\_\n']
+    content += summary
+    content += ['.TE\n']
+    content += body
+    return ''.join(content)
+
+def make_oxm_classes_xml(document):
+    s = '''tab(;);
+l l l.
+Prefix;Vendor;Class
+\_;\_;\_
+'''
+    for key in sorted(OXM_CLASSES, key=OXM_CLASSES.get):
+        vendor, class_ = OXM_CLASSES.get(key)
+        s += r"\fB%s\fR;" % key.rstrip('_')
+        if vendor:
+            s += r"\fL0x%08x\fR;" % vendor
+        else:
+            s += "(none);"
+        s += r"\fL0x%04x\fR;" % class_
+        s += "\n"
+    e = document.createElement('tbl')
+    e.appendChild(document.createTextNode(s))
+    return e
+
+def recursively_replace(node, name, replacement):
+    for child in node.childNodes:
+        if child.nodeType == node.ELEMENT_NODE:
+            if child.tagName == name:
+                node.replaceChild(replacement, child)
+            else:
+                recursively_replace(child, name, replacement)
 
-    return output
+def make_ovs_fields(meta_flow_h, meta_flow_xml):
+    fields = extract_ofp_fields(meta_flow_h)
+    fields_map = {}
+    for f in fields:
+        fields_map[f['mff']] = f
 
+    document = xml.dom.minidom.parse(meta_flow_xml)
+    doc = document.documentElement
+
+    global version
+    if version == None:
+        version = "UNKNOWN"
+
+    print('''\
+'\\" tp
+.\\" -*- mode: troff; coding: utf-8 -*-
+.TH "ovs\-fields" 7 "%s" "Open vSwitch" "Open vSwitch Manual"
+.fp 5 L CR              \\" Make fixed-width font available as \\fL.
+.de ST
+.  PP
+.  RS -0.15in
+.  I "\\\\$1"
+.  RE
+..
+
+.de SU
+.  PP
+.  I "\\\\$1"
+..
+
+.de IQ
+.  br
+.  ns
+.  IP "\\\\$1"
+..
+.de URL
+\\\\$2 \\(laURL: \\\\$1 \\(ra\\\\$3
+..
+.if \\n[.g] .mso www.tmac
+.SH NAME
+ovs\-fields \- protocol header fields in OpenFlow and Open vSwitch
+.
+.PP
+''') % version
+
+    recursively_replace(doc, 'oxm_classes', make_oxm_classes_xml(document))
+
+    s = ''
+    for node in doc.childNodes:
+        if node.nodeType == node.ELEMENT_NODE and node.tagName == "group":
+            s += group_xml_to_nroff(node, fields_map)
+        elif node.nodeType == node.TEXT_NODE:
+            assert node.data.isspace()
+        elif node.nodeType == node.COMMENT_NODE:
+            pass
+        else:
+            s += build.nroff.block_xml_to_nroff([node])
 
-if __name__ == '__main__':
-    if '--help' in sys.argv:
-        usage()
-    elif len(sys.argv) != 3:
-        sys.stderr.write("exactly two arguments required; "
-                         "use --help for help\n")
+    for f in fields:
+        if "used" not in f:
+            fatal("%s: field not documented" % f["mff"])
+    if n_errors:
         sys.exit(1)
-    elif sys.argv[2] in ('--meta-flow', '--nx-match'):
-        global file_name
-        global input_file
-        global line_number
-        file_name = sys.argv[1]
-        input_file = open(file_name)
-        line_number = 0
-
-        for oline in extract_ofp_fields(sys.argv[2]):
-            print(oline)
-    else:
-        sys.stderr.write("invalid arguments; use --help for help\n")
+
+    output = []
+    for oline in s.split("\n"):
+        oline = oline.strip()
+
+        # Life is easier with nroff if we don't try to feed it Unicode.
+        # Fortunately, we only use a few characters outside the ASCII range.
+        oline = oline.replace(u'\u2208', r'\[mo]')
+        oline = oline.replace(u'\u2260', r'\[!=]')
+        oline = oline.replace(u'\u2264', r'\[<=]')
+        if len(oline):
+            output += [oline]
+
+    # nroff tends to ignore .bp requests if they come after .PP requests,
+    # so remove .PPs that precede .bp.
+    for i in range(len(output)):
+        if output[i] == '.bp':
+            j = i - 1
+            while j >= 0 and output[j] == '.PP':
+                output[j] = None
+                j -= 1
+    for i in range(len(output)):
+        if output[i] is not None:
+            print(output[i])
+
+## ------------ ##
+## Main Program ##
+## ------------ ##
+
+if __name__ == "__main__":
+    argv0 = sys.argv[0]
+    try:
+        options, args = getopt.gnu_getopt(sys.argv[1:], 'h',
+                                          ['help', 'ovs-version='])
+    except getopt.GetoptError, geo:
+        sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
         sys.exit(1)
+
+    global version
+    version = None
+    for key, value in options:
+        if key in ['-h', '--help']:
+            usage()
+        elif key == '--ovs-version':
+            version = value
+        else:
+            sys.exit(0)
+
+    if not args:
+        sys.stderr.write("%s: missing command argument "
+                         "(use --help for help)\n" % argv0)
+        sys.exit(1)
+
+    commands = {"meta-flow": (make_meta_flow, 1),
+                "nx-match": (make_nx_match, 1),
+                "ovs-fields": (make_ovs_fields, 2)}
+
+    if not args[0] in commands:
+        sys.stderr.write("%s: unknown command \"%s\" "
+                         "(use --help for help)\n" % (argv0, args[0]))
+        sys.exit(1)
+
+    func, n_args = commands[args[0]]
+    if len(args) - 1 != n_args:
+        sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
+                         "provided\n"
+                         % (argv0, args[0], n_args, len(args) - 1))
+        sys.exit(1)
+
+    func(*args[1:])
diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index b091c1b..217be30 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -34,64 +34,7 @@  struct match;
 /* Open vSwitch fields
  * ===================
  *
- * A "field" is a property of a packet.  Most familiarly, "data fields" are
- * fields that can be extracted from a packet.
- *
- * Some data fields are always present as a consequence of the basic networking
- * technology in use.  Ethernet is the assumed base technology for current
- * versions of OpenFlow and Open vSwitch, so Ethernet header fields are always
- * available.
- *
- * Other data fields are not always present.  A packet contains ARP fields, for
- * example, only when its Ethernet header indicates the Ethertype for ARP,
- * 0x0806.  We say that a field is "applicable" when it is it present in a
- * packet, and "inapplicable" when it is not, and refer to the conditions that
- * determine whether a field is applicable as "prerequisites".  Some
- * VLAN-related fields are a special case: these fields are always applicable,
- * but have a designated value or bit that indicates whether a VLAN header is
- * present, with the remaining values or bits indicating the VLAN header's
- * content (if it is present).  See MFF_VLAN_TCI for an example.
- *
- * Conceptually, an inapplicable field does not have a value, not even a
- * nominal ``value'' such as all-zero-bits.  In many circumstances, OpenFlow
- * and Open vSwitch allow references only to applicable fields.  For example,
- * one may match a given field only if the match includes the field's
- * prerequisite, e.g. matching an ARP field is only allowed if one also matches
- * on Ethertype 0x0806.
- *
- * (Practically, however, OVS represents a field's value as some fixed member
- * in its "struct flow", so accessing that member will obtain some value.  Some
- * members are used for more than one purpose, e.g. the "tp_src" member
- * represents the TCP, UDP, and SCTP source port, so the value read may not
- * even make sense.  For this reason, it is important to know whether a field's
- * prerequisites are satisfied before attempting to read it.)
- *
- * Sometimes a packet may contain multiple instances of a header.  For example,
- * a packet may contain multiple VLAN or MPLS headers, and tunnels can cause
- * any data field to recur.  OpenFlow and Open vSwitch do not address these
- * cases uniformly.  For VLAN and MPLS headers, only the outermost header is
- * accessible, so that inner headers may be accessed only by ``popping''
- * (removing) the outer header.  (Open vSwitch supports only a single VLAN
- * header in any case.)  For tunnels, e.g. GRE or VXLAN, the outer header and
- * inner headers are treated as different data fields.
- *
- * OpenFlow and Open vSwitch support some fields other than data fields.
- * "Metadata fields" relate to the origin or treatment of a packet, but they
- * are not extracted from the packet data itself.  One example is the physical
- * port on which a packet arrived at the switch.  "Register fields" act like
- * variables: they give an OpenFlow switch space for temporary storage while
- * processing a packet.  Existing metadata and register fields have no
- * prerequisites.
- *
- * A field's value consists of an integral number of bytes.  Most data fields
- * are copied directly from protocol headers, e.g. at layer 2, MFF_ETH_SRC is
- * copied from the Ethernet source address and MFF_ETH_DST from the destination
- * address.  Other data fields are copied from a packet with padding, usually
- * with zeros and in the most significant positions (see e.g. MFF_MPLS_LABEL)
- * but not always (see e.g. MFF_IP_DSCP).  A final category of data fields is
- * transformed in other ways as they are copied from the packets, to make them
- * more useful for matching, e.g. MFF_IP_FRAG describes whether a packet is a
- * fragment but it is not copied directly from the IP header.
+ * Refer to ovs-fields(7) for a detailed introduction to Open vSwitch fields.
  *
  *
  * Field specifications
@@ -115,8 +58,8 @@  struct match;
  *
  *       New fields should have only one name.
  *
- *     - Any number of paragraphs of free text that describe the field.  This
- *       is meant for human readers, so extract-ofp-fields ignores it.
+ *     - Any number of paragraphs of free text that describe the field.  These
+ *       are kept brief because the main description is in meta-flow.xml.
  *
  *     - A final paragraph that consists of a series of key-value pairs, one
  *       per line, in the form "key: value." where the period at the end of the
@@ -409,18 +352,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      *
      * Flags representing aspects of tunnel behavior.
      *
-     * This field currently only has a single flag defined:
-     *
-     *   - NX_TUN_FLAG_OAM: The tunnel protocol indicated that this is an
-     *                      OAM control packet.
-     *
-     * The switch may reject matches against values that it is not aware of.
-     *
-     * Note that it is possible for newer version of Open vSwitch to
-     * introduce additional flags with varying meaning. It is therefore not
-     * recommended to use an exact match on this field since the behavior of
-     * these new flags is unknown and should be ignored.
-     *
      * For non-tunneled packets, the value is 0.
      *
      * Type: be16 (low 1 bits).
@@ -743,42 +674,7 @@  enum OVS_PACKED_ENUM mf_field_id {
     /* "ct_state".
      *
      * Connection tracking state.  The field is populated by the NXAST_CT
-     * action. The following bit values describe the state of the connection:
-     *
-     *   - New (0x01): This is the beginning of a new connection.
-     *   - Established (0x02): This is part of an already existing connection.
-     *   - Related (0x04): This is a separate connection that is related to an
-     *                     existing connection.
-     *   - Reply (0x08): This flow is in the reply direction, ie it did not
-     *                   initiate the connection.
-     *   - Invalid (0x10): This flow could not be associated with a connection.
-     *                     This could be set for a variety of reasons,
-     *                     including (but not limited to):
-     *                     - L3/L4 protocol handler is not loaded/unavailable.
-     *                     - L3/L4 protocol handler determines that the packet
-     *                       is malformed or invalid for the current FSM stage.
-     *                     - Packets are unexpected length for protocol.
-     *   - Tracked (0x20): Connection tracking has occurred.
-     *
-     * The "Tracked" bit corresponds to the packet_state as described in the
-     * description of NXAST_CT action. The remaining bits correspond to
-     * connection state. The "New" bit implies that the connection state
-     * is uncommitted, while "Established" implies that it has previously been
-     * committed.
-     *
-     * There are additional constraints on the ct_state bits, listed in order
-     * of precedence below:
-     *
-     *   - If "Tracked" is unset, no other bits may be set.
-     *   - If "Tracked" is set, one or more other bits may be set.
-     *   - If "Invalid" is set, only the "Tracked" bit is also set.
-     *   - The "New" and "Established" bits are mutually exclusive.
-     *   - The "New" and "Reply" bits are mutually exclusive.
-     *   - The "Related" bit may be set in conjunction with any other bits.
-     *     Connections that are identified as "Related" are separate
-     *     connections from the originating connection, so must be committed
-     *     separately. All packets for a related connection will have the
-     *     "Related" bit set (not just the initial packet).
+     * action.
      *
      * Type: be32.
      * Maskable: bitwise.
@@ -894,15 +790,7 @@  enum OVS_PACKED_ENUM mf_field_id {
 #if FLOW_N_XREGS == 8
     /* "xreg<N>".
      *
-     * OpenFlow 1.5 ``extended register".  Each extended register
-     * overlays two of the Open vSwitch extension 32-bit registers:
-     * xreg0 overlays reg0 and reg1, with reg0 supplying the
-     * most-significant bits of xreg0 and reg1 the least-significant.
-     * xreg1 similarly overlays reg2 and reg3, and so on.
-     *
-     * These registers were introduced in OpenFlow 1.5, but EXT-244 in the ONF
-     * JIRA also publishes them as a (draft) OpenFlow extension to OpenFlow
-     * 1.3.
+     * OpenFlow 1.5 ``extended register".
      *
      * Type: be64.
      * Maskable: bitwise.
@@ -927,11 +815,7 @@  enum OVS_PACKED_ENUM mf_field_id {
 #if FLOW_N_XXREGS == 4
     /* "xxreg<N>".
      *
-     * ``extended-extended register".  Each of these extended registers
-     * overlays four of the Open vSwitch extension 32-bit registers:
-     * xxreg0 overlays reg0 through reg3, with reg0 supplying the
-     * most-significant bits of xxreg0 and reg3 the least-significant.
-     * xxreg1 similarly overlays reg4 and reg7.
+     * ``extended-extended register".
      *
      * Type: be128.
      * Maskable: bitwise.
@@ -964,8 +848,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      *
      * Source address in Ethernet header.
      *
-     * This field was not maskable before Open vSwitch 1.8.
-     *
      * Type: MAC.
      * Maskable: bitwise.
      * Formatting: Ethernet.
@@ -982,10 +864,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      *
      * Destination address in Ethernet header.
      *
-     * Before Open vSwitch 1.8, the allowed masks were restricted to
-     * 00:00:00:00:00:00, fe:ff:ff:ff:ff:ff, 01:00:00:00:00:00,
-     * ff:ff:ff:ff:ff:ff.
-     *
      * Type: MAC.
      * Maskable: bitwise.
      * Formatting: Ethernet.
@@ -1002,11 +880,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      *
      * Packet's Ethernet type.
      *
-     * For an Ethernet II packet this is taken from the Ethernet header.  For
-     * an 802.2 LLC+SNAP header with OUI 00-00-00 this is taken from the SNAP
-     * header.  A packet that has neither format has value 0x05ff
-     * (OFP_DL_TYPE_NOT_ETH_TYPE).
-     *
      * For a packet with an 802.1Q header, this is the type of the encapsulated
      * frame.
      *
@@ -1040,36 +913,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      * (TCI) field, with the CFI bit forced to 1.  For a packet with no 802.1Q
      * header, this has value 0.
      *
-     * This field can be used in various ways:
-     *
-     *   - If it is not constrained at all, the nx_match matches packets
-     *     without an 802.1Q header or with an 802.1Q header that has any TCI
-     *     value.
-     *
-     *   - Testing for an exact match with 0 matches only packets without an
-     *     802.1Q header.
-     *
-     *   - Testing for an exact match with a TCI value with CFI=1 matches
-     *     packets that have an 802.1Q header with a specified VID and PCP.
-     *
-     *   - Testing for an exact match with a nonzero TCI value with CFI=0 does
-     *     not make sense.  The switch may reject this combination.
-     *
-     *   - Testing with a specific VID and CFI=1, with nxm_mask=0x1fff, matches
-     *     packets that have an 802.1Q header with that VID (and any PCP).
-     *
-     *   - Testing with a specific PCP and CFI=1, with nxm_mask=0xf000, matches
-     *     packets that have an 802.1Q header with that PCP (and any VID).
-     *
-     *   - Testing with nxm_value=0, nxm_mask=0x0fff matches packets with no
-     *     802.1Q header or with an 802.1Q header with a VID of 0.
-     *
-     *   - Testing with nxm_value=0, nxm_mask=0xe000 matches packets with no
-     *     802.1Q header or with an 802.1Q header with a PCP of 0.
-     *
-     *   - Testing with nxm_value=0, nxm_mask=0xefff matches packets with no
-     *     802.1Q header or with an 802.1Q header with both VID and PCP of 0.
-     *
      * Type: be16.
      * Maskable: bitwise.
      * Formatting: hexadecimal.
@@ -1399,42 +1242,6 @@  enum OVS_PACKED_ENUM mf_field_id {
      *
      * IP fragment information.
      *
-     * This field has three possible values:
-     *
-     *   - A packet that is not an IP fragment has value 0.
-     *
-     *   - A packet that is an IP fragment with offset 0 (the first fragment)
-     *     has bit 0 set and thus value 1.
-     *
-     *   - A packet that is an IP fragment with nonzero offset has bits 0 and 1
-     *     set and thus value 3.
-     *
-     * NX_IP_FRAG_ANY and NX_IP_FRAG_LATER are declared to symbolically
-     * represent the meanings of bits 0 and 1.
-     *
-     * The switch may reject matches against values that can never appear.
-     *
-     * It is important to understand how this field interacts with the OpenFlow
-     * IP fragment handling mode:
-     *
-     *   - In OFPC_FRAG_DROP mode, the OpenFlow switch drops all IP fragments
-     *     before they reach the flow table, so every packet that is available
-     *     for matching will have value 0 in this field.
-     *
-     *   - Open vSwitch does not implement OFPC_FRAG_REASM mode, but if it did
-     *     then IP fragments would be reassembled before they reached the flow
-     *     table and again every packet available for matching would always
-     *     have value 0.
-     *
-     *   - In OFPC_FRAG_NORMAL mode, all three values are possible, but
-     *     OpenFlow 1.0 says that fragments' transport ports are always 0, even
-     *     for the first fragment, so this does not provide much extra
-     *     information.
-     *
-     *   - In OFPC_FRAG_NX_MATCH mode, all three values are possible.  For
-     *     fragments with offset 0, Open vSwitch makes L4 header information
-     *     available.
-     *
      * Type: u8 (low 2 bits).
      * Maskable: bitwise.
      * Formatting: frag.
diff --git a/lib/automake.mk b/lib/automake.mk
index 88344a3..29a6d73 100644
--- a/lib/automake.mk
+++ b/lib/automake.mk
@@ -494,10 +494,12 @@  lib/dirs.c: lib/dirs.c.in Makefile
 	mv lib/dirs.c.tmp lib/dirs.c
 
 lib/meta-flow.inc: $(srcdir)/build-aux/extract-ofp-fields include/openvswitch/meta-flow.h
-	$(AM_V_GEN)$(run_python) $^ --meta-flow > $@.tmp && mv $@.tmp $@
+	$(AM_V_GEN)$(run_python) $< meta-flow $(srcdir)/include/openvswitch/meta-flow.h > $@.tmp
+	$(AM_V_at)mv $@.tmp $@
 lib/meta-flow.lo: lib/meta-flow.inc
-lib/nx-match.inc: $(srcdir)/build-aux/extract-ofp-fields include/openvswitch/meta-flow.h
-	$(AM_V_GEN)$(run_python) $^ --nx-match > $@.tmp && mv $@.tmp $@
+lib/nx-match.inc: $(srcdir)/build-aux/extract-ofp-fields include/openvswitch/meta-flow.h 
+	$(AM_V_GEN)$(run_python) $< nx-match $(srcdir)/include/openvswitch/meta-flow.h > $@.tmp
+	$(AM_V_at)mv $@.tmp $@
 lib/nx-match.lo: lib/nx-match.inc
 CLEANFILES += lib/meta-flow.inc lib/nx-match.inc
 EXTRA_DIST += build-aux/extract-ofp-fields
@@ -534,3 +536,12 @@  lib-install-data-local:
 	$(MKDIR_P) $(DESTDIR)$(LOGDIR)
 	$(MKDIR_P) $(DESTDIR)$(DBDIR)
 	$(MKDIR_P) $(DESTDIR)$(sysconfdir)/openvswitch
+
+man_MANS += lib/ovs-fields.7
+lib/ovs-fields.7: $(srcdir)/build-aux/extract-ofp-fields include/openvswitch/meta-flow.h lib/meta-flow.xml
+	$(AM_V_GEN)PYTHONIOENCODING=utf8 $(run_python) $< \
+            --ovs-version=$(VERSION) ovs-fields \
+	    $(srcdir)/include/openvswitch/meta-flow.h \
+            $(srcdir)/lib/meta-flow.xml > $@.tmp
+	$(AM_V_at)mv $@.tmp $@
+EXTRA_DIST += lib/meta-flow.xml
diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
new file mode 100644
index 0000000..1b646f5
--- /dev/null
+++ b/lib/meta-flow.xml
@@ -0,0 +1,4163 @@ 
+<?xml version="1.0" encoding="utf-8"?>
+<fields>
+  <h1>Introduction</h1>
+
+  <p>
+    This document aims to comprehensively document all of the fields,
+    both standard and non-standard, supported by OpenFlow or Open
+    vSwitch, regardless of origin.
+  </p>
+
+  <h2>Fields</h2>
+
+  <p>
+    A <dfn>field</dfn> is a property of a packet.  Most familiarly, <dfn>data
+    fields</dfn> are fields that can be extracted from a packet.  Most data
+    fields are copied directly from protocol headers, e.g. at layer 2, the
+    Ethernet source and destination addresses, or the VLAN ID; at layer 3, the
+    IPv4 or IPv6 source and destination; and at layer 4, the TCP or UDP ports.
+    Other data fields are computed, e.g. <ref field="ip_frag"/> describes
+    whether a packet is a fragment but it is not copied directly from the IP
+    header.
+  </p>
+
+  <p>
+    Some data fields, called <dfn>root fields</dfn>, are always present as a
+    consequence of the basic networking technology in use.  The Ethernet header
+    fields are root fields in current versions of Open vSwitch, though future
+    versions might support other roots.  (Currently, to support LISP tunnels,
+    which do not encapsulate an Ethernet header, Open vSwitch synthesizes one.)
+  </p>
+
+  <!-- future directions: EXT-112 -->
+  <p>
+    Other data fields are not always present.  A packet contains ARP fields,
+    for example, only when its Ethernet header indicates the Ethertype for ARP,
+    0x0806.  In this documentation, we say that a field is
+    <dfn>applicable</dfn> when it is it present in a packet, and
+    <dfn>inapplicable</dfn> when it is not.  (These are not standard terms.)
+    We refer to the conditions that determine whether a field is applicable as
+    <dfn>prerequisites</dfn>.  Some VLAN-related fields are a special case:
+    these fields are always applicable, but have a designated value or bit that
+    indicates whether a VLAN header is present, with the remaining values or
+    bits indicating the VLAN header's content (if it is present).  <!-- XXX
+    also ethertype -->
+  </p>
+
+  <p>
+    An inapplicable field does not have a value, not even a nominal
+    ``value'' such as all-zero-bits.  In many circumstances, OpenFlow
+    and Open vSwitch allow references only to applicable fields.  For
+    example, one may match (see <cite>Matching</cite>, below) a given
+    field only if the match includes the field's prerequisite,
+    e.g. matching an ARP field is only allowed if one also matches on
+    Ethertype 0x0806.
+  </p>
+
+  <p>
+    Sometimes a packet may contain multiple instances of a header.
+    For example, a packet may contain multiple VLAN or MPLS headers,
+    and tunnels can cause any data field to recur.  OpenFlow and Open
+    vSwitch do not address these cases uniformly.  For VLAN and MPLS
+    headers, only the outermost header is accessible, so that inner
+    headers may be accessed only by ``popping'' (removing) the outer
+    header.  (Open vSwitch supports only a single VLAN header in any
+    case.)  For tunnels, e.g. GRE or VXLAN, the outer header and inner
+    headers are treated as different data fields.
+  </p>
+
+  <p>
+    Many network protocols are built in layers as a stack of concatenated
+    headers.  Each header typically contains a ``next type'' field that
+    indicates the type of the protocol header that follows, e.g. Ethernet
+    contains an Ethertype and IPv4 contains a IP protocol type.  The
+    exceptional cases, where protocols are layered but an outer layer does not
+    indicate the protocol type for the inner layer, or gives only an ambiguous
+    indication, are troublesome.  An MPLS header, for example, only indicates
+    whether another MPLS header or some other protocol follows, and in the
+    latter case the inner protocol must be known from the context.  In these
+    exceptional cases, OpenFlow and Open vSwitch cannot provide insight into
+    the inner protocol data fields without additional context, and thus they
+    treat all later data fields as inapplicable until an OpenFlow action
+    explicitly specifies what protocol follows.  In the case of MPLS, the
+    OpenFlow ``pop MPLS'' action that removes the last MPLS header from a
+    packet provides this context, as the Ethertype of the payload.  See
+    <cite>Layer 2.5: MPLS</cite> for more information.
+  </p>
+
+  <p>
+    OpenFlow and Open vSwitch support some fields other than data
+    fields.  <dfn>Metadata fields</dfn> relate to the origin or
+    treatment of a packet, but they are not extracted from the packet
+    data itself.  One example is the physical port on which a packet
+    arrived at the switch.  <dfn>Register fields</dfn> act like
+    variables: they give an OpenFlow switch space for temporary
+    storage while processing a packet.  Existing metadata and register
+    fields have no prerequisites.
+  </p>
+
+  <p>
+    A field's value consists of an integral number of bytes.  For data
+    fields, sometimes those bytes are taken directly from the packet.
+    Other data fields are copied from a packet with padding (usually
+    with zeros and in the most significant positions).  The remaining
+    data fields are transformed in other ways as they are copied from
+    the packets, to make them more useful for matching.
+  </p>
+
+  <h2>Matching</h2>
+
+  <p>
+    The most important use of fields in OpenFlow is
+    <dfn>matching</dfn>, to determine whether particular field values
+    agree with a set of constraints called a <dfn>match</dfn>.  A
+    match consists of zero or more constraints on individual fields,
+    all of which must be met to satisfy the match.  (A match that
+    contain no constraints is always satisfied.)  OpenFlow and Open
+    vSwitch support a number of forms of matching on individual
+    fields:
+  </p>
+
+  <dl>
+    <dt><dfn>Exact match</dfn>, e.g. <code>nw_src=10.1.2.3</code></dt>
+    <dd>
+      <p>
+	Only a particular value of the field is matched; for example, only one
+	particular source IP address.  Exact matches are written as
+	<code><var>field</var>=<var>value</var></code>.  The forms accepted for
+	<var>value</var> depend on the field.
+      </p>
+
+      <p>
+	All fields support exact matches.
+      </p>
+    </dd>
+
+    <dt>
+      <dfn>Bitwise match</dfn>, e.g. <code>nw_src=10.1.0.0/255.255.0.0</code>
+    </dt>
+    <dd>
+      <p>
+	Specific bits in the field must have specified values; for example,
+	only source IP addresses in a particular subnet.  Bitwise matches are
+	written as
+	<code><var>field</var>=<var>value</var>/<var>mask</var></code>, where
+	<var>value</var> and <var>mask</var> take one of the forms accepted for
+	an exact match on <var>field</var>.  Some fields accept other forms for
+	bitwise matches; for example, <code>nw_src=10.1.0.0/255.255.0.0</code>
+	may also be written <code>nw_src=10.1.0.0/16</code>.
+      </p>
+
+      <p>
+        Most OpenFlow switches do not allow every bitwise matching on every
+        field (and before OpenFlow 1.2, the protocol did not even provide for
+        the possibility for most fields).  Even switches that do allow bitwise
+        matching on a given field may restrict the masks that are allowed, e.g.
+        by allowing matches only on contiguous sets of bits starting from the
+        most significant bit, that is, ``CIDR'' masks [RFC 4632].  Open vSwitch
+        does not allows bitwise matching on every field, but it allows
+        arbitrary bitwise masks on any field that does support bitwise
+        matching.  (Older versions had some restrictions, as documented in the
+        descriptions of individual fields.)
+      </p>
+    </dd>
+
+    <dt><dfn>Wildcard</dfn>, e.g. ``any <code>ip_src</code>''</dt>
+    <dd>
+      <p>
+	The value of the field is not constrained.  Wildcarded fields may be
+	written as <code><var>field</var>=*</code>, although it is unusual to
+	mention them at all.  (When specifying a wildcard explicitly in a
+	command invocation, be sure to using quoting to protect against shell
+	expansion.)
+      </p>
+
+      <p>
+	There is a tiny difference between wildcarding a field and not
+	specifying any match on a field: wildcarding a field requires
+	satisfying the field's prerequisites.
+      </p>
+    </dd>
+  </dl>
+
+  <p>
+    Some types of matches on individual fields cannot be expressed directly
+    with OpenFlow and Open vSwitch.  These can be expressed indirectly:
+  </p>
+
+  <dl>
+    <dt><dfn>Set match</dfn>, e.g. ``<code>tcp_dst</code> ∈ {80, 443,
+    8080}''</dt>
+    <dd>
+      <p>
+	The value of a field is one of a specified set of values; for
+	example, the TCP destination port is 80, 443, or 8080.
+      </p>
+
+      <p>
+	For matches used in flows (see <cite>Flows</cite>, below), multiple
+	flows can simulate set matches.
+      </p>
+    </dd>
+
+    <dt><dfn>Range match</dfn>, e.g. ``1000 ≤ <code>tcp_dst</code> ≤
+    1999''</dt>
+    <dd>
+      <p>
+	The value of the field must lie within a numerical range, for
+	example, TCP destination ports between 1000 and 1999.
+      </p>
+
+      <p>
+	Range matches can be expressed as a collection of bitwise matches.  For
+	example, suppose that the goal is to match TCP source ports 1000 to
+	1999, inclusive.  The binary representations of 1000 and 1999 are:
+      </p>
+
+      <pre fixed="yes">
+01111101000
+11111001111
+      </pre>
+
+      <p>
+	The following series of bitwise matches will match 1000 and
+	1999 and all the values in between:
+      </p>
+
+      <pre fixed="yes">
+01111101xxx
+0111111xxxx
+10xxxxxxxxx
+110xxxxxxxx
+1110xxxxxxx
+11110xxxxxx
+1111100xxxx
+      </pre>
+
+      <p>
+	which can be written as the following matches:
+      </p>
+
+      <pre>
+tcp,tp_src=0x03e8/0xfff8
+tcp,tp_src=0x03f0/0xfff0
+tcp,tp_src=0x0400/0xfe00
+tcp,tp_src=0x0600/0xff00
+tcp,tp_src=0x0700/0xff80
+tcp,tp_src=0x0780/0xffc0
+tcp,tp_src=0x07c0/0xfff0
+      </pre>
+    </dd>
+
+    <dt><dfn>Inequality match</dfn>, e.g. ``<code>tcp_dst</code> ≠ 80''</dt>
+    <dd>
+      <p>
+	The value of the field differs from a specified value, for
+	example, all TCP destination ports except 80.
+      </p>
+
+      <p>
+        An inequality match on an <var>n</var>-bit field can be expressed as a
+        disjunction of <var>n</var> 1-bit matches.  For example, the inequality
+        match ``<code>vlan_pcp</code> ≠ 5'' can be expressed as
+        ``<code>vlan_pcp</code> = 0/4 or <code>vlan_pcp</code> = 2/2 or
+        <code>vlan_pcp</code> = 0/1.''  For matches used in flows (see
+        <cite>Flows</cite>, below), sometimes one can more compactly express
+        inequality as a higher-priority flow that matches the exceptional case
+        paired with a lower-priority flow that matches the general case.
+      </p>
+
+      <p>
+        Alternatively, an inequality match may be converted to a pair of range
+        matches, e.g. <code>tcp_src ≠ 80</code> may be expressed as ``0 ≤
+        <code>tcp_src</code> &lt; 80 or 80 &lt; <code>tcp_src</code> ≤ 65535'',
+        and then each range match may in turn be converted to a bitwise match.
+      </p>
+    </dd>
+
+    <dt><dfn>Conjunctive match</dfn>, e.g. ``<code>tcp_src</code> ∈ {80, 443, 8080} and <code>tcp_dst</code> ∈ {80, 443, 8080}''</dt>
+    <dd>
+      As an OpenFlow extension, Open vSwitch supports matching on conditions on
+      conjunctions of the previously mentioned forms of matching.  See the
+      documentation for <ref field="conj_id"/> for more information.
+    </dd>
+  </dl>
+
+  <p>
+    All of these supported forms of matching are special cases of bitwise
+    matching.  In some cases this influences the design of field values.  <ref
+    field="ip_frag"/> is the most prominent example: it is designed to make all
+    of the practically useful checks for IP fragmentation possible as a single
+    bitwise match.
+  </p>
+
+  <h3>Shorthands</h3>
+
+  <p>
+    Some matches are very commonly used, so Open vSwitch accepts shorthand
+    notations.  In some cases, Open vSwitch also uses shorthand notations when
+    it displays matches.  The following shorthands are defined, with their long
+    forms shown on the right side:
+  </p>
+
+  <dl>
+    <dt><code>ip</code></dt>     <dd><code>eth_type=0x0800</code></dd>
+    <dt><code>ipv6</code></dt>   <dd><code>eth_type=0x86dd</code></dd>
+    <dt><code>icmp</code></dt>   <dd><code>eth_type=0x0800,ip_proto=1</code></dd>
+    <dt><code>icmp6</code></dt>  <dd><code>eth_type=0x86dd,ip_proto=58</code></dd>
+    <dt><code>tcp</code></dt>    <dd><code>eth_type=0x0800,ip_proto=6</code></dd>
+    <dt><code>tcp6</code></dt>   <dd><code>eth_type=0x86dd,ip_proto=6</code></dd>
+    <dt><code>udp</code></dt>    <dd><code>eth_type=0x0800,ip_proto=17</code></dd>
+    <dt><code>udp6</code></dt>   <dd><code>eth_type=0x86dd,ip_proto=17</code></dd>
+    <dt><code>sctp</code></dt>   <dd><code>eth_type=0x0800,ip_proto=132</code></dd>
+    <dt><code>sctp6</code></dt>  <dd><code>eth_type=0x86dd,ip_proto=132</code></dd>
+    <dt><code>arp</code></dt>    <dd><code>eth_type=0x0806</code></dd>
+    <dt><code>rarp</code></dt>   <dd><code>eth_type=0x8035</code></dd>
+    <dt><code>mpls</code></dt>   <dd><code>eth_type=0x8847</code></dd>
+    <dt><code>mplsm</code></dt>  <dd><code>eth_type=0x8848</code></dd>
+  </dl>
+
+  <h2>Evolution of OpenFlow Fields</h2>
+
+  <p>
+    The discussion so far applies to all OpenFlow and Open vSwitch
+    versions.  This section starts to draw in specific information by
+    explaining, in broad terms, the treatment of fields and matches in
+    each OpenFlow version.
+  </p>
+
+  <h3>OpenFlow 1.0</h3>
+
+  <p>
+    OpenFlow 1.0 defined the OpenFlow protocol format of a match as a
+    fixed-length data structure that could match on the following
+    fields:
+  </p>
+
+  <ul>
+    <li>Ingress port.</li>
+    <li>Ethernet source and destination MAC.</li>
+    <li>Ethertype (with a special value to match frames that lack an
+    Ethertype).</li>
+    <li>VLAN ID and priority.</li>
+    <li>IPv4 source, destination, protocol, and DSCP.</li>
+    <li>TCP source and destination port.</li>
+    <li>UDP source and destination port.</li>
+    <li>ICMPv4 type and code.</li>
+    <li>ARP IPv4 addresses (SPA and TPA) and opcode.</li>
+  </ul>
+
+  <p>
+    Each supported field corresponded to some member of the data
+    structure.  Some members represented multiple fields, in the case
+    of the TCP, UDP, ICMPv4, and ARP fields whose presence is mutually
+    exclusive.  This also meant that some members were poor fits for
+    their fields: only the low 8 bits of the 16-bit ARP opcode could
+    be represented, and the ICMPv4 type and code were padded with 8 bits
+    of zeros to fit in the 16-bit members primarily meant for TCP and
+    UDP ports.  An additional bitmap member indicated, for each
+    member, whether its field should be an ``exact'' or ``wildcarded''
+    match (see <cite>Matching</cite>), with additional support for
+    CIDR prefix matching on the IPv4 source and destination fields.
+  </p>
+
+  <p>
+    Simplicity was recognized early on as the main virtue of this
+    approach.  Obviously, any fixed-length data structure cannot
+    support matching new protocols that do not fit.  There was no
+    room, for example, for matching IPv6 fields, which was not a
+    priority at the time.  Lack of room to support matching the
+    Ethernet addresses inside ARP packets actually caused more of a
+    design problem later, leading to an Open vSwitch extension action
+    specialized for dropping ``spoofed'' ARP packets in which the
+    frame and ARP Ethernet source addressed differed.  (This extension
+    was never standardized.  Open vSwitch dropped support for it a few
+    releases after it added support for full ARP matching.)
+  </p>
+
+  <p>
+    The design of the OpenFlow fixed-length matches also illustrates
+    compromises, in both directions, between the strengths and
+    weaknesses of software and hardware that have always influenced
+    the design of OpenFlow.  Support for matching ARP fields that do
+    fit in the data structure was only added late in the design
+    process (and remained optional in OpenFlow 1.0), for example,
+    because common switch ASICs did not support matching these fields.
+  </p>
+
+  <p>
+    The compromises in favor of software occurred for more complicated
+    reasons.  The OpenFlow designers did not know how to implement
+    matching in software that was fast, dynamic, and general.  (A way
+    was later found [Srinivasan].)  Thus, the designers sought to
+    support dynamic, general matching that would be fast in realistic
+    special cases, in particular when all of the matches were
+    <dfn>microflows</dfn>, that is, matches that specify every field
+    present in a packet, because such matches can be implemented as a
+    single hash table lookup.  Contemporary research supported the
+    feasibility of this approach: the number of microflows in a campus
+    network had been measured to peak at about 10,000 [Casado, section
+    3.2].  (Calculations show that this can only be true in a lightly
+    loaded network [Pepelnjak].)
+  </p>
+
+  <p>
+    As a result, OpenFlow 1.0 required switches to treat microflow
+    matches as the highest possible priority.  This let software
+    switches perform the microflow hash table lookup first. Only on
+    failure to match a microflow did the switch need to fall back to
+    checking the more general and presumed slower matches.  Also, the
+    OpenFlow 1.0 flow match was minimally flexible, with no support
+    for general bitwise matching, partly on the basis that this seemed
+    more likely amenable to relatively efficient software
+    implementation. (CIDR masking for IPv4 addresses was added
+    relatively late in the OpenFlow 1.0 design process.)
+  </p>
+
+  <p>
+    Microflow matching was later discovered to aid some hardware
+    implementations.  The TCAM chips used for matching in hardware do
+    not support priority in the same way as OpenFlow but instead tie
+    priority to ordering [Pagiamtzis].  Thus, adding a new match with
+    a priority between the priorities of existing matches can require
+    reordering an arbitrary number of TCAM entries.  On the other
+    hand, when microflows are highest priority, they can be managed as
+    a set-aside portion of the TCAM entries.
+  </p>
+
+  <p>
+    The emphasis on matching microflows also led designers to
+    carefully consider the bandwidth requirements between switch and
+    controller: to maximize the number of microflow setups per second,
+    one must minimize the size of each flow's description.  This
+    favored the fixed-length format in use, because it expressed
+    common TCP and UDP microflows in fewer bytes than more flexible
+    ``type-length-value'' (TLV) formats.  (Early versions of OpenFlow
+    also avoided TLVs in general to head off protocol fragmentation.)
+  </p>
+
+  <h4>Inapplicable Fields</h4>
+
+  <p>
+    OpenFlow 1.0 does not clearly specify how to treat inapplicable
+    fields.  The members for inapplicable fields are always present in
+    the match data structure, as are the bits that indicate whether
+    the fields are matched, and the ``correct'' member and bit values
+    for inapplicable fields is unclear.  OpenFlow 1.0 implementations
+    changed their behavior over time as priorities shifted.  The early
+    OpenFlow reference implementation, motivated to make every flow a
+    microflow to enable hashing, treated inapplicable fields as exact
+    matches on a value of 0.  Initially, this behavior was implemented
+    in the reference controller only.
+  </p>
+
+  <p>
+    Later, the reference switch was also changed to actually force any
+    wildcarded inapplicable fields into exact matches on 0.  The
+    latter behavior sometimes caused problems, because the modified
+    flow was the one reported back to the controller later when it
+    queried the flow table, and the modifications sometimes meant that
+    the controller could not properly recognize the flow that it had
+    added.  In retrospect, perhaps this problem should have alerted
+    the designers to a design error, but the ability to use a single
+    hash table was held to be more important than almost every other
+    consideration at the time.
+  </p>
+
+  <p>
+    When more flexible match formats were introduced much later, they
+    disallowed any mention of inapplicable fields as part of a match.
+    This raised the question of how to translate between this new
+    format and the OpenFlow 1.0 fixed format.  It seemed somewhat
+    inconsistent and backward to treat fields as exact-match in one
+    format and forbid matching them in the other, so instead the
+    treatment of inapplicable fields in the fixed-length format was
+    changed from exact match on 0 to wildcarding.  (A better
+    classifier had by now eliminated software performance problems
+    with wildcards.)
+  </p>
+
+  <p>
+    The OpenFlow 1.0.1 errata (released only in 2012) added some
+    additional explanation [OpenFlow 1.0.1, section 3.4], but it did
+    not mandate specific behavior because of variation among
+    implementations.
+  </p>
+
+  <h3>OpenFlow 1.1</h3>
+
+  <p>
+    The OpenFlow 1.1 protocol match format was designed as a type/length/value
+    (TLV) format to allow for future flexibility.  The specification
+    standardized only a single type <code>OFPMT_STANDARD</code> (0) with a
+    fixed-size payload, described here.  The additional fields and bitwise
+    masks in OpenFlow 1.1 cause this match structure to be over twice as large
+    as in OpenFlow 1.0, 88 bytes versus 40.
+  </p>
+
+  <p>
+    OpenFlow 1.1 added support for the following fields:
+  </p>
+
+  <ul>
+    <li>SCTP source and destination port.</li>
+    <li>MPLS label and traffic control (TC) fields.</li>
+    <li>One 64-bit register (named ``metadata'').</li>
+  </ul>
+
+  <p>
+    OpenFlow 1.1 increased the width of the ingress port number field (and all
+    other port numbers in the protocol) from 16 bits to 32 bits.
+  </p>
+
+  <p>
+    OpenFlow 1.1 increased matching flexibility by introducing
+    arbitrary bitwise matching on Ethernet and IPv4 address fields and
+    on the new ``metadata'' register field.  Switches were not
+    required to support all possible masks [OpenFlow 1.1, section
+    4.3].
+  </p>
+
+  <p>
+    By a strict reading of the specification, OpenFlow 1.1 removed
+    support for matching ICMPv4 type and code [OpenFlow 1.1, section
+    A.2.3], but this is likely an editing error because ICMP
+    matching is described elsewhere [OpenFlow 1.1, Table 3, Table 4,
+    Figure 4].  Open vSwitch does support ICMPv4 type and code
+    matching with OpenFlow 1.1.
+  </p>
+
+  <p>
+    OpenFlow 1.1 avoided the pitfalls of inapplicable fields that
+    OpenFlow 1.0 encountered, by requiring the switch to ignore the
+    specified field values [OpenFlow 1.1, section A.2.3].  It also
+    implied that the switch that should ignore the bits that indicate
+    whether to match inapplicable fields.
+  </p>
+
+  <h4>Physical Ingress Port</h4>
+
+  <p>
+    OpenFlow 1.1 introduced a new pseudo-field, the physical ingress port.  The
+    physical ingress port is only a pseudo-field because it cannot be used for
+    matching.  It appears only one place in the protocol, in the ``packet-in''
+    message that passes a packet received at the switch to an OpenFlow
+    controller.
+  </p>
+
+  <p>
+    A packet's ingress port and physical ingress port are identical except for
+    packets processed by a switch feature such as bonding or tunneling that
+    makes a packet appear to arrive on a ``virtual'' port associated with the
+    bond or the tunnel.  For such packets, the ingress port is the virtual port
+    and the physical ingress port is, naturally, the physical port.  Open
+    vSwitch implements both bonding and tunneling, but its bonding
+    implementation does not use virtual ports and its tunnels are typically not
+    on the same OpenFlow switch as their physical ingress ports (which need not
+    be part of any switch), so the ingress port and physical ingress port are
+    always the same in Open vSwitch.
+  </p>
+
+  <h3>OpenFlow 1.2</h3>
+
+  <p>
+    OpenFlow 1.2 abandoned the fixed-length approach to matching.  One reason
+    was size, since adding support for IPv6 address matching (now seen as
+    important), with bitwise masks, would have added 64 bytes to the match
+    length, increasing it from 88 bytes in OpenFlow 1.1 to over 150 bytes.
+    Extensibility had also become important as controller writers increasingly
+    wanted support for new fields without having to change messages throughout
+    the OpenFlow protocol.  The challenges of carefully defining fixed-length
+    matches to avoid problems with inapplicable fields had also become clear
+    over time.
+  </p>
+
+  <p>
+    Therefore, OpenFlow 1.2 adopted a flow format using a flexible
+    type-length-value (TLV) representation, in which each TLV expresses a match
+    on one field.  These TLVs were in turn encapsulated inside the outer TLV
+    wrapper introduced in OpenFlow 1.1 with the new identifier
+    <code>OFPMT_OXM</code> (1).  (This wrapper fulfilled its intended purpose
+    of reducing the amount of churn in the protocol when changing match
+    formats; some messages that included matches remained unchanged from
+    OpenFlow 1.1 to 1.2 and later versions.)
+  </p>
+
+  <p>
+    OpenFlow 1.2 added support for the following fields:
+  </p>
+
+  <ul>
+    <li>ARP hardware addresses (SHA and THA).</li>
+    <li>IPv4 ECN.</li>
+    <li>IPv6 source and destination addresses, flow label, DSCP, ECN,
+    and protocol.</li>
+    <li>TCP, UDP, and SCTP port numbers when encapsulated inside IPv6.</li>
+    <li>ICMPv6 type and code.</li>
+    <li>ICMPv6 Neighbor Discovery target address and source and target
+    Ethernet addresses.</li>
+  </ul>
+
+  <!-- mention tun_id_from_cookie extension? -->
+
+  <p>
+    The OpenFlow 1.2 format, called <dfn>OXM</dfn> (<dfn>OpenFlow Extensible
+    Match</dfn>), was modeled closely on an extension to OpenFlow 1.0
+    introduced in Open vSwitch 1.1 called <dfn>NXM</dfn> (<dfn>Nicira Extended
+    Match</dfn>).  Each OXM or NXM TLV has the following format:
+  </p>
+
+  <diagram>
+    <header name="type">
+      <bits name="vendor/class" above="16" width=".75"/>
+      <bits name="field" above="7" width=".4"/>
+    </header>
+    <nospace/>
+    <header name="">
+      <bits name="M" above="1" width=".15"/>
+      <bits name="length" above="8" width=".4"/>
+    </header>
+    <header name="">
+      <bits name="body" above="length bytes" width="1.7"/>
+    </header>
+  </diagram>
+
+  <p>
+    The most significant 16 bits of the NXM or OXM header, called
+    <code>vendor</code> by NXM and <code>class</code> by OXM, identify
+    an organization permitted to allocate identifiers for fields.  NXM
+    allocates only two vendors, 0x0000 for fields supported by
+    OpenFlow 1.0 and 0x0001 for fields implemented as an Open vSwitch
+    extension.  OXM assigns classes as follows:
+  </p>
+
+  <dl>
+    <dt>0x0000 (<code>OFPXMC_NXM_0</code>).</dt>
+    <dt>0x0001 (<code>OFPXMC_NXM_1</code>).</dt>
+    <dd>Reserved for NXM compatibility.</dd>
+
+    <dt>0x0002 to 0x7fff</dt>
+    <dd>
+      Reserved for allocation to ONF members, but none yet assigned.
+    </dd>
+
+    <dt>0x8000 (<code>OFPXMC_OPENFLOW_BASIC</code>)</dt>
+    <dd>
+      Used for most standard OpenFlow fields.
+    </dd>
+
+    <dt>0x8001 (<code>OFPXMC_PACKET_REGS</code>)</dt>
+    <dd>
+      Used for packet register fields in OpenFlow 1.5 and later.
+    </dd>
+
+    <dt>0x8002 to 0xfffe</dt>
+    <dd>
+      Reserved for the OpenFlow specification.
+    </dd>
+
+    <dt>0xffff (<code>OFPXMC_EXPERIMENTER</code>)</dt>
+    <dd>Experimental use.</dd>
+  </dl>
+
+  <p>
+    When <code>class</code> is 0xffff, the OXM header is extended to 64 bits by
+    using the first 32 bits of the body as an <code>experimenter</code> field
+    whose most significant byte is zero and whose remaining bytes are an
+    Organizationally Unique Identifier (OUI) assigned by the IEEE [IEEE OUI],
+    as shown below.  OpenFlow says that support for experimenter fields is
+    optional.  Open vSwitch 2.4 and later does support them, primarily so that
+    it can support the <code>ONFOXM_ET_</code>* code points defined by official
+    Open Networking Foundation extensions to OpenFlow 1.3 in e.g. [TCP Flags
+    Match Field Extension].
+  </p>
+
+  <diagram>
+    <header name="type">
+      <bits name="class" above="16" below="0xffff" width=".75"/>
+      <bits name="field" above="7" width=".4"/>
+    </header>
+    <nospace/>
+    <header name="">
+      <bits name="HM" above="1" width=".25"/>
+      <bits name="length" above="8" width=".4"/>
+    </header>
+
+    <header name="experimenter">
+      <bits name="zero" above="8" below="0x00" width=".4"/>
+      <bits name="OUI" above="24" width="1"/>
+    </header>
+    <header name="">
+      <bits name="body" above="(length - 4) bytes" width="1.7"/>
+    </header>
+  </diagram>
+
+  <p>
+    Taken as a unit, <code>class</code> (or <code>vendor</code>),
+    <code>field</code>, and <code>experimenter</code> (when present) uniquely
+    identify a particular field.
+  </p>
+
+  <p>
+    When <code>hasmask</code> (abbreviated <code>HM</code> above) is 0, the OXM
+    is an exact match on an entire field.  In this case, the body (excluding
+    the experimenter field, if present) is a single value to be matched.
+  </p>
+
+  <p>
+    When <code>hasmask</code> is 1, the OXM is a bitwise match.  The body
+    (excluding the experimenter field) consists of a value to match, followed
+    by the bitwise mask to apply.  A 1-bit in the mask indicates that the
+    corresponding bit in the value should be matched and a 0-bit that it should
+    be ignored.  For example, for an IP address field, a value of 192.168.0.0
+    followed by a mask of 255.255.0.0 would match addresses in the
+    196.168.0.0/16 subnet.
+  </p>
+
+  <ul>
+    <li>
+      Some fields might not support masking at all, and some fields that do
+      support masking might restrict it to certain patterns.  For example,
+      fields that have IP address values might be restricted to CIDR masks.
+      The descriptions of individual fields note these restrictions.
+    </li>
+
+    <li>
+      An OXM TLV with a mask that is all zeros is not useful (although it is
+      not forbidden), because it is has the same effect as omitting the TLV
+      entirely.
+    </li>
+
+    <li>
+      It is not meaningful to pair a 0-bit in an OXM mask with a 1-bit in its
+      value, and Open vSwitch rejects such an OXM with the error
+      <code>OFPBMC_BAD_WILDCARDS</code>, as required by OpenFlow 1.3 and later.
+    </li>
+  </ul>
+
+  <p>
+    The <code>length</code> identifies the number of bytes in the body,
+    including the 4-byte <code>experimenter</code> header, if it is present.
+    Each OXM TLV has a fixed length; that is, given <code>class</code>,
+    <code>field</code>, <code>experimenter</code> (if present), and
+    <code>hasmask</code>, <code>length</code> is a constant.  The
+    <code>length</code> is included explicitly to allow software to minimally
+    parse OXM TLVs of unknown types.
+  </p>
+
+  <p>
+    OXM TLVs must be ordered so that a field's prerequisites are satisfied
+    before it is parsed.  For example, an OXM TLV that matches on the IPv4
+    source address field is only allowed following an OXM TLV that matches on
+    the Ethertype for IPv4.  Similarly, an OXM TLV that matches on the TCP
+    source port must follow a TLV that matches an Ethertype of IPv4 or IPv6 and
+    one that matches an IP protocol of TCP (in that order).  The order of OXM
+    TLVs is not otherwise restricted; no canonical ordering is defined.
+  </p>
+
+  <p>
+    A given field may be matched only once in a series of OXM TLVs.
+  </p>
+
+  <!-- EXT-482? -->
+
+  <h3>OpenFlow 1.3</h3>
+
+  <p>
+    OpenFlow 1.3 showed OXM to be largely successful, by adding new fields
+    without making any changes to how flow matches otherwise worked.  It added
+    OXMs for the following fields supported by Open vSwitch:
+  </p>
+
+  <ul>
+    <li>Tunnel ID for ports associated with e.g. VXLAN or keyed GRE.</li>
+    <li>MPLS ``bottom of stack'' (BOS) bit.</li>
+  </ul>
+
+  <p>
+    OpenFlow 1.3 also added OXMs for the following fields not documented here
+    and not yet implemented by Open vSwitch:
+  </p>
+
+  <ul>
+    <li>IPv6 extension header handling.</li>
+    <li>PBB I-SID.</li>
+  </ul>
+
+  <h3>OpenFlow 1.4</h3>
+
+  <p>
+    OpenFlow 1.4 added OXMs for the following fields not documented here and
+    not yet implemented by Open vSwitch:
+  </p>
+
+  <ul>
+    <li>PBB UCA.</li>
+  </ul>
+
+  <h3>OpenFlow 1.5</h3>
+
+  <p>
+    OpenFlow 1.5 added OXMs for the following fields supported by Open vSwitch:
+  </p>
+
+  <ul>
+    <li>TCP flags.</li>
+    <li>Packet registers.</li>
+    <li>The output port in the OpenFlow action set.</li>
+  </ul>
+
+  <p>
+    OpenFlow 1.5 also added OXMs for the following fields not documented here
+    and not yet implemented by Open vSwitch:
+  </p>
+
+  <ul>
+    <li>Packet type.</li>
+  </ul>
+
+  <h1>Fields Reference</h1>
+
+  <p>
+    The following sections document the fields that Open vSwitch supports.
+    Each section provides introductory material on a group of related fields,
+    followed by information on each individual field.  In addition to
+    field-specific information, each field begins with a table with entries for
+    the following important properties:
+  </p>
+
+  <dl>
+    <dt>Name</dt>
+    <dd>
+      The field's name, used for parsing and formatting the field, e.g. in
+      <code>ovs-ofctl</code> commands.  For historical reasons, some fields
+      have an additional name that is accepted as an alternative in parsing.
+      This name, when there is one, is listed as well, e.g. ``<code>tun</code>
+      (aka <code>tunnel_id</code>).''
+    </dd>
+
+    <dt>Width</dt>
+    <dd>
+      The field's width, always a multiple of 8 bits.  Some fields don't use
+      all of the bits, so this may be accompanied by an explanation.  For
+      example, OpenFlow embeds the 2-bit IP ECN field as as the low bits in an
+      8-bit byte, and so its width is expressed as ``8 bits (only the
+      least-significant 2 bits may be nonzero).''
+    </dd>
+
+    <dt>Format</dt>
+    <dd>
+      <p>
+        How a value for the field is formatted or parsed by, e.g.,
+        <code>ovs-ofctl</code>.  Some possibilities are generic:
+      </p>
+
+      <dl>
+        <dt>decimal</dt>
+        <dd>
+          Formats as a decimal number.  On input, accepts decimal numbers or
+          hexadecimal numbers prefixed by <code>0x</code>.
+        </dd>
+
+        <dt>hexadecimal</dt>
+        <dd>
+          Formats as a hexadecimal number prefixed by <code>0x</code>.  On
+          input, accepts decimal numbers or hexadecimal numbers prefixed by
+          <code>0x</code>.  (The default for parsing is <em>not</em>
+          hexadecimal: only a <code>0x</code> prefix causes input to be treated
+          as hexadecimal.)
+        </dd>
+
+        <dt>Ethernet</dt>
+        <dd>
+          Formats and accepts the common Ethernet address format
+          <code><var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var></code>.
+        </dd>
+
+        <dt>IPv4</dt>
+        <dd>
+          Formats and accepts the dotted-quad format
+          <code><var>a</var>.<var>b</var>.<var>c</var>.<var>d</var></code>.
+          For bitwise matches, formats and accepts
+          <code><var>address</var>/<var>length</var></code> CIDR notation in
+          addition to <code><var>address</var>/<var>mask</var></code>.
+        </dd>
+
+        <dt>IPv6</dt>
+        <dd>
+          Formats and accepts the common IPv6 address formats, plus CIDR
+          notation for bitwise matches.
+        </dd>
+
+        <dt>OpenFlow 1.0 port</dt>
+        <dd>
+          Accepts 16-bit port numbers in decimal, plus OpenFlow well-known port
+          names (e.g. <code>IN_PORT</code>) in uppercase or lowercase.
+        </dd>
+
+        <dt>OpenFlow 1.1+ port</dt>
+        <dd>
+          Same syntax as OpenFlow 1.0 ports but for 32-bit OpenFlow 1.1+ port
+          number fields.
+        </dd>
+      </dl>
+
+      <p>
+        Other, field-specific formats are explained along with their fields.
+      </p>
+    </dd>
+
+    <dt>Masking</dt>
+    <dd>
+      For most fields, this says ``arbitrary bitwise masks,'' meaning that a
+      flow may match any combination of bits in the field.  Some fields
+      instead say ``exact match only,'' which means that a flow that matches
+      on this field must match on the whole field instead of just certain
+      bits.  Either way, this reports masking support for the latest version
+      of Open vSwitch using OXM or NXM (that is, either OpenFlow 1.2+ or
+      OpenFlow 1.0 plus Open vSwitch NXM extensions).  In particular,
+      OpenFlow 1.0 (without NXM) and 1.1 don't always support masking even if
+      Open vSwitch itself does; refer to the <em>OpenFlow 1.0</em> and
+      <em>OpenFlow 1.1</em> rows to learn about masking with these protocol
+      versions.
+    </dd>
+
+    <dt>Prerequisites</dt>
+    <dd>
+      <p>
+        Requirements that must be met to match on this field.  For example,
+        <ref field="ip_src"/> has IPv4 as a prerequisite, meaning that a match
+        must include <code>eth_type=0x0800</code> to match on the IPv4 source
+        address.  The following prerequisites, with their requirements, are
+        currently in use:
+      </p>
+
+      <dl>
+        <dt>none</dt>
+        <dd>(no requirements)</dd>
+
+        <dt>VLAN VID</dt>
+        <dd><code>vlan_tci=0x1000/0x1000</code> (i.e. a VLAN header is
+        present)</dd>
+
+        <dt>ARP</dt>
+        <dd><code>eth_type=0x0806</code> (ARP) or <code>eth_type=0x8035</code> (RARP)</dd>
+
+        <dt>IPv4</dt>
+        <dd><code>eth_type=0x0800</code></dd>
+
+        <dt>IPv6</dt>
+        <dd><code>eth_type=0x86dd</code></dd>
+
+        <dt>IPv4/IPv6</dt>
+        <dd>IPv4 or IPv6</dd>
+
+        <dt>MPLS</dt>
+        <dd><code>eth_type=0x8847</code> or <code>eth_type=0x8848</code></dd>
+
+        <dt>TCP</dt>
+        <dd>IPv4/IPv6 and <code>ip_proto=6</code></dd>
+
+        <dt>UDP</dt>
+        <dd>IPv4/IPv6 and <code>ip_proto=17</code></dd>
+
+        <dt>SCTP</dt>
+        <dd>IPv4/IPv6 and <code>ip_proto=132</code></dd>
+
+        <dt>ICMPv4</dt>
+        <dd>IPv4 and <code>ip_proto=1</code></dd>
+
+        <dt>ICMPv6</dt>
+        <dd>IPv6 and <code>ip_proto=1</code></dd>
+
+        <dt>ND solicit</dt>
+        <dd>ICMPv6 and <code>icmp_type=135</code> and <code>icmp_code=0</code></dd>
+
+        <dt>ND advert</dt>
+        <dd>ICMPv6 and <code>icmp_type=136</code> and <code>icmp_code=0</code></dd>
+
+        <dt>ND</dt>
+        <dd>ND solicit or ND advert</dd>
+      </dl>
+
+      <p>
+        The TCP, UDP, and SCTP prerequisites also have the special requirement
+        that <code>nw_frag</code> is not being used to select ``later
+        fragments.''  This is because only the first fragment of a fragmented
+        IPv4 or IPv6 datagram contains the TCP or UDP header.
+      </p>
+    </dd>
+
+    <dt>Access</dt>
+    <dd>
+      Most fields are ``read/write,'' which means that common OpenFlow actions
+      like <code>set_field</code> can modify them.  Fields that are
+      ``read-only'' cannot be modified in these general-purpose ways, although
+      there may be others ways that actions can modify them.
+    </dd>
+
+    <dt>OpenFlow 1.0</dt>
+    <dt>OpenFlow 1.1</dt>
+    <dd>
+      These rows report the level of support that OpenFlow 1.0 or OpenFlow 1.1,
+      respectively, has for a field.  For OpenFlow 1.0, supported fields are
+      reported as either ``yes (exact match only)'' for fields that do not
+      support any bitwise masking or ``yes (CIDR match only)'' for fields that
+      support CIDR masking.  OpenFlow 1.1 supported fields report either ``yes
+      (exact match only)'' or simply ``yes'' for fields that do support
+      arbitrary masks.  These OpenFlow versions supported a fixed collection of
+      fields that cannot be extended, so many more fields are reported as ``not
+      supported.''
+    </dd>
+
+    <dt>OXM</dt>
+    <dt>NXM</dt>
+    <dd>
+      <p>
+        These rows report the OXM and NXM code points that correspond to a
+        given field.  Either or both may be ``none.''
+      </p>
+
+      <p>
+        A field that has only an OXM code point is usually one that was
+        standardized before it was added to Open vSwitch.  A field that has
+        only an NXM code point is usually one that is not yet standardized.
+        When a field has both OXM and NXM code points, it usually indicates
+        that it was introduced as an Open vSwitch extension under the NXM code
+        point, then later standardized under the OXM code point.  A field can
+        have more than one OXM code point if it was standardized in OpenFlow
+        1.4 or later and additionally introduced as an official ONF extension
+        for OpenFlow 1.3.  (A field that has neither OXM nor NXM code point is
+        typically an obsolete field that is supported in some other form using
+        OXM or NXM.)
+      </p>
+
+      <p>
+        Each code point in these rows is described in the form
+        ``<code>NAME</code> (<var>number</var>) since OpenFlow <var>spec</var>
+        and Open vSwitch <var>version</var>,''
+        e.g. ``<code>OXM_OF_ETH_TYPE</code> (5) since OpenFlow 1.2 and Open
+        vSwitch 1.7.'' The named OpenFlow <var>spec</var>, which is the version
+        of OpenFlow that standardized the code point, is omitted for NXM code
+        points because they are nonstandard.  The <var>version</var> is the
+        version of Open vSwitch that first supported the code point.  The
+        <code>NAME</code>, which specifies a name for the code point, starts
+        with a prefix that designates a class and, in some cases, a vendor, as
+        listed in the following table.  Refer back to <em>OpenFlow 1.2</em>
+        under <em>Evolution of OpenFlow Fields</em> for more information on
+        OXM/NXM classes and vendors.  Finally, <var>number</var> is the field
+        number within the class and vendor.
+      </p>
+
+      <oxm_classes/>
+    </dd>
+  </dl>
+
+  <group title="Conjunctive Match">
+    <p>
+      An individual OpenFlow flow can match only a single value for each field.
+      However, situations often arise where one wants to match one of a set of
+      values within a field or fields.  For matching a single field against a
+      set, it is straightforward and efficient to add multiple flows to the
+      flow table, one for each value in the set.  For example, one might use
+      the following flows to send packets with IP source address <var>a</var>,
+      <var>b</var>, <var>c</var>, or <var>d</var> to the OpenFlow controller:
+    </p>
+
+    <pre>
+      ip,ip_src=<var>a</var> actions=controller
+      ip,ip_src=<var>b</var> actions=controller
+      ip,ip_src=<var>c</var> actions=controller
+      ip,ip_src=<var>d</var> actions=controller
+    </pre>
+
+    <p>
+      Similarly, these flows send packets with IP destination address
+      <var>e</var>, <var>f</var>, <var>g</var>, or <var>h</var> to the OpenFlow
+      controller:
+    </p>
+
+    <pre>
+      ip,ip_dst=<var>e</var> actions=controller
+      ip,ip_dst=<var>f</var> actions=controller
+      ip,ip_dst=<var>g</var> actions=controller
+      ip,ip_dst=<var>h</var> actions=controller
+    </pre>
+
+    <p>
+      Installing all of the above flows in a single flow table yields a
+      disjunctive effect: a packet is sent to the controller if
+      <code>ip_src</code> ∈ {<var>a</var>,<var>b</var>,<var>c</var>,<var>d</var>}
+      or <code>ip_dst</code> ∈
+      {<var>e</var>,<var>f</var>,<var>g</var>,<var>h</var>} (or both).
+      (Pedantically, if both of the above sets of flows are present in the flow
+      table, they should have different priorities, because OpenFlow says that
+      the results are undefined when two flows with same priority can both match
+      a single packet.)
+    </p>
+
+    <p>
+      Suppose, on the other hand, one wishes to match conjunctively, that is, to
+      send a packet to the controller only if both <code>ip_src</code> ∈
+      {<var>a</var>,<var>b</var>,<var>c</var>,<var>d</var>} and
+      <code>ip_dst</code> ∈
+      {<var>e</var>,<var>f</var>,<var>g</var>,<var>h</var>}.  This requires 4 × 4
+      = 16 flows, one for each possible pairing of <code>ip_src</code> and
+      <code>ip_dst</code>.  That is acceptable for our small example, but it does
+      not gracefully extend to larger sets or greater numbers of dimensions.
+    </p>
+
+    <p>
+      The <code>conjunction</code> action is a solution for conjunctive matches
+      that is built into Open vSwitch.  A <code>conjunction</code> action ties groups of
+      individual OpenFlow flows into higher-level ``conjunctive flows''.  Each
+      group corresponds to one dimension, and each flow within the group matches
+      one possible value for the dimension.  A packet that matches one flow from
+      each group matches the conjunctive flow.
+    </p>
+
+    <p>
+      To implement a conjunctive flow with <code>conjunction</code>, assign the
+      conjunctive flow a 32-bit <var>id</var>, which must be unique within an
+      OpenFlow table.  Assign each of the <var>n</var> ≥ 2 dimensions a unique
+      number from 1 to <var>n</var>; the ordering is unimportant.  Add one flow
+      to the OpenFlow flow table for each possible value of each dimension with
+      <code>conjunction(<var>id</var>, <var>k</var>/<var>n</var>)</code> as the
+      flow's actions, where <var>k</var> is the number assigned to the flow's
+      dimension.  Together, these flows specify the conjunctive flow's match
+      condition.  When the conjunctive match condition is met, Open vSwitch looks
+      up one more flow that specifies the conjunctive flow's actions and receives
+      its statistics.  This flow is found by setting <code>conj_id</code> to the
+      specified <var>id</var> and then again searching the flow table.
+    </p>
+
+    <p>
+      The following flows provide an example.  Whenever the IP source is one of
+      the values in the flows that match on the IP source (dimension 1 of 2),
+      <em>and</em> the IP destination is one of the values in the flows that
+      match on IP destination (dimension 2 of 2), Open vSwitch searches for a
+      flow that matches <code>conj_id</code> against the conjunction ID (1234),
+      finding the first flow listed below.
+    </p>
+
+    <pre>
+      conj_id=1234 actions=controller
+      ip,ip_src=10.0.0.1 actions=conjunction(1234, 1/2)
+      ip,ip_src=10.0.0.4 actions=conjunction(1234, 1/2)
+      ip,ip_src=10.0.0.6 actions=conjunction(1234, 1/2)
+      ip,ip_src=10.0.0.7 actions=conjunction(1234, 1/2)
+      ip,ip_dst=10.0.0.2 actions=conjunction(1234, 2/2)
+      ip,ip_dst=10.0.0.5 actions=conjunction(1234, 2/2)
+      ip,ip_dst=10.0.0.7 actions=conjunction(1234, 2/2)
+      ip,ip_dst=10.0.0.8 actions=conjunction(1234, 2/2)
+    </pre>
+
+    <p>
+      Many subtleties exist:
+    </p>
+
+    <ul>
+      <li>
+        In the example above, every flow in a single dimension has the same form,
+        that is, dimension 1 matches on <code>ip_src</code> and dimension 2 on
+        <code>ip_dst</code>, but this is not a requirement.  Different flows
+        within a dimension may match on different bits within a field (e.g. IP
+        network prefixes of different lengths, or TCP/UDP port ranges as bitwise
+        matches), or even on entirely different fields (e.g. to match packets for
+        TCP source port 80 or TCP destination port 80).
+      </li>
+
+      <li>
+        The flows within a dimension can vary their matches across more than
+        one field, e.g. to match only specific pairs of IP source and
+        destination addresses or L4 port numbers.
+      </li>
+
+      <li>
+        A flow may have multiple <code>conjunction</code> actions, with different
+        <code>id</code> values.  This is useful for multiple conjunctive flows with
+        overlapping sets.  If one conjunctive flow matches packets with both
+        <code>ip_src</code> ∈ {<var>a</var>,<var>b</var>} and <code>ip_dst</code> ∈
+        {<var>d</var>,<var>e</var>} and a second conjunctive flow matches <code>ip_src</code>
+        ∈ {<var>b</var>,<var>c</var>} and <code>ip_dst</code> ∈ {<var>f</var>,<var>g</var>}, for
+        example, then the flow that matches <code>ip_src=</code><var>b</var> would have two
+        <code>conjunction</code> actions, one for each conjunctive flow.  The order
+        of <code>conjunction</code> actions within a list of actions is not
+        significant.
+      </li>
+      <li>
+        A flow with <code>conjunction</code> actions may also include <code>note</code>
+        actions for annotations, but not any other kind of actions.  (They
+        would not be useful because they would never be executed.)
+      </li>
+      <li>
+        All of the flows that constitute a conjunctive flow with a given
+        <var>id</var> must have the same priority.  (Flows with the same <var>id</var>
+        but different priorities are currently treated as different
+        conjunctive flows, that is, currently <var>id</var> values need only be
+        unique within an OpenFlow table at a given priority.  This behavior
+        isn't guaranteed to stay the same in later releases, so please use
+        <var>id</var> values unique within an OpenFlow table.)
+      </li>
+      <li>
+        Conjunctive flows must not overlap with each other, at a given
+        priority, that is, any given packet must be able to match at most one
+        conjunctive flow at a given priority.  Overlapping conjunctive flows
+        yield unpredictable results.
+      </li>
+      <li>
+        Following a conjunctive flow match, the search for the flow with
+        <code>conj_id=</code><var>id</var> is done in the same general-purpose way as
+        other flow table searches, so one can use flows with
+        <code>conj_id=</code><var>id</var> to act differently depending on
+        circumstances.  (One exception is that the search for the
+        <code>conj_id=</code><var>id</var> flow itself ignores conjunctive flows, to
+        avoid recursion.) If the search with <code>conj_id=</code><var>id</var> fails,
+        Open vSwitch acts as if the conjunctive flow had not matched at all, and
+        continues searching the flow table for other matching flows.
+      </li>
+      <li>
+        <p>
+          OpenFlow prerequisite checking occurs for the flow with
+          <code>conj_id=</code><var>id</var> in the same way as any other flow, e.g. in
+          an OpenFlow 1.1+ context, putting a <code>mod_nw_src</code> action into the example
+          above would require adding an <code>ip</code> match, like this:
+        </p>
+        <pre>
+          conj_id=1234,ip actions=mod_nw_src:1.2.3.4,controller
+        </pre>
+      </li>
+      <li>
+        OpenFlow prerequisite checking also occurs for the individual flows
+        that comprise a conjunctive match in the same way as any other flow.
+      </li>
+      <li>
+        The flows that constitute a conjunctive flow do not have useful
+        statistics.  They are never updated with byte or packet counts, and so
+        on.  (For such a flow, therefore, the idle and hard timeouts work much
+        the same way.)
+      </li>
+      <li>
+        <p>
+          Sometimes there is a choice of which flows include a particular match.
+          For example, suppose that we added an extra constraint to our example,
+          to match on <code>ip_src</code> ∈
+          {<var>a</var>,<var>b</var>,<var>c</var>,<var>d</var>} and
+          <code>ip_dst</code> ∈
+          {<var>e</var>,<var>f</var>,<var>g</var>,<var>h</var>} and
+          <code>tcp_dst</code> = <var>i</var>.  One way to implement this is to
+          add the new constraint to the <code>conj_id</code> flow, like this:
+        </p>
+        <pre>
+          conj_id=1234,tcp,tcp_dst=<var>i</var> actions=mod_nw_src:1.2.3.4,controller
+        </pre>
+        <p>
+          but <em>this is not recommended</em> because of the cost of the extra
+          flow table lookup.  Instead, add the constraint to the individual
+          flows, either in one of the dimensions or (slightly better) all of
+          them.
+        </p>
+      </li>
+      <li>
+        A conjunctive match must have <var>n</var> ≥ 2 dimensions (otherwise a
+        conjunctive match is not necessary).  Open vSwitch enforces this.
+      </li>
+      <li>
+        Each dimension within a conjunctive match should ordinarily have more
+        than one flow.  Open vSwitch does not enforce this.
+      </li>
+    </ul>
+
+    <field id="MFF_CONJ_ID" title="Conjunction ID">
+      Used for conjunctive matching.  See above for more information.
+    </field>
+  </group>
+
+  <group title="Tunnel">
+    <p>
+      The fields in this group relate to tunnels, which Open vSwitch
+      supports in several forms (GRE, VXLAN, and so on).  Most of
+      these fields do appear in the wire format of a packet, so they
+      are data fields from that point of view, but they are metadata
+      from an OpenFlow flow table point of view because they do not
+      appear in packets that are forwarded to the controller or to
+      ordinary (non-tunnel) output ports.
+    </p>
+
+    <p>
+      Open vSwitch supports a spectrum of usage models for mapping
+      tunnels to OpenFlow ports:
+    </p>
+
+    <dl>
+      <dt>``Port-based'' tunnels</dt>
+      <dd>
+	<p>
+	  In this model, an OpenFlow port represents one tunnel: it matches a
+	  particular type of tunnel traffic between two IP endpoints, with a
+	  particular tunnel key (if keys are in use).  In this situation, <ref
+	  field="in_port"/> suffices to distinguish one tunnel from another, so
+	  the tunnel header fields have little importance for OpenFlow
+	  processing.  (They are still populated and may be used if it is
+	  convenient.)  The tunnel header fields play no role in sending
+	  packets out such an OpenFlow port, either, because the OpenFlow port
+	  itself fully specifies the tunnel headers.
+	</p>
+
+	<p>
+	  The following Open vSwitch commands create a bridge
+	  <code>br-int</code>, add port <code>tap0</code> to the bridge as
+	  OpenFlow port 1, establish a port-based GRE tunnel between the local
+	  host and remote IP 192.168.1.1 using GRE key 5001 as OpenFlow port 2,
+	  and arranges to forward all traffic from <code>tap0</code> to the
+	  tunnel and vice versa:
+	</p>
+
+	<pre>
+ovs-vsctl add-br br-int
+ovs-vsctl add-port br-int tap0 -- set interface tap0 ofport_request=1
+ovs-vsctl add-port br-int gre0 --
+    set interface gre0 ofport_request=2 type=gre \
+                       options:remote_ip=192.168.1.1 options:key=5001
+ovs-ofctl add-flow br-int in_port=1,actions=2
+ovs-ofctl add-flow br-int in_port=2,actions=1
+	</pre>
+      </dd>
+
+      <dt>``Flow-based'' tunnels</dt>
+      <dd>
+	<p>
+	  In this model, one OpenFlow port represents all possible tunnels of a
+	  given type with an endpoint on the current host, for example, all GRE
+	  tunnels.  In this situation, <ref field="in_port"/> only indicates
+	  that traffic was received on the particular kind of tunnel.  This is
+	  where the tunnel header fields are most important: they allow the
+	  OpenFlow tables to discriminate among tunnels based on their IP
+	  endpoints or keys.  Tunnel header fields also determine the IP
+	  endpoints and keys of packets sent out such a tunnel port.
+	</p>
+
+	<p>
+	  The following Open vSwitch commands create a bridge
+	  <code>br-int</code>, add port <code>tap0</code> to the
+	  bridge as OpenFlow port 1, establish a flow-based GRE tunnel
+	  port 3, and arranges to forward all traffic from
+	  <code>tap0</code> to remote IP 192.168.1.1 over a GRE tunnel
+	  with key 5001 and vice versa:
+	</p>
+
+	<pre>
+ovs-vsctl add-br br-int
+ovs-vsctl add-port br-int tap0 -- set interface tap0 ofport_request=1
+ovs-vsctl add-port br-int allgre --
+    set interface gre0 ofport_request=2 type=gre \
+                       options:remote_ip=flow options:key=flow
+ovs-ofctl add-flow br-int \
+    'in_port=1 actions=set_tunnel:5001,set_field:192.168.1.1->tun_dst,3'
+ovs-ofctl add-flow br-int 'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
+	</pre>
+      </dd>
+
+      <dt>Mixed models.</dt>
+      <dd>
+	<p>
+	  One may define both flow-based and port-based tunnels at the
+	  same time.  For example, it is valid and possibly useful to
+	  create and configure both <code>gre0</code> and
+	  <code>allgre</code> tunnel ports described above.
+	</p>
+
+	<p>
+	  Traffic is attributed on ingress to the most specific
+	  matching tunnel.  For example, <code>gre0</code> is more
+	  specific than <code>allgre</code>.  Therefore, if both
+	  exist, then <code>gre0</code> will be the ingress port for any
+	  GRE traffic received from 192.168.1.1 with key 5001.
+	</p>
+
+	<p>
+	  On egress, traffic may be directed to any appropriate tunnel
+	  port.  If both <code>gre0</code> and <code>allgre</code> are
+	  configured as already described, then the actions
+	  <code>2</code> and
+	  <code>set_tunnel:5001,set_field:192.168.1.1->tun_dst,3</code>
+	  send the same tunnel traffic.
+	</p>
+      </dd>
+
+      <dt>Intermediate models.</dt>
+      <dd>
+	Ports may be configured as partially flow-based.  For example,
+	one may define an OpenFlow port that represents tunnels
+	between a pair of endpoints but leaves the flow table to
+	discriminate on the flow key.
+      </dd>
+    </dl>
+
+    <p>
+      <code>ovs-vswitchd.conf.db</code>(5) describes all the details of tunnel
+      configuration.
+    </p>
+
+    <p>
+      These fields do not have any prerequisites, which means that a
+      flow may match on any or all of them, in any combination.
+    </p>
+
+    <p>
+      These fields are zeros for packets that did not arrive on a tunnel.
+    </p>
+
+    <field id="MFF_TUN_ID" title="Tunnel ID">
+      <p>
+	Many kinds of tunnels support a tunnel ID:
+      </p>
+
+      <ul>
+	<li>
+          VXLAN and Geneve have a 24-bit virtual network identifier (VNI).
+        </li>
+	<li>LISP has a 24-bit instance ID.</li>
+	<li>GRE has an optional 32-bit key.</li>
+	<li>STT has a 64-bit key.</li>
+      </ul>
+
+      <p>
+	When a packet is received from a tunnel, this field holds the
+	tunnel ID in its least significant bits, zero-extended to fit.
+	This field is zero if the tunnel does not support an ID, or if
+	no ID is in use for a tunnel type that has an optional ID, or
+	if an ID of zero received, or if the packet was not received
+	over a tunnel.
+      </p>
+
+      <p>
+	When a packet is output to a tunnel port, the tunnel
+	configuration determines whether the tunnel ID is taken from
+	this field or bound to a fixed value.  See the earlier
+	description of ``port-based'' and ``flow-based'' tunnels for
+	more information.
+      </p>
+
+      <p>
+	The following diagram shows the origin of this field in a
+	typical keyed GRE tunnel:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x800" width="0.4"/>
+	</header>
+	<header name="IPv4">
+	  <bits name="..." width="0.4"/>
+	  <bits name="proto" above="8" below="47" width="0.4"/>
+	  <bits name="src" above="32" width="0.4"/>
+	  <bits name="dst" above="32" width="0.4"/>
+	</header>
+	<header name="GRE">
+	  <bits name="..." above="16" width="0.4"/>
+	  <bits name="type" above="16" below="0x6558" width="0.4"/>
+	  <bits name="key" above="32" width=".4" fill="yes"/>
+	</header>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+    </field>
+
+    <field id="MFF_TUN_SRC" title="Tunnel IPv4 Source">
+      <p>
+	When a packet is received from a tunnel, this field is the
+	source address in the outer IP header of the tunneled packet.
+	This field is zero if the packet was not received over a
+	tunnel.
+      </p>
+
+      <p>
+	When a packet is output to a flow-based tunnel port, this
+	field influences the IPv4 source address used to send the
+	packet.  If it is zero, then the kernel chooses an appropriate
+	IP address based using the routing table.
+      </p>
+
+      <p>
+	The following diagram shows the origin of this field in a
+	typical keyed GRE tunnel:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x800" width="0.4"/>
+	</header>
+	<header name="IPv4">
+	  <bits name="..." width="0.4"/>
+	  <bits name="proto" above="8" below="47" width="0.4"/>
+	  <bits name="src" above="32" width="0.4" fill="yes"/>
+	  <bits name="dst" above="32" width="0.4"/>
+	</header>
+	<header name="GRE">
+	  <bits name="..." above="16" width="0.4"/>
+	  <bits name="type" above="16" below="0x6558" width="0.4"/>
+	  <bits name="key" above="32" width=".4"/>
+	</header>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+    </field>
+
+    <field id="MFF_TUN_DST" title="Tunnel IPv4 Destination">
+      <p>
+	When a packet is received from a tunnel, this field is the
+	destination address in the outer IP header of the tunneled
+	packet.  This field is zero if the packet was not received
+	over a tunnel.
+      </p>
+
+      <p>
+	When a packet is output to a flow-based tunnel port, this
+	field specifies the destination to which the tunnel packet is
+	sent.
+      </p>
+
+      <p>
+	The following diagram shows the origin of this field in a
+	typical keyed GRE tunnel:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x800" width="0.4"/>
+	</header>
+	<header name="IPv4">
+	  <bits name="..." width="0.4"/>
+	  <bits name="proto" above="8" below="47" width="0.4"/>
+	  <bits name="src" above="32" width="0.4"/>
+	  <bits name="dst" above="32" width="0.4" fill="yes"/>
+	</header>
+	<header name="GRE">
+	  <bits name="..." above="16" width="0.4"/>
+	  <bits name="type" above="16" below="0x6558" width="0.4"/>
+	  <bits name="key" above="32" width=".4"/>
+	</header>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+    </field>
+
+    <field id="MFF_TUN_IPV6_SRC" title="Tunnel IPv6 Source">
+      Similar to <ref field="tun_src"/>, but for tunnels over IPv6.
+    </field>
+
+    <field id="MFF_TUN_IPV6_DST" title="Tunnel IPv6 Destination">
+      Similar to <ref field="tun_dst"/>, but for tunnels over IPv6.
+    </field>
+
+    <field id="MFF_TUN_GBP_ID" title="VXLAN Group-Based Policy ID">
+      <p>
+        For a packet tunneled over VXLAN with the Group-Based Policy (GBP)
+        extension, this field represents the GBP policy ID.  Only packets that
+        arrive over a VXLAN tunnel with the GBP extension enabled have this
+        field set.
+      </p>
+    </field>
+
+    <field id="MFF_TUN_GBP_FLAGS" title="VXLAN Group-Based Policy Flags">
+      <p>
+        For a packet tunneled over VXLAN with the Group-Based Policy (GBP)
+        extension, this field represents the GBP policy flags.  Only packets
+        that arrive over a VXLAN tunnel with the GBP extension enabled have
+        this field set.
+      </p>
+
+      <p>
+        The field has the format shown below:
+      </p>
+
+      <diagram>
+        <header name="GBP Flags">
+          <bits name="" above="1" width="0.15"/>
+          <bits name="D" above="1" width="0.15"/>
+          <bits name="" above="1" width="0.15"/>
+          <bits name="" above="1" width="0.15"/>
+          <bits name="A" above="1" width="0.15"/>
+          <bits name="" above="1" width="0.15"/>
+          <bits name="" above="1" width="0.15"/>
+          <bits name="" above="1" width="0.15"/>
+        </header>
+      </diagram>
+
+      <p>
+        Unlabeled bits are reserved and must be transmitted as 0.  The
+        following bits have defined meanings:
+      </p>
+
+      <dl>
+        <dt><code>D</code> (Don't Learn)</dt>
+        <dd>
+          When set, this bit indicates that the egress tunnel endpoint MUST NOT
+          learn the source address of the encapsulated frame.
+        </dd>
+
+        <dt><code>A</code> (Applied</dt>
+        <dd>
+          When set, indicates that the group policy has already been applied to
+          this packet. Policies MUST NOT be applied by devices when the A bit
+          is set.
+        </dd>
+      </dl>
+    </field>
+
+    <field id="MFF_TUN_METADATA0" title="Generic Tunnel Option 0">
+      <p>
+        These fields provide OpenFlow access to the generic type-length-value
+        options defined by the Geneve tunneling protocol or other protocols
+        with options in the same TLV format as Geneve options.  Each of these
+        options has the following wire format:
+      </p>
+
+      <diagram>
+	<header name="header">
+	  <bits name="class" above="16" width="0.6"/>
+	  <bits name="type" above="8" width="0.5"/>
+	  <bits name="res" above="3" below="0" width="0.25"/>
+	  <bits name="length" above="5" width="0.4"/>
+	</header>
+        <nospace/>
+	<header name="body">
+	  <bits name="value" above="4×(length - 1) bytes" width="1.7"/>
+	</header>
+      </diagram>
+
+      <p>
+        Taken together, the <code>class</code> and <code>type</code> in the
+        option format mean that there are about 16 million distinct kinds of
+        TLV options, too many to give individual OXM code points.  Thus, Open
+        vSwitch requires the user to define the TLV options of interest.  Up to
+        64 TLV options can be bound to generic tunnel option NXM code points.
+        Each option may have up to 124 bytes in its value (the maximum this
+        format allows), and the total set of bound options must total at most
+        252 bytes.
+      </p>
+
+      <p>
+        Open vSwitch extensions to the OpenFlow protocol bind TLV options to
+        NXM code points.  The <code>ovs-ofctl</code>(8) program offers one way
+        to use these extensions, e.g. to configure a mapping from a TLV option
+        with <code>class</code> <code>0xffff</code>, <code>type</code> 0, and a
+        body length of 4 bytes:
+      </p>
+
+      <pre>
+ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0,len=4}->tun_metadata0"
+      </pre>
+
+      <p>
+        Once a TLV option is properly bound, it can be accessed and modified
+        like any other field, e.g. to send packets that have value 1234 for the
+        option described above to the controller:
+      </p>
+
+      <pre>
+ovs-ofctl add-flow br0 tun_metadata0=1234,actions=controller
+      </pre>
+    </field>
+    <!--- XXX need a way to define a range of OXMs -->
+    <field id="MFF_TUN_METADATA1" title="Generic Tunnel Option 1" hidden="yes"/>
+    <field id="MFF_TUN_METADATA2" title="Generic Tunnel Option 2" hidden="yes"/>
+    <field id="MFF_TUN_METADATA3" title="Generic Tunnel Option 3" hidden="yes"/>
+    <field id="MFF_TUN_METADATA4" title="Generic Tunnel Option 4" hidden="yes"/>
+    <field id="MFF_TUN_METADATA5" title="Generic Tunnel Option 5" hidden="yes"/>
+    <field id="MFF_TUN_METADATA6" title="Generic Tunnel Option 6" hidden="yes"/>
+    <field id="MFF_TUN_METADATA7" title="Generic Tunnel Option 7" hidden="yes"/>
+    <field id="MFF_TUN_METADATA8" title="Generic Tunnel Option 8" hidden="yes"/>
+    <field id="MFF_TUN_METADATA9" title="Generic Tunnel Option 9" hidden="yes"/>
+    <field id="MFF_TUN_METADATA10" title="Generic Tunnel Option 10" hidden="yes"/>
+    <field id="MFF_TUN_METADATA11" title="Generic Tunnel Option 11" hidden="yes"/>
+    <field id="MFF_TUN_METADATA12" title="Generic Tunnel Option 12" hidden="yes"/>
+    <field id="MFF_TUN_METADATA13" title="Generic Tunnel Option 13" hidden="yes"/>
+    <field id="MFF_TUN_METADATA14" title="Generic Tunnel Option 14" hidden="yes"/>
+    <field id="MFF_TUN_METADATA15" title="Generic Tunnel Option 15" hidden="yes"/>
+    <field id="MFF_TUN_METADATA16" title="Generic Tunnel Option 16" hidden="yes"/>
+    <field id="MFF_TUN_METADATA17" title="Generic Tunnel Option 17" hidden="yes"/>
+    <field id="MFF_TUN_METADATA18" title="Generic Tunnel Option 18" hidden="yes"/>
+    <field id="MFF_TUN_METADATA19" title="Generic Tunnel Option 19" hidden="yes"/>
+    <field id="MFF_TUN_METADATA20" title="Generic Tunnel Option 20" hidden="yes"/>
+    <field id="MFF_TUN_METADATA21" title="Generic Tunnel Option 21" hidden="yes"/>
+    <field id="MFF_TUN_METADATA22" title="Generic Tunnel Option 22" hidden="yes"/>
+    <field id="MFF_TUN_METADATA23" title="Generic Tunnel Option 23" hidden="yes"/>
+    <field id="MFF_TUN_METADATA24" title="Generic Tunnel Option 24" hidden="yes"/>
+    <field id="MFF_TUN_METADATA25" title="Generic Tunnel Option 25" hidden="yes"/>
+    <field id="MFF_TUN_METADATA26" title="Generic Tunnel Option 26" hidden="yes"/>
+    <field id="MFF_TUN_METADATA27" title="Generic Tunnel Option 27" hidden="yes"/>
+    <field id="MFF_TUN_METADATA28" title="Generic Tunnel Option 28" hidden="yes"/>
+    <field id="MFF_TUN_METADATA29" title="Generic Tunnel Option 29" hidden="yes"/>
+    <field id="MFF_TUN_METADATA30" title="Generic Tunnel Option 30" hidden="yes"/>
+    <field id="MFF_TUN_METADATA31" title="Generic Tunnel Option 31" hidden="yes"/>
+    <field id="MFF_TUN_METADATA32" title="Generic Tunnel Option 32" hidden="yes"/>
+    <field id="MFF_TUN_METADATA33" title="Generic Tunnel Option 33" hidden="yes"/>
+    <field id="MFF_TUN_METADATA34" title="Generic Tunnel Option 34" hidden="yes"/>
+    <field id="MFF_TUN_METADATA35" title="Generic Tunnel Option 35" hidden="yes"/>
+    <field id="MFF_TUN_METADATA36" title="Generic Tunnel Option 36" hidden="yes"/>
+    <field id="MFF_TUN_METADATA37" title="Generic Tunnel Option 37" hidden="yes"/>
+    <field id="MFF_TUN_METADATA38" title="Generic Tunnel Option 38" hidden="yes"/>
+    <field id="MFF_TUN_METADATA39" title="Generic Tunnel Option 39" hidden="yes"/>
+    <field id="MFF_TUN_METADATA40" title="Generic Tunnel Option 40" hidden="yes"/>
+    <field id="MFF_TUN_METADATA41" title="Generic Tunnel Option 41" hidden="yes"/>
+    <field id="MFF_TUN_METADATA42" title="Generic Tunnel Option 42" hidden="yes"/>
+    <field id="MFF_TUN_METADATA43" title="Generic Tunnel Option 43" hidden="yes"/>
+    <field id="MFF_TUN_METADATA44" title="Generic Tunnel Option 44" hidden="yes"/>
+    <field id="MFF_TUN_METADATA45" title="Generic Tunnel Option 45" hidden="yes"/>
+    <field id="MFF_TUN_METADATA46" title="Generic Tunnel Option 46" hidden="yes"/>
+    <field id="MFF_TUN_METADATA47" title="Generic Tunnel Option 47" hidden="yes"/>
+    <field id="MFF_TUN_METADATA48" title="Generic Tunnel Option 48" hidden="yes"/>
+    <field id="MFF_TUN_METADATA49" title="Generic Tunnel Option 49" hidden="yes"/>
+    <field id="MFF_TUN_METADATA50" title="Generic Tunnel Option 50" hidden="yes"/>
+    <field id="MFF_TUN_METADATA51" title="Generic Tunnel Option 51" hidden="yes"/>
+    <field id="MFF_TUN_METADATA52" title="Generic Tunnel Option 52" hidden="yes"/>
+    <field id="MFF_TUN_METADATA53" title="Generic Tunnel Option 53" hidden="yes"/>
+    <field id="MFF_TUN_METADATA54" title="Generic Tunnel Option 54" hidden="yes"/>
+    <field id="MFF_TUN_METADATA55" title="Generic Tunnel Option 55" hidden="yes"/>
+    <field id="MFF_TUN_METADATA56" title="Generic Tunnel Option 56" hidden="yes"/>
+    <field id="MFF_TUN_METADATA57" title="Generic Tunnel Option 57" hidden="yes"/>
+    <field id="MFF_TUN_METADATA58" title="Generic Tunnel Option 58" hidden="yes"/>
+    <field id="MFF_TUN_METADATA59" title="Generic Tunnel Option 59" hidden="yes"/>
+    <field id="MFF_TUN_METADATA60" title="Generic Tunnel Option 60" hidden="yes"/>
+    <field id="MFF_TUN_METADATA61" title="Generic Tunnel Option 61" hidden="yes"/>
+    <field id="MFF_TUN_METADATA62" title="Generic Tunnel Option 62" hidden="yes"/>
+    <field id="MFF_TUN_METADATA63" title="Generic Tunnel Option 63" hidden="yes"/>
+
+    <field id="MFF_TUN_FLAGS" title="Tunnel Flags">
+      <p>
+        Flags indicating various aspects of the tunnel encapsulation.
+      </p>
+
+      <p>
+        Matches on this field are most conveniently written in terms of
+        symbolic names (given in the diagram below), each preceded by either
+        <code>+</code> for a flag that must be set, or <code>-</code> for a
+        flag that must be unset, without any other delimiters between the
+        flags.  Flags not mentioned are wildcarded.  For example,
+        <code>tun_flags=+oam</code> matches only OAM packets.  Matches can also
+        be written as <code><var>flags</var>/<var>mask</var></code>, where
+        <var>flags</var> and <var>mask</var> are 16-bit numbers in decimal or
+        in hexadecimal prefixed by <code>0x</code>.
+      </p>
+
+      <p>
+        Currently, there is only one flag defined:
+      </p>
+
+      <dl>
+        <dt><code>oam</code></dt>
+        <dd>
+          The tunnel protocol indicated that this is an OAM (Operations and
+          Management) control packet.
+        </dd>
+      </dl>
+
+      <p>
+        The switch may reject matches against unknown flags.
+      </p>
+
+      <p>
+        Newer versions of Open vSwitch may introduce additional flags with new
+        meanings.  It is therefore not recommended to use an exact match on
+        this field since the behavior of these new flags is unknown and should
+        be ignored.
+      </p>
+
+      <p>
+        For non-tunneled packets, the value is 0.
+      </p>
+    </field>
+
+    <!-- Open vSwitch uses the following fields internally, but it
+         does not expose them to the user via OpenFlow, so we do not
+         document them. -->
+    <field id="MFF_TUN_TTL" title="Tunnel IPv4 Time-to-Live" internal="yes"/>
+    <field id="MFF_TUN_TOS" title="Tunnel IPv4 Type of Service" internal="yes"/>
+  </group>
+
+  <group title="Metadata">
+    <p>
+      These fields relate to the origin or treatment of a packet, but
+      they are not extracted from the packet data itself.
+    </p>
+
+    <field id="MFF_IN_PORT" title="Ingress Port">
+      <p>
+	The OpenFlow port on which the packet being processed arrived.
+	This is a 16-bit field that holds an OpenFlow 1.0 port number.
+	For receiving a packet, the only values that appear in this
+	field are:
+      </p>
+
+      <dl>
+	<dt>1 through <code>0xfeff</code> (65,279), inclusive.</dt>
+	<dd>
+	  Conventional OpenFlow port numbers.
+	</dd>
+
+	<dt><code>OFPP_LOCAL</code> (<code>0xfffe</code> or 65,534).</dt>
+	<dd>
+	  <p>
+	    The ``local'' port, which in Open vSwitch is always named
+	    the same as the bridge itself.  This represents a
+	    connection between the switch and the local TCP/IP stack.
+	    This port is where an IP address is most commonly
+	    configured on an Open vSwitch switch.
+	  </p>
+
+	  <p>
+	    OpenFlow does not require a switch to have a local port,
+	    but all existing versions of Open vSwitch have always
+	    included a local port.  <b>Future Directions:</b> Future
+	    versions of Open vSwitch might be able to optionally omit
+	    the local port, if someone submits code to implement such
+	    a feature.
+	  </p>
+	</dd>
+
+	<dt><code>OFPP_NONE</code> (<code>0xffff</code> or 65,535).</dt>
+	<dt><code>OFPP_CONTROLLER</code> (<code>0xfffd</code> or 65,533).</dt>
+	<dd>
+	  <p>
+	    When a controller injects a packet into an OpenFlow switch
+	    with a ``packet-out'' request, it can specify one of these
+	    ingress ports to indicate that the packet was generated
+	    internally rather than having been received on some port.
+	  </p>
+
+	  <p>
+	    OpenFlow 1.0 specified <code>OFPP_NONE</code> for this
+	    purpose.  Despite that, some controllers used
+	    <code>OFPP_CONTROLLER</code>, and some switches only
+	    accepted <code>OFPP_CONTROLLER</code>, so OpenFlow 1.0.2
+	    required support for both ports.  OpenFlow 1.1 and later
+	    were more clearly drafted to allow only
+	    <code>OFPP_CONTROLLER</code>.  For maximum compatibility,
+	    Open vSwitch allows both ports with all OpenFlow versions.
+	  </p>
+	</dd>
+      </dl>
+
+      <p>
+	Values not mentioned above will never appear when receiving a
+	packet, including the following notable values:
+      </p>
+
+      <dl>
+	<dt>0</dt>
+	<dd>
+	  Zero is not a valid OpenFlow port number.
+	</dd>
+
+	<dt><code>OFPP_MAX</code> (<code>0xff00</code> or 65,280).</dt>
+	<dd>
+	  This value has only been clearly specified as a valid port
+	  number as of OpenFlow 1.3.3.  Before that, its status was
+	  unclear, and so Open vSwitch has never allowed
+	  <code>OFPP_MAX</code> to be used as a port number, so
+	  packets will never be received on this port.  (Other
+	  OpenFlow switches, of course, might use it.)
+	</dd>
+
+        <dt><code>OFPP_UNSET</code> (<code>0xfff7</code> or 65,527)</dt>
+	<dt><code>OFPP_IN_PORT</code> (<code>0xfff8</code> or 65,528)</dt>
+	<dt><code>OFPP_TABLE</code> (<code>0xfff9</code> or 65,529)</dt>
+	<dt><code>OFPP_NORMAL</code> (<code>0xfffa</code> or 65,530)</dt>
+	<dt><code>OFPP_FLOOD</code> (<code>0xfffb</code> or 65,531)</dt>
+	<dt><code>OFPP_ALL</code> (<code>0xfffc</code> or 65,532)</dt>
+	<dd>
+          <p>
+	    These port numbers are used only in output actions and never
+	    appear as ingress ports.
+          </p>
+
+          <p>
+            Most of these port numbers were defined in OpenFlow 1.0, but
+            <code>OFPP_UNSET</code> was only introduced in OpenFlow 1.5.
+          </p>
+	</dd>
+      </dl>
+
+      <p>
+	Values that will never appear when receiving a packet may
+	still be matched against in the flow table.  There are still
+	circumstances in which those flows can be matched:
+      </p>
+
+      <ul>
+	<li>
+	  The <code>resubmit</code> Open vSwitch extension action allows a
+	  flow table lookup with an arbitrary ingress port.
+	</li>
+
+	<li>
+	  An action that modifies the ingress port field (see below),
+	  such as e.g. <code>load</code> or <code>set_field</code>,
+	  followed by an action or instruction that performs another
+	  flow table lookup, such as <code>resubmit</code> or
+	  <code>goto_table</code>.
+	</li>
+      </ul>
+
+      <p>
+	This field is heavily used for matching in OpenFlow tables,
+	but for packet egress, it has only very limited roles:
+      </p>
+
+      <ul>
+	<li>
+	  <p>
+	    OpenFlow requires suppressing output actions to <ref
+	    field="in_port"/>.  That is, the following two flows both drop all
+	    packets that arrive on port 1:
+	  </p>
+
+	  <pre>
+in_port=1,actions=1
+in_port=1,actions=drop
+	  </pre>
+
+	  <p>
+	    (This behavior is occasionally useful for flooding to a
+	    subset of ports.  Specifying <code>actions=1,2,3,4</code>,
+	    for example, outputs to ports 1, 2, 3, and 4, omitting the
+	    ingress port.)
+	  </p>
+	</li>
+
+	<li>
+	  OpenFlow has a special port <code>OFPP_IN_PORT</code> (with
+	  value 0xfff8) that outputs to the ingress port.  For example,
+	  in a switch that has four ports numbered 1 through 4,
+	  <code>actions=1,2,3,4,in_port</code> outputs to ports 1, 2,
+	  3, and 4, including the ingress port.
+	</li>
+      </ul>
+
+      <p>
+	Because the ingress port field has so little influence on packet
+	processing, it does not ordinarily make sense to modify the
+	ingress port field.  The field is writable only to support the
+	occasional use case where the ingress port's roles in packet
+	egress, described above, become troublesome.  For example,
+	<code>actions=load:0-&gt;NXM_OF_IN_PORT[],output:123</code>
+	will output to port 123 regardless of whether it is in the
+	ingress port.  If the ingress port is important, then one may save
+	and restore it on the stack:
+      </p>
+
+      <pre>
+actions=push:NXM_OF_IN_PORT[],load:0->NXM_OF_IN_PORT[],output:123,pop:NXM_OF_IN_PORT[]
+      </pre>
+
+      <p>
+	The ability to modify the ingress port is an Open vSwitch
+	extension to OpenFlow.
+      </p>
+
+      <p>
+	Modifying the ingress port does not prevent or frustrate specifying an
+	ingress port in the <code>resubmit</code> action, because
+	<code>resubmit</code> only (optionally) changes the
+	<code>in_port</code> used for <code>resubmit</code>'s flow table
+	lookup.  It does not otherwise affect the ingress port.
+      </p>
+    </field>
+
+    <field id="MFF_IN_PORT_OXM" title="OXM Ingress Port">
+      <p>
+	OpenFlow 1.1 and later use a 32-bit port number, so this field
+	supplies a 32-bit view of the ingress port.  Current versions of
+	Open vSwitch support only a 16-bit range of ports:
+      </p>
+
+      <ul>
+	<li>
+	  OpenFlow 1.0 ports <code>0x0000</code> to
+	  <code>0xfeff</code>, inclusive, map to OpenFlow 1.1
+	  port numbers with the same values.
+	</li>
+
+	<li>
+	  OpenFlow 1.0 ports <code>0xff00</code> to
+	  <code>0xffff</code>, inclusive, map to OpenFlow 1.1 port
+	  numbers <code>0xffffff00</code> to <code>0xffffffff</code>.
+	</li>
+
+	<li>
+	  OpenFlow 1.1 ports <code>0x0000ff00</code> to
+	  <code>0xfffffeff</code> are not mapped and not supported.
+	</li>
+      </ul>
+
+      <p>
+	<ref field="in_port"/> and <ref field="in_port_oxm"/> are two views of
+	the same information, so all of the comments on <ref field="in_port"/>
+	apply to <ref field="in_port_oxm"/> too.  Modifying <ref
+	field="in_port"/> changes <ref field="in_port_oxm"/>, and vice versa.
+      </p>
+
+      <p>
+	Setting <ref field="in_port_oxm"/> to an unsupported value yields
+	unspecified behavior.
+      </p>
+    </field>
+
+    <field id="MFF_SKB_PRIORITY" title="Output Queue">
+      <p>
+	This field influences how packets in the flow will be queued,
+	for quality of service (QoS) purposes, when they egress the
+	switch.  Its range of meaningful values, and their meanings,
+	varies greatly from one OpenFlow implementation to another.
+	Even within a single implementation, there is no guarantee
+	that all OpenFlow ports have the same queues configured or
+	that all OpenFlow ports in an implementation can be configured
+	the same way queue-wise.
+      </p>
+
+      <p>
+	Configuring queues on OpenFlow is not well standardized.  On
+	Linux, Open vSwitch supports queue configuration via OVSDB,
+	specifically the <code>QoS</code> and <code>Queue</code>
+	tables (see <code>ovs-vswitchd.conf.db(5)</code> for details).
+	Ports of Open vSwitch to other platforms might require queue
+	configuration through some separate protocol (such as a CLI).
+	Even on Linux, Open vSwitch exposes only a fraction of the
+	kernel's queuing features through OVSDB, so advanced or
+	unusual uses might require use of separate utilities
+	(e.g. <code>tc</code>).  OpenFlow switches other than Open
+	vSwitch might use OF-CONFIG or any of the configuration
+	methods mentioned above.  Finally, some OpenFlow switches have
+	a fixed number of fixed-function queues (e.g. eight queues
+	with strictly defined priorities) and others do not support
+	any control over queuing.
+      </p>
+
+      <p>
+	The only output queue that all OpenFlow implementations must
+	support is zero, to identify a default queue, whose properties
+	are implementation-defined.  Outputting a packet to a queue
+	that does not exist on the output port yields unpredictable
+	behavior: among the possibilities are that the packet might be
+	dropped or transmitted with a very high or very low priority.
+      </p>
+
+      <p>
+	OpenFlow 1.0 only allowed output queues to be specified as
+	part of an ``enqueue'' action that specified both a queue and
+	an output port.  That is, OpenFlow 1.0 treats the queue as an
+	argument to an action, not as a field.
+      </p>
+
+      <p>
+	To increase flexibility, OpenFlow 1.1 added an action to set the output
+	queue.  This model was carried forward, without change, through
+	OpenFlow 1.5.
+      </p>
+
+      <p>
+	Open vSwitch implements the native queuing model of each
+	OpenFlow version it supports.  Open vSwitch also includes an
+	extension for setting the output queue as an action in
+	OpenFlow 1.0.
+      </p>
+
+      <p>
+	When a packet ingresses into an OpenFlow switch, the output
+	queue is ordinarily set to 0, indicating the default queue.
+	However, Open vSwitch supports various ways to forward a
+	packet from one OpenFlow switch to another within a single
+	host.  In these cases, Open vSwitch maintains the output queue
+	across the forwarding step.  For example:
+      </p>
+
+      <ul>
+	<li>
+	  A hop across a Open vSwitch ``patch port'' (which does not
+	  actually involve queuing) preserves the output queue.
+	</li>
+
+	<li>
+	  <p>
+	    When a flow sets the output queue then outputs to an
+	    OpenFlow tunnel port, the encapsulation preserves the
+	    output queue.  If the kernel TCP/IP stack routes the
+	    encapsulated packet directly to a physical interface, then
+	    that output honors the output queue.  Alternatively, if
+	    the kernel routes the encapsulated packet to another Open
+	    vSwitch bridge, then the output queue set previously
+	    becomes the initial output queue on ingress to the second
+	    bridge and will thus be used for further output actions
+	    (unless overridden by a new ``set queue'' action).
+	  </p>
+
+	  <p>
+	    (This description reflects the current behavior of Open
+	    vSwitch on Linux.  This behavior relies on details of the
+	    Linux TCP/IP stack.  It could be difficult to make ports
+	    to other operating systems behave the same way.)
+	  </p>
+	</li>
+      </ul>
+
+      <p>
+	<b>Future Directions:</b> Open vSwitch implements the output
+	queue as a field, but does not currently expose it through OXM
+	or NXM for matching purposes.  If this turns out to be a
+	useful feature, it could be implemented in future versions.
+      </p>
+    </field>
+
+    <field id="MFF_PKT_MARK" title="Packet Mark">
+      <p>
+        Packet mark comes to Open vSwitch from the Linux kernel, in
+        which the <code>sk_buff</code> data structure that represents
+        a packet contains a 32-bit member named <code>skb_mark</code>.
+        The value of <code>skb_mark</code> propagates along with the
+        packet it accompanies wherever the packet goes in the kernel.
+        It has no predefined semantics but various kernel-user
+        interfaces can set and match on it, which makes it suitable
+        for ``marking'' packets at one point in their handling and
+        then acting on the mark later.  With <code>iptables</code>,
+        for example, one can mark some traffic specially at ingress
+        and then handle that traffic differently at egress based on
+        the marked value.
+      </p>
+
+      <p>
+	Packet mark is an attempt at a generalization of the
+	<code>skb_mark</code> concept beyond Linux, at least through more
+	generic naming.  Like <ref field="skb_priority"/>, packet mark is
+	preserved across forwarding steps within a machine.  Unlike <ref
+	field="skb_priority"/>, packet mark has no direct effect on packet
+	forwarding: the value set in packet mark does not matter unless some
+	later OpenFlow table or switch matches on packet mark, or unless the
+	packet passes through some other kernel subsystem that has been
+	configured to interpret packet mark in specific ways, e.g. through
+	<code>iptables</code> configuration mentioned above.
+      </p>
+
+      <p>
+	Preserving packet mark across kernel forwarding steps relies
+	heavily on kernel support, which ports to non-Linux operating
+	systems may not have.  Regardless of operating system support,
+	Open vSwitch supports packet mark within a single bridge and
+	across patch ports.
+      </p>
+
+      <p>
+	The value of packet mark when a packet ingresses into the
+	first Open vSwich bridge is typically zero, but it could be
+	nonzero if its value was previously set by some kernel
+	subsystem.
+      </p>
+    </field>
+
+    <field id="MFF_ACTSET_OUTPUT" title="Action Set Output Port">
+      <p>
+        Holds the output port currently in the OpenFlow action set (i.e. from
+        an <code>output</code> action within a <code>write_actions</code>
+        instruction).  Its value is an OpenFlow port number.  If there is no
+        output port in the OpenFlow action set, or if the output port will be
+        ignored (e.g. because there is an output group in the OpenFlow action
+        set), then the value will be <code>OFPP_UNSET</code>.
+      </p>
+
+      <p>
+        Open vSwitch allows any table to match this field.  OpenFlow, however,
+        only requires this field to be matchable from within an OpenFlow egress
+        table (a feature that Open vSwitch does not yet implement).
+      </p>
+    </field>
+
+    <field id="MFF_DP_HASH" title="Datapath Hash" internal="yes"/>
+    <field id="MFF_RECIRC_ID" title="Datapath Recirculation ID" internal="yes"/>
+  </group>
+
+  <group title="Connection Tracking">
+    <p>
+      Open vSwitch 2.5 and later support ``connection tracking,'' which allows
+      bidirectional streams of packets to be statefully grouped into
+      connections.  Open vSwitch connection tracking, for example, identifies
+      the patterns of TCP packets that indicates a successfully initiated
+      connection, as well as those that indicate that a connection has been
+      torn down.  Open vSwitch connection tracking can also identify related
+      connections, such as FTP data connections spawned from FTP control
+      connections.
+    </p>
+
+    <p>
+      An individual packet passing through the pipeline may be in one of two
+      states: ``untracked'' or ``tracked.''  A packet is <dfn>untracked</dfn>
+      at the beginning of the Open vSwitch pipeline and continues to be
+      untracked until the pipeline invokes the <code>ct</code> action.  The
+      connection tracking fields are all zeroes in an untracked packet.  When a
+      flow in the Open vSwitch pipeline invokes the <code>ct</code> action, the
+      action initializes the connection tracking fields and the packet becomes
+      <dfn>tracked</dfn> for the remainder of its processing.
+    </p>
+
+    <p>
+      The connection tracker stores connection state in an internal table, but
+      it only adds a new entry to this table when a <code>ct</code> action for
+      a new connection invokes <code>ct</code> with the <code>commit</code>
+      parameter.  For a given connection, when a pipeline has executed
+      <code>ct</code>, but not yet with <code>commit</code>, the connection is
+      said to be <dfn>uncommitted</dfn>.  State for an uncommitted connection
+      is ephemeral and does not persist past the end of the pipeline, so some
+      features are only available to committed connections.  A connection would
+      typically be left uncommitted as a way to drop its packets.
+    </p>
+
+    <p>
+      Connection tracking is an Open vSwitch extension to OpenFlow.
+    </p>
+
+    <field id="MFF_CT_STATE" title="Connection Tracking State">
+      <p>
+        This field holds several flags that can be used to determine the state
+        of the connection to which the packet belongs.
+      </p>
+
+      <p>
+        Matches on this field are most conveniently written in terms of
+        symbolic names (listed below), each preceded by either <code>+</code>
+        for a flag that must be set, or <code>-</code> for a flag that must be
+        unset, without any other delimiters between the flags.  Flags not
+        mentioned are wildcarded.  For example,
+        <code>tcp,ct_state=+trk-new</code> matches TCP packets that have been
+        run through the connection tracker and do not establish a new
+        connection.  Matches can also be written as
+        <code><var>flags</var>/<var>mask</var></code>, where <var>flags</var>
+        and <var>mask</var> are 32-bit numbers in decimal or in hexadecimal
+        prefixed by <code>0x</code>.
+      </p>
+
+      <p>
+        The following flags are defined:
+      </p>
+
+      <dl>
+        <dt><code>new</code> (0x01)</dt>
+        <dd>
+          A new connection.  Set to 1 if this is an uncommitted connection.
+        </dd>
+
+        <dt><code>est</code> (0x02)</dt>
+        <dd>
+          Part of an existing connection.  Set to 1 if this is a committed
+          connection.
+        </dd>
+
+        <dt><code>rel</code> (0x04)</dt>
+        <dd>
+          <p>
+            Related to an existing connection, e.g. an ICMP ``destination
+            unreachable'' message or an FTP data connections.  This flag will
+            only be 1 if the connection to which this one is related is
+            committed.
+          </p>
+
+          <p>
+            Connections identified as <code>rel</code> are separate from the
+            originating connection and must be committed separately.  All
+            packets for a related connection will have the <code>rel</code>
+            flag set, not just the initial packet.
+          </p>
+        </dd>
+
+        <dt><code>rpl</code> (0x08)</dt>
+        <dd>
+          This packet is in the reply direction, meaning that it is in the
+          opposite direction from the packet that initiated the connection.
+          This flag will only be 1 if the connection is committed.
+        </dd>
+
+        <dt><code>inv</code> (0x10)</dt>
+        <dd>
+          <p>
+            The state is invalid, meaning that the connection tracker couldn't
+            identify the connection. This flag is a catch-all for problems
+            in the connection or the connection tracker, such as:
+          </p>
+
+          <ul>
+            <li>
+              L3/L4 protocol handler is not loaded/unavailable.  With the Linux
+              kernel datapath, this may mean that the
+              <code>nf_conntrack_ipv4</code> or <code>nf_conntrack_ipv6</code>
+              modules are not loaded.
+            </li>
+
+            <li>
+              L3/L4 protocol handler determines that the packet is malformed.
+            </li>
+
+            <li>
+              Packets are unexpected length for protocol.
+            </li>
+          </ul>
+        </dd>
+
+        <dt><code>trk</code> (0x20)</dt>
+        <dd>
+          This packet is tracked, meaning that it has previously traversed the
+          connection tracker.  If this flag is not set, then no other flags
+          will be set.  If this flag is set, then the packet is tracked and
+          other flags may also be set.
+        </dd>
+
+        <dt><code>snat</code> (0x40)</dt>
+        <dd>
+          This packet was transformed by source address/port translation by a
+          preceding <code>ct</code> action.  Open vSwitch 2.6 added this flag.
+        </dd>
+
+        <dt><code>dnat</code> (0x80)</dt>
+        <dd>
+          This packet was transformed by destination address/port translation
+          by a preceding <code>ct</code> action.  Open vSwitch 2.6 added this
+          flag.
+        </dd>
+      </dl>
+
+      <p>
+        There are additional constraints on these flags, listed in decreasing
+        order of precedence below:
+      </p>
+
+      <ol>
+        <li>
+          If <code>trk</code> is unset, no other flags are set.
+        </li>
+
+        <li>
+          If <code>trk</code> is set, one or more other flags may be set.
+        </li>
+
+        <li>
+          If <code>inv</code> is set, only the <code>trk</code> flag is also
+          set.
+        </li>
+
+        <li>
+          <code>new</code> and <code>est</code> are mutually exclusive.
+        </li>
+
+        <li>
+          <code>new</code> and <code>rpy</code> are mutually exclusive.
+        </li>
+
+        <li>
+          <code>rel</code> may be set in conjunction with any other flags.
+        </li>
+      </ol>
+
+      <p>
+        Future versions of Open vSwitch may define new flags.
+      </p>
+    </field>
+
+    <field id="MFF_CT_ZONE" title="Connection Tracking Zone">
+      A connection tracking zone, the zone value passed to the most recent
+      <code>ct</code> action.  Each zone is an independent connection tracking
+      context, so tracking the same packet in multiple contexts requires using
+      the <code>ct</code> action multiple times.
+    </field>
+
+    <field id="MFF_CT_MARK" title="Connection Tracking Mark">
+      The metadata committed, by an action within the <code>exec</code>
+      parameter to the <code>ct</code> action, to the connection to which the
+      current packet belongs.
+    </field>
+
+    <field id="MFF_CT_LABEL" title="Connection Tracking Label">
+      The label committed, by an action within the <code>exec</code>
+      parameter to the <code>ct</code> action, to the connection to which the
+      current packet belongs.
+    </field>
+  </group>
+
+  <group title="Register">
+    <p>
+      These fields give an OpenFlow switch space for temporary storage while
+      the pipeline is running.  Whereas metadata fields can have a meaningful
+      initial value and can persist across some hops across OpenFlow switches,
+      registers are always initially 0 and their values never persist across
+      inter-switch hops (not even across patch ports).
+    </p>
+
+    <field id="MFF_METADATA" title="OpenFlow Metadata">
+      <p>
+	This field is the oldest standardized OpenFlow register field,
+	introduced in OpenFlow 1.1.  It was introduced to model the limited
+	number of user-defined bits that some ASIC-based switches can carry
+	through their pipelines.  Because of hardware limitations, OpenFlow
+	allows switches to support writing and masking only an
+	implementation-defined subset of bits, even no bits at all.  The Open
+	vSwitch software switch always supports all 64 bits, but of course an
+	Open vSwitch port to an ASIC would have the same restriction as the
+	ASIC itself.
+      </p>
+
+      <p>
+	This field has an OXM code point, but OpenFlow 1.4 and earlier allow it
+	to be modified only with a specialized instruction, not with a
+	``set-field'' action.  OpenFlow 1.5 removes this restriction.  Open
+	vSwitch does not enforce this restriction, regardless of OpenFlow
+	version.
+      </p>
+    </field>
+
+    <field id="MFF_REG0" title="Register 0">
+      This is the first of several Open vSwitch registers, all of which have
+      the same properties.  Open vSwitch 1.1 introduced registers 0, 1, 2, and
+      3, version 1.3 added register 4, version 1.7 added registers 5, 6, and 7,
+      and version 2.6 added registers 8 through 15.
+    </field>
+    <!-- XXX series -->
+    <field id="MFF_REG1" title="Register 1" hidden="yes"/>
+    <field id="MFF_REG2" title="Register 2" hidden="yes"/>
+    <field id="MFF_REG3" title="Register 3" hidden="yes"/>
+    <field id="MFF_REG4" title="Register 4" hidden="yes"/>
+    <field id="MFF_REG5" title="Register 5" hidden="yes"/>
+    <field id="MFF_REG6" title="Register 6" hidden="yes"/>
+    <field id="MFF_REG7" title="Register 7" hidden="yes"/>
+    <field id="MFF_REG8" title="Register 8" hidden="yes"/>
+    <field id="MFF_REG9" title="Register 9" hidden="yes"/>
+    <field id="MFF_REG10" title="Register 10" hidden="yes"/>
+    <field id="MFF_REG11" title="Register 11" hidden="yes"/>
+    <field id="MFF_REG12" title="Register 12" hidden="yes"/>
+    <field id="MFF_REG13" title="Register 13" hidden="yes"/>
+    <field id="MFF_REG14" title="Register 14" hidden="yes"/>
+    <field id="MFF_REG15" title="Register 15" hidden="yes"/>
+
+    <field id="MFF_XREG0" title="Extended Register 0">
+      <p>
+        This is the first of the registers introduced in OpenFlow 1.5.
+        OpenFlow 1.5 calls these fields just the ``packet registers,'' but Open
+        vSwitch already had 32-bit registers by that name, so Open vSwitch uses
+        the name ``extended registers'' in an attempt to reduce confusion.  The
+        standard allows for up to 128 registers, each 64 bits wide, but Open
+        vSwitch only implements 4 (in versions 2.4 and 2.5) or 8 (in version
+        2.6 and later).
+      </p>
+
+      <p>
+        Each of the 64-bit extended registers overlays two of the 32-bit
+        registers: <code>xreg0</code> overlays <code>reg0</code> and
+        <code>reg1</code>, with <code>reg0</code> supplying the
+        most-significant bits of <code>xreg0</code> and <code>reg1</code> the
+        least-significant.  Similarly, <code>xreg1</code> overlays
+        <code>reg2</code> and <code>reg3</code>, and so on.
+      </p>
+
+      <p>
+        The OpenFlow specification says that, ``In most cases, the packet
+        registers can not be matched in tables, i.e. they usually can not be
+        used in the flow entry match structure'' [OpenFlow 1.5, section
+        7.2.3.10], but there is no reason for a software switch to impose such
+        a restriction, and Open vSwitch does not.
+      </p>
+    </field>
+
+    <!-- XXX series -->
+    <field id="MFF_XREG1" title="Extended Register 1" hidden="yes"/>
+    <field id="MFF_XREG2" title="Extended Register 2" hidden="yes"/>
+    <field id="MFF_XREG3" title="Extended Register 3" hidden="yes"/>
+    <field id="MFF_XREG4" title="Extended Register 4" hidden="yes"/>
+    <field id="MFF_XREG5" title="Extended Register 5" hidden="yes"/>
+    <field id="MFF_XREG6" title="Extended Register 6" hidden="yes"/>
+    <field id="MFF_XREG7" title="Extended Register 7" hidden="yes"/>
+
+    <field id="MFF_XXREG0" title="Double-Extended Register 0">
+      <p>
+        This is the first of the double-extended registers introduce in Open
+        vSwitch 2.6. Each of the 128-bit extended registers overlays four of
+        the 32-bit registers: <code>xxreg0</code> overlays <code>reg0</code>
+        through <code>reg3</code>, with <code>reg0</code> supplying the
+        most-significant bits of <code>xxreg0</code> and <code>reg3</code> the
+        least-significant.  <code>xxreg1</code> similarly overlays
+        <code>reg4</code> through <code>reg7</code>, and so on.
+      </p>
+    </field>
+
+    <!-- XXX series -->
+    <field id="MFF_XXREG1" title="Double-Extended Register 1" hidden="yes"/>
+    <field id="MFF_XXREG2" title="Double-Extended Register 2" hidden="yes"/>
+    <field id="MFF_XXREG3" title="Double-Extended Register 3" hidden="yes"/>
+  </group>
+
+  <group title="Layer 2 (Ethernet)">
+    <p>
+      Ethernet is the only layer-2 protocol that Open vSwitch
+      supports.  As with most software, Open vSwitch and OpenFlow
+      regard an Ethernet frame to begin with the 14-byte header and
+      end with the final byte of the payload; that is, the frame check
+      sequence is not considered part of the frame.
+    </p>
+
+    <field id="MFF_ETH_SRC" title="Ethernet Source">
+      <p>
+        The Ethernet source address:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75"/>
+	  <bits name="src" above="48" width=".75" fill="yes"/>
+	  <bits name="type" above="16" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+    </field>
+
+    <field id="MFF_ETH_DST" title="Ethernet Destination">
+      <p>
+	The Ethernet destination address:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75" fill="yes"/>
+	  <bits name="src" above="48" width=".75"/>
+	  <bits name="type" above="16" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+        Open vSwitch 1.8 and later support arbitrary masks for source and/or
+        destination.  Earlier versions only support masking the destination
+        with the following masks:
+      </p>
+
+      <dl>
+        <dt><code>01:00:00:00:00:00</code></dt>
+        <dd>
+          Match only the multicast bit.  Thus,
+          <code>dl_dst=01:00:00:00:00:00/01:00:00:00:00:00</code> matches all
+          multicast (including broadcast) Ethernet packets, and
+          <code>dl_dst=00:00:00:00:00:00/01:00:00:00:00:00</code> matches all
+          unicast Ethernet packets.
+        </dd>
+
+        <dt><code>fe:ff:ff:ff:ff:ff</code></dt>
+        <dd>
+          Match all bits except the multicast bit.  This is probably not
+          useful.
+        </dd>
+
+        <dt><code>ff:ff:ff:ff:ff:ff</code></dt>
+        <dd>
+          Exact match (equivalent to omitting the mask).
+        </dd>
+
+        <dt><code>00:00:00:00:00:00</code></dt>
+        <dd>
+          Wildcard all bits (equivalent to <code>dl_dst=*</code>.)
+        </dd>
+      </dl>
+    </field>
+
+    <field id="MFF_ETH_TYPE" title="Ethernet Type">
+      <p>
+	The most commonly seen Ethernet frames today use a format
+	called ``Ethernet II,'' in which the last two bytes of the
+	Ethernet header specify the Ethertype.  For such a frame, this
+	field is copied from those bytes of the header, like so:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75"/>
+	  <bits name="src" above="48" width=".75"/>
+	  <bits name="type" above="16" below="\[&gt;=]0x600" width="0.4" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+	Every Ethernet type has a value 0x600 (1,536) or greater.
+	When the last two bytes of the Ethernet header have a value
+	too small to be an Ethernet type, then the value found there
+	is the total length of the frame in bytes, excluding the
+	Ethernet header.  An 802.2 LLC header typically follows the
+	Ethernet header.  OpenFlow and Open vSwitch only support LLC
+	headers with DSAP and SSAP <code>0xaa</code> and control byte
+	<code>0x03</code>, which indicate that a SNAP header follows
+	the LLC header.  In turn, OpenFlow and Open vSwitch only
+	support a SNAP header with organization <code>0x000000</code>.
+	In such a case, this field is copied from the type field in
+	the SNAP header, like this:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75"/>
+	  <bits name="src" above="48" width=".75"/>
+	  <bits name="type" above="16" below="&lt;0x600" width="0.4"/>
+	</header>
+	<header name="LLC">
+	  <bits name="DSAP" above="8" below="0xaa" width=".4"/>
+	  <bits name="SSAP" above="8" below="0xaa" width=".4"/>
+	  <bits name="cntl" above="8" below="0x03" width=".4"/>
+	</header>
+	<header name="SNAP">
+	  <bits name="org" above="24" below="0x000000" width=".75"/>
+	  <bits name="type" above="16" below="\[&gt;=]0x600" width=".4" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+	When an 802.1Q header is inserted after the Ethernet source
+	and destination, this field is populated with the encapsulated
+	Ethertype, not the 802.1Q Ethertype.  With an Ethernet II
+	inner frame, the result looks like this:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75"/>
+	  <bits name="src" above="48" width=".75"/>
+	</header>
+	<header name="802.1Q">
+	  <bits name="TPID" above="16" below="0x8100" width=".4"/>
+	  <bits name="TCI" above="16" width=".4"/>
+	</header>
+	<header name="Ethertype">
+	  <bits name="type" above="16" below="\[&gt;=]0x600" width=".4" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+	LLC and SNAP encapsulation look like this with an 802.1Q header:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width=".75"/>
+	  <bits name="src" above="48" width=".75"/>
+	</header>
+	<header name="802.1Q">
+	  <bits name="TPID" above="16" below="0x8100" width=".4"/>
+	  <bits name="TCI" above="16" width=".4"/>
+	</header>
+	<header name="Ethertype">
+	  <bits name="type" above="16" below="&lt;0x600" width="0.4"/>
+	</header>
+	<header name="LLC">
+	  <bits name="DSAP" above="8" below="0xaa" width=".4"/>
+	  <bits name="SSAP" above="8" below="0xaa" width=".4"/>
+	  <bits name="cntl" above="8" below="0x03" width=".4"/>
+	</header>
+	<header name="SNAP">
+	  <bits name="org" above="24" below="0x000000" width=".75"/>
+	  <bits name="type" above="16" below="\[&gt;=]0x600" width=".4" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+	When a packet doesn't match any of the header formats described
+	above, Open vSwitch and OpenFlow set this field to
+	<code>0x5ff</code> (<code>OFP_DL_TYPE_NOT_ETH_TYPE</code>).
+      </p>
+    </field>
+  </group>
+
+  <group title="VLAN">
+    <p>
+      The 802.1Q VLAN header causes more trouble than any other 4
+      bytes in networking.  OpenFlow 1.0, 1.1, and 1.2+ all treat VLANs
+      differently.  Open vSwitch extensions add another variant to the mix.
+      Open vSwitch reconciles all four treatments as best it can.
+    </p>
+
+    <h2>VLAN Header Format</h2>
+
+    <p>
+      An 802.1Q VLAN header consists of two 16-bit fields:
+    </p>
+
+    <diagram>
+      <header name="TPID">
+	<bits name="Ethertype" above="16" below="0x8100" width="1.8"/>
+      </header>
+      <nospace/>
+      <header name="TCI">
+	<bits name="PCP" above="3" width=".6"/>
+	<bits name="CFI" above="1" below="0" width=".3"/>
+	<bits name="VID" above="12" width=".9"/>
+      </header>
+    </diagram>
+
+    <p>
+      The first 16 bits of the VLAN header, the <dfn>TPID</dfn> (Tag Protocol
+      IDentifier), is an Ethertype.  When the VLAN header is inserted just
+      after the source and destination MAC addresses in a Ethertype frame, the
+      TPID serves to identify the presence of the VLAN.  The standard TPID, the
+      only one that Open vSwitch supports, is <code>0x8100</code>.  OpenFlow
+      1.0 explicitly supports only TPID <code>0x8100</code>.  OpenFlow 1.1, but
+      not earlier or later versions, also requires support for TPID
+      <code>0x88a8</code> (Open vSwitch does not support this).  OpenFlow 1.2
+      through 1.5 do not require support for specific TPIDs (the ``push vlan
+      header'' action does say that only <code>0x8100</code> and
+      <code>0x88a8</code> should be pushed).  No version of OpenFlow provides a
+      way to distinguish or match on the TPID.
+    </p>
+
+    <p>
+      The remaining 16 bits of the VLAN header, the <dfn>TCI</dfn>
+      (Tag Control Information), is subdivided into three subfields:
+    </p>
+
+    <ul>
+      <li>
+	<dfn>PCP</dfn> (Priority Control Point), is a 3-bit 802.1p
+	<dfn>priority</dfn>.  The lowest priority is value 1, the
+	second-lowest is value 0, and priority increases from 2 up to
+	highest priority 7.
+      </li>
+
+      <li>
+        <p>
+	  <dfn>CFI</dfn> (Canonical Format Indicator), is a 1-bit field.  On an
+	  Ethernet network, its value is always 0.  This led to it later being
+	  repurposed under the name <dfn>DEI</dfn> (Drop Eligibility
+	  Indicator).  By either name, OpenFlow and Open vSwitch don't provide
+	  any way to match or set this bit.
+        </p>
+      </li>
+
+      <li>
+	<dfn>VID</dfn> (VLAN IDentifier), is a 12-bit VLAN.  If the
+	VID is 0, then the frame is not part of a VLAN.  In that case,
+	the VLAN header is called a <dfn>priority tag</dfn> because it
+	is only meaningful for assigning the frame a priority.  VID
+	<code>0xfff</code> (4,095) is reserved.
+      </li>
+    </ul>
+
+    <p>
+      See <ref field="eth_type"/> for illustrations of a complete Ethernet
+      frame with 802.1Q tag included.
+    </p>
+
+    <h2>Multiple VLANs</h2>
+
+    <p>
+      Open vSwitch can match only a single VLAN header.  If more than
+      one VLAN header is present, then <ref field="eth_type"/>
+      holds the TPID of the inner VLAN header.  Open vSwitch stops
+      parsing the packet after the inner TPID, so matching further
+      into the packet (e.g. on the inner TCI or L3 fields) is not
+      possible.
+    </p>
+
+    <p>
+      OpenFlow only directly supports matching a single VLAN header.  In
+      OpenFlow 1.1 or later, one OpenFlow table can match on the outermost VLAN
+      header and pop it off, and a later OpenFlow table can match on the next
+      outermost header.  Open vSwitch does not support this.
+    </p>
+
+    <h2>VLAN Field Details</h2>
+
+    <p>
+      The four variants have three different levels of expressiveness: OpenFlow
+      1.0 and 1.1 VLAN matching are less powerful than OpenFlow 1.2+ VLAN
+      matching, which is less powerful than Open vSwitch extension VLAN
+      matching.
+    </p>
+
+    <h2>OpenFlow 1.0 VLAN Fields</h2>
+
+    <p>
+      OpenFlow 1.0 uses two fields, called <code>dl_vlan</code> and
+      <code>dl_vlan_pcp</code>, each of which can be either exact-matched or
+      wildcarded, to specify VLAN matches:
+    </p>
+
+    <ul>
+      <li>
+	When both <code>dl_vlan</code> and <code>dl_vlan_pcp</code> are
+	wildcarded, the flow matches packets without an 802.1Q header or
+	with any 802.1Q header.
+      </li>
+
+      <li>
+        The match <code>dl_vlan=0xffff</code> causes a flow to match only
+        packets without an 802.1Q header.  Such a flow should also wildcard
+        <code>dl_vlan_pcp</code>, since a packet without an 802.1Q header does
+        not have a PCP.  OpenFlow does not specify what to do if a match on PCP
+        is actually present, but Open vSwitch ignores it.
+      </li>
+
+      <li>
+	<p>
+	  Otherwise, the flow matches only packets with an 802.1Q
+	  header.  If <code>dl_vlan</code> is not wildcarded, then the
+	  flow only matches packets with the VLAN ID specified in
+	  <code>dl_vlan</code>'s low 12 bits.  If
+	  <code>dl_vlan_pcp</code> is not wildcarded, then the flow
+	  only matches packets with the priority specified in
+	  <code>dl_vlan_pcp</code>'s low 3 bits.
+	</p>
+
+	<p>
+	  OpenFlow does not specify how to interpret the high 4 bits of
+	  <code>dl_vlan</code> or the high 5 bits of <code>dl_vlan_pcp</code>.
+	  Open vSwitch ignores them.
+	</p>
+      </li>
+    </ul>
+
+    <field id="MFF_DL_VLAN" title="OpenFlow 1.0 VLAN ID" hidden="yes"/>
+    <field id="MFF_DL_VLAN_PCP" title="OpenFlow 1.0 VLAN Priority"
+	   hidden="yes"/>
+
+    <h2>OpenFlow 1.1 VLAN Fields</h2>
+
+    <p>
+      VLAN matching in OpenFlow 1.1 is similar to OpenFlow 1.0.
+      The one refinement is that when <code>dl_vlan</code> matches on
+      <code>0xfffe</code> (<code>OFVPID_ANY</code>), the flow matches
+      only packets with an 802.1Q header, with any VLAN ID.  If
+      <code>dl_vlan_pcp</code> is wildcarded, the flow matches any
+      packet with an 802.1Q header, regardless of VLAN ID or priority.
+      If <code>dl_vlan_pcp</code> is not wildcarded, then the flow
+      only matches packets with the priority specified in
+      <code>dl_vlan_pcp</code>'s low 3 bits.
+    </p>
+
+    <p>
+      OpenFlow 1.1 uses the name <code>OFPVID_NONE</code>, instead of
+      <code>OFP_VLAN_NONE</code>, for a <code>dl_vlan</code> of
+      <code>0xffff</code>, but it has the same meaning.
+    </p>
+
+    <p>
+      In OpenFlow 1.1, Open vSwitch reports error
+      <code>OFPBMC_BAD_VALUE</code> for an attempt to match on
+      <code>dl_vlan</code> between 4,096 and <code>0xfffd</code>,
+      inclusive, or <code>dl_vlan_pcp</code> greater than 7.
+    </p>
+
+    <h2>OpenFlow 1.2 VLAN Fields</h2>
+
+    <field id="MFF_VLAN_VID" title="OpenFlow 1.2+ VLAN ID">
+      <p>
+	The OpenFlow standard describes this field as consisting of
+	``12+1'' bits.  On ingress, its value is 0 if no 802.1Q header
+	is present, and otherwise it holds the VLAN VID in its least
+	significant 12 bits, with bit 12 (<code>0x1000</code> aka
+	<code>OFPVID_PRESENT</code>) also set to 1.  The three most
+	significant bits are always zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_VLAN_VID">
+	  <bits name="" above="3" below="0" width=".6"/>
+	  <bits name="P" above="1" width=".1"/>
+	  <bits name="VLAN ID" above="12" width=".9"/>
+	</header>
+      </diagram>
+
+      <p>
+	As a consequence of this field's format, one may use it to match the
+	VLAN ID in all of the ways available with the OpenFlow 1.0 and 1.1
+	formats, and a few new ways:
+      </p>
+
+      <dl>
+	<dt>Fully wildcarded</dt>
+	<dd>
+	  Matches any packet, that is, one without an 802.1Q header or
+	  with an 802.1Q header with any TCI value.
+	</dd>
+
+	<dt>
+	  Value <code>0x0000</code> (<code>OFPVID_NONE</code>), mask
+	  <code>0xffff</code> (or no mask)
+	</dt>
+	<dd>
+	  Matches only packets without an 802.1Q header.
+	</dd>
+
+	<dt>
+	  Value <code>0x1000</code>, mask <code>0x1000</code>
+	</dt>
+	<dd>
+	  Matches any packet with an 802.1Q header, regardless of VLAN
+	  ID.
+	</dd>
+
+	<dt>
+	  Value <code>0x1009</code>, mask <code>0xffff</code> (or no mask)
+	</dt>
+	<dd>
+	  Match only packets with an 802.1Q header with VLAN ID 9.
+	</dd>
+
+	<dt>Value <code>0x1001</code>, mask <code>0x1001</code></dt>
+	<dd>
+	  Matches only packets that have an 802.1Q header with an
+	  odd-numbered VLAN ID.  (This is just an example; one can
+	  match on any desired VLAN ID bit pattern.)
+	</dd>
+      </dl>
+    </field>
+
+    <field id="MFF_VLAN_PCP" title="OpenFlow 1.2+ VLAN Priority">
+      <p>
+	The 3 least significant bits may be used to match the PCP bits
+	in an 802.1Q header.  Other bits are always zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_VLAN_VID">
+	  <bits name="zero" above="5" below="0" width="1.0"/>
+	  <bits name="PCP" above="3" width=".6"/>
+	</header>
+      </diagram>
+
+      <p>
+	May only be used when <ref field="vlan_vid"/> is not
+	wildcarded and does not exact match on 0 (which only matches
+	when there is no 802.1Q header).
+      </p>
+
+      <p>
+	See <cite>VLAN Comparison Chart</cite>, below, for some examples.
+      </p>
+    </field>
+
+    <h2>Open vSwitch Extension VLAN Field</h2>
+
+    <p>
+      This extension <ref field="vlan_tci"/> can describe more kinds of VLAN
+      matches than the other variants.  It is also simpler than the other
+      variants.
+    </p>
+
+    <field id="MFF_VLAN_TCI" title="VLAN TCI">
+      <p>
+	For a packet without an 802.1Q header, this field is zero.  For a
+	packet with an 802.1Q header, this field is the TCI with the bit in
+	CFI's position (marked <code>P</code> for ``present'' below) forced to
+	1.  Thus, for a packet in VLAN 9 with priority 7, it has the value
+	<code>0xf009</code>:
+      </p>
+
+      <diagram>
+	<header name="NXM_VLAN_TCI">
+	  <bits name="PCP" above="3" below="7" width=".6"/>
+	  <bits name="P" above="1" below="1" width=".2"/>
+	  <bits name="VID" above="12" below="9" width=".9"/>
+	  </header>
+      </diagram>
+
+      <p>
+        Usage examples:
+      </p>
+
+      <dl>
+        <dt><code>vlan_tci=0</code></dt>
+        <dd>
+          Match packets without an 802.1Q header.
+        </dd>
+
+        <dt><code>vlan_tci=0x1000/0x1000</code></dt>
+        <dd>
+          Match packets with an 802.1Q header, regardless  of  VLAN
+          and priority values.
+        </dd>
+
+        <dt><code>vlan_tci=0xf123</code></dt>
+        <dd>
+          Match packets tagged with priority 7 in VLAN 0x123.
+        </dd>
+
+        <dt><code>vlan_tci=0x1123/0x1fff</code></dt>
+        <dd>
+          Match packets tagged with VLAN 0x123 (and any priority).
+        </dd>
+
+        <dt><code>vlan_tci=0x5000/0xf000</code></dt>
+        <dd>
+          Match packets tagged with priority 2 (in any VLAN).
+        </dd>
+
+        <dt><code>vlan_tci=0/0xfff</code></dt>
+        <dd>
+          Match packets with no 802.1Q header or tagged with VLAN 0
+          (and any priority).
+        </dd>
+
+        <dt><code>vlan_tci=0x5000/0xe000</code></dt>
+        <dd>
+          Match packets with no 802.1Q header or tagged with prior‐
+          ity 2 (in any VLAN).
+        </dd>
+
+        <dt><code>vlan_tci=0/0xefff</code></dt>
+        <dd>
+          Match packets with no 802.1Q header or tagged with VLAN 0
+          and priority 0.
+        </dd>
+      </dl>
+
+      <p>
+	See <cite>VLAN Comparison Chart</cite>, below, for more examples.
+      </p>
+    </field>
+
+    <h2>VLAN Comparison Chart</h2>
+
+    <p>
+      The following table describes each of several possible matching
+      criteria on 802.1Q header may be expressed with each variation
+      of the VLAN matching fields:
+    </p>
+
+    <tbl>
+r r r r r.
+Criteria	OpenFlow 1.0	OpenFlow 1.1	OpenFlow 1.2+	NXM
+\_	\_	\_	\_	\_
+[1]	\fL????\fR/\fL1\fR,\fL??\fR/\fL?\fR	\fL????\fR/\fL1\fR,\fL??\fR/\fL?\fR	\fL0000\fR/\fL0000\fR,\fL--\fR	\fL0000\fR/\fL0000\fR
+[2]	\fLffff\fR/\fL0\fR,\fL??\fR/\fL?\fR	\fLffff\fR/\fL0\fR,\fL??\fR/\fL?\fR	\fL0000\fR/\fLffff\fR,\fL--\fR	\fL0000\fR/\fLffff\fR
+[3]	\fL0xxx\fR/\fL0\fR,\fL??\fR/\fL1\fR	\fL0xxx\fR/\fL0\fR,\fL??\fR/\fL1\fR	\fL1xxx\fR/\fLffff\fR,\fL--\fR	\fL1xxx\fR/\fL1fff\fR
+[4]	\fL????\fR/\fL1\fR,\fL0y\fR/\fL0\fR	\fLfffe\fR/\fL0\fR,\fL0y\fR/\fL0\fR	\fL1000\fR/\fL1000\fR,\fL0y\fR	\fLz000\fR/\fLf000\fR
+[5]	\fL0xxx\fR/\fL0\fR,\fL0y\fR/\fL0\fR	\fL0xxx\fR/\fL0\fR,\fL0y\fR/\fL0\fR	\fL1xxx\fR/\fLffff\fR,\fL0y\fR	\fLzxxx\fR/\fLffff\fR
+.T&amp;
+r r c c r.
+[6]	(none)	(none)	\fL1001\fR/\fL1001\fR,\fL--\fR	\fL1001\fR/\fL1001\fR
+.T&amp;
+r r c c c.
+[7]	(none)	(none)	(none)	\fL3000\fR/\fL3000\fR
+[8]	(none)	(none)	(none)	\fL0000\fR/\fL0fff\fR
+[9]	(none)	(none)	(none)	\fL0000\fR/\fLf000\fR
+[10]	(none)	(none)	(none)	\fL0000\fR/\fLefff\fR
+    </tbl>
+
+    <p>
+      All numbers in the table are expressed in hexadecimal.  The
+      columns in the table are interpreted as follows:
+    </p>
+
+    <dl>
+      <dt>Criteria</dt>
+      <dd>See the list below.</dd>
+
+      <dt>OpenFlow 1.0</dt>
+      <dt>OpenFlow 1.1</dt>
+      <dd>
+	<literal>wwww/x,yy/z</literal> means VLAN ID match value
+	<literal>wwww</literal> with wildcard bit <literal>x</literal>
+	and VLAN PCP match value <literal>yy</literal> with wildcard
+	bit <literal>z</literal>.  <literal>?</literal> means that the
+	given bits are ignored (and conventionally
+	<literal>0</literal> for <literal>wwww</literal> or
+	<literal>yy</literal>, conventionally <literal>1</literal> for
+	<literal>x</literal> or <literal>z</literal>).  ``(none)''
+	means that OpenFlow 1.0 (or 1.1) cannot match with these
+	criteria.
+      </dd>
+
+      <dt>OF1.2</dt>
+      <dd>
+	<literal>xxxx/yyyy,zz</literal> means <ref field="vlan_vid"/> with
+	value <literal>xxxx</literal> and mask <literal>yyyy</literal>, and
+	<ref field="vlan_pcp"/> (which is not maskable) with value
+	<literal>zz</literal>.  <literal>--</literal> means that <ref
+	field="vlan_pcp"/> is omitted.  ``(none)'' means that OpenFlow 1.2
+	cannot match with these criteria.
+      </dd>
+
+      <dt>NXM</dt>
+      <dd>
+	<literal>xxxx/yyyy</literal> means <ref field="vlan_tci"/> with value
+	<literal>xxxx</literal> and mask <literal>yyyy</literal>.
+      </dd>
+    </dl>
+
+    <p>
+      The matching criteria described by the table are:
+    </p>
+
+    <dl>
+      <dt>[1]</dt>
+      <dd>
+	Matches any packet, that is, one without an 802.1Q header or
+	with an 802.1Q header with any TCI value.
+      </dd>
+
+      <dt>[2]</dt>
+      <dd>
+	<p>
+	  Matches only packets without an 802.1Q header.
+	</p>
+
+	<p>
+	  OpenFlow 1.0 doesn't define the behavior if <ref field="dl_vlan"/> is
+	  set to <code>0xffff</code> and <ref field="dl_vlan_pcp"/> is not
+	  wildcarded.  (Open vSwitch always ignores <ref field="dl_vlan_pcp"/>
+	  when <ref field="dl_vlan"/> is set to <code>0xffff</code>.)
+	</p>
+
+	<p>
+	  OpenFlow 1.1 says explicitly to ignore <ref field="dl_vlan_pcp"/>
+	  when <ref field="dl_vlan"/> is set to <code>0xffff</code>.
+	</p>
+
+	<p>
+	  OpenFlow 1.2 doesn't say how to interpret a match with <ref
+	  field="vlan_vid"/> value 0 and a mask with
+	  <code>OFPVID_PRESENT</code> (<code>0x1000</code>) set to 1 and some
+	  other bits in the mask set to 1 also.  Open vSwitch interprets it the
+	  same way as a mask of <code>0x1000</code>.
+	</p>
+
+	<p>
+	  Any NXM match with <ref field="vlan_tci"/> value 0 and the CFI bit
+	  set to 1 in the mask is equivalent to the one listed in the table.
+	</p>
+      </dd>
+
+      <dt>[3]</dt>
+      <dd>
+	Matches only packets that have an 802.1Q header with VID
+	<literal>xxx</literal> (and any PCP).
+      </dd>
+
+      <dt>[4]</dt>
+      <dd>
+	<p>
+	  Matches only packets that have an 802.1Q header with PCP
+	  <literal>y</literal> (and any VID).
+	</p>
+
+	<p>
+	  OpenFlow 1.0 doesn't clearly define the behavior for this
+	  case.  Open vSwitch implements it this way.
+	</p>
+
+	<p>
+	  In the NXM value, <literal>z</literal> equals
+	  (<literal>y</literal> &lt;&lt; 1) | 1.
+	</p>
+      </dd>
+
+      <dt>[5]</dt>
+      <dd>
+	<p>
+	  Matches only packets that have an 802.1Q header with VID
+	  <literal>xxx</literal> and PCP <literal>y</literal>.
+	</p>
+
+	<p>
+	  In the NXM value, <literal>z</literal> equals
+	  (<literal>y</literal> &lt;&lt; 1) | 1.
+	</p>
+      </dd>
+
+      <dt>[6]</dt>
+      <dd>
+	Matches only packets that have an 802.1Q header with an
+	odd-numbered VID (and any PCP).  Only possible with OpenFlow
+	1.2 and NXM.  (This is just an example; one can match on any
+	desired VID bit pattern.)
+      </dd>
+
+      <dt>[7]</dt>
+      <dd>
+	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.)
+      </dd>
+
+      <dt>[8]</dt>
+      <dd>
+	Matches packets with no 802.1Q header or with an 802.1Q header
+	with a VID of 0.  Only possible with NXM.
+      </dd>
+
+      <dt>[9]</dt>
+      <dd>
+	Matches packets with no 802.1Q header or with an 802.1Q header
+	with a PCP of 0.  Only possible with NXM.
+      </dd>
+
+      <dt>[10]</dt>
+      <dd>
+	Matches packets with no 802.1Q header or with an 802.1Q header
+	with both VID and PCP of 0.  Only possible with NXM.
+      </dd>
+    </dl>
+  </group>
+
+  <group title="Layer 2.5: MPLS">
+    <p>
+      One or more MPLS headers (more commonly called <dfn>MPLS
+      labels</dfn>) follow an Ethernet type field that specifies an
+      MPLS Ethernet type [RFC 3032].  Ethertype <code>0x8847</code> is
+      used for all unicast.  Multicast MPLS is divided into two
+      specific classes, one of which uses Ethertype
+      <code>0x8847</code> and the other <code>0x8848</code> [RFC
+      5332].
+    </p>
+
+    <p>
+      The most common overall packet format is Ethernet II, shown
+      below (SNAP encapsulation may be used but is not ordinarily seen
+      in Ethernet networks):
+    </p>
+
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.75"/>
+	<bits name="src" above="48" width="0.75"/>
+	<bits name="type" above="16" below="0x8847" width="0.4"/>
+      </header>
+      <header name="MPLS">
+	<bits name="label" above="20" width=".6"/>
+	<bits name="TC" above="3" width=".3"/>
+	<bits name="S" above="1" width=".1"/>
+	<bits name="TTL" above="8" width=".4"/>
+      </header>
+      <dots/>
+    </diagram>
+
+    <p>
+      MPLS can be encapsulated inside an 802.1Q header, in which case
+      the combination looks like this:
+    </p>
+
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width=".75"/>
+	<bits name="src" above="48" width=".75"/>
+      </header>
+      <header name="802.1Q">
+	<bits name="TPID" above="16" below="0x8100" width=".4"/>
+	<bits name="TCI" above="16" width=".4"/>
+      </header>
+      <header name="Ethertype">
+	<bits name="type" above="16" below="0x8847" width=".4"/>
+      </header>
+      <header name="MPLS">
+	<bits name="label" above="20" width=".6"/>
+	<bits name="TC" above="3" width=".3"/>
+	<bits name="S" above="1" width=".1"/>
+	<bits name="TTL" above="8" width=".4"/>
+      </header>
+      <dots/>
+    </diagram>
+
+    <p>
+      The fields within an MPLS label are:
+    </p>
+
+    <dl>
+      <dt>Label, 20 bits.</dt>
+      <dd>
+	An identifier.
+      </dd>
+
+      <dt>Traffic control (TC), 3 bits.</dt>
+      <dd>
+	Used for quality of service.
+      </dd>
+
+      <dt>Bottom of stack (BOS), 1 bit (labeled just ``S'' above).</dt>
+      <dd>
+	<p>
+	  0 indicates that another MPLS label follows this one.
+	</p>
+
+	<p>
+	  1 indicates that this MPLS label is the last one in the
+	  stack, so that some other protocol follows this one.
+	</p>
+      </dd>
+
+      <dt>Time to live (TTL), 8 bits.</dt>
+      <dd>
+	<p>
+	  Each hop across an MPLS network decrements the TTL by 1.  If
+	  it reaches 0, the packet is discarded.
+	</p>
+
+	<p>
+	  OpenFlow does not make the MPLS TTL available as a match field, but
+	  actions are available to set and decrement the TTL.  Open vSwitch 2.6
+	  and later makes the MPLS TTL available as an extension.
+	</p>
+      </dd>
+    </dl>
+
+    <h2>MPLS Label Stacks</h2>
+
+    <p>
+      Unlike the other encapsulations supported by OpenFlow and Open vSwitch,
+      MPLS labels are routinely used in ``stacks'' two or three deep and
+      sometimes even deeper.  Open vSwitch currently supports up to three
+      labels.
+    </p>
+
+    <p>
+      OpenFlow only supports matching on the outermost MPLS label at any given
+      time.  To match on the second label, one must first ``pop'' the outer
+      label and advance to another OpenFlow table, where the inner label may be
+      matched.  To match on the third label, one must pop the two outer labels,
+      and so on.  The Open Networking Foundation is considering support for
+      directly matching on multiple MPLS labels for OpenFlow 1.6.<!-- XXX add
+      EXT-* link -->
+    </p>
+
+    <h2>MPLS Inner Protocol</h2>
+
+    <p>
+      Unlike all other forms of encapsulation that Open vSwitch and
+      OpenFlow support, an MPLS label does not indicate what inner
+      protocol it encapsulates.  Different deployments determine the
+      inner protocol in different ways [RFC 3032]:
+    </p>
+
+    <ul>
+      <li>
+	A few reserved label values do indicate an inner protocol.
+	Label 0, the ``IPv4 Explicit NULL Label,'' indicates inner
+	IPv4.  Label 2, the ``IPv6 Explicit NULL Label,'' indicates
+	inner IPv6.
+      </li>
+
+      <li>
+	Some deployments use a single inner protocol consistently.
+      </li>
+
+      <li>
+	In some deployments, the inner protocol must be inferred from
+	the innermost label.
+      </li>
+
+      <li>
+	In some deployments, the inner protocol must be inferred from
+	the innermost label and the encapsulated data, e.g. to
+	distinguish between inner IPv4 and IPv6 based on whether the
+	first nibble of the inner protocol data are <code>4</code> or
+	<code>6</code>.  OpenFlow and Open vSwitch do not currently
+	support these cases.
+      </li>
+    </ul>
+
+    <h2>Field Details</h2>
+
+    <field id="MFF_MPLS_LABEL" title="MPLS Label">
+      <p>
+	The least significant 20 bits hold the ``label'' field from
+	the MPLS label.  Other bits are zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_MPLS_LABEL">
+	  <bits name="zero" above="12" below="0" width=".6"/>
+	  <bits name="label" above="20" width="1.0"/>
+	</header>
+      </diagram>
+
+      <p>
+	Most label values are available for any use by deployments.
+	Values under 16 are reserved.
+      </p>
+    </field>
+
+    <field id="MFF_MPLS_TC" title="MPLS Traffic Class">
+      <p>
+	The least significant 3 bits hold the TC field from the MPLS
+	label.  Other bits are zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_MPLS_TC">
+	  <bits name="zero" above="5" below="0" width="1.0"/>
+	  <bits name="TC" above="3" width=".6"/>
+	</header>
+      </diagram>
+
+      <p>
+	This field is intended for use for Quality of Service (QoS)
+	and Explicit Congestion Notification purposes, but its
+	particular interpretation is deployment specific.
+      </p>
+
+      <p>
+	Before 2009, this field was named EXP and reserved for
+	experimental use [RFC 5462].
+      </p>
+    </field>
+
+    <field id="MFF_MPLS_BOS" title="MPLS Bottom of Stack">
+      <p>
+	The least significant bit holds the BOS field from the MPLS
+	label.  Other bits are zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_MPLS_BOS">
+	  <bits name="zero" above="7" below="0" width="1.3"/>
+	  <bits name="BOS" above="1" width=".3"/>
+	</header>
+      </diagram>
+
+      <p>
+	This field is useful as part of processing a series of incoming MPLS
+	labels.  A flow that includes a <code>pop_mpls</code> action should
+	generally match on <ref field="mpls_bos"/>:
+      </p>
+
+      <ul>
+	<li>
+	  When <ref field="mpls_bos"/> is 1, there is another MPLS label
+	  following this one, so the Ethertype passed to <code>pop_mpls</code>
+	  should be an MPLS Ethertype.  For example: <code>table=0,
+	  dl_type=0x8847, mpls_bos=1, actions=pop_mpls:0x8847,
+	  goto_table:1</code>
+	</li>
+
+	<li>
+	  When <ref field="mpls_bos"/> is 0, this MPLS label is the last one,
+	  so the Ethertype passed to <code>pop_mpls</code> should be a non-MPLS
+	  Ethertype such as IPv4.  For example: <code>table=1, dl_type=0x8847,
+	  mpls_bos=0, actions=pop_mpls:0x0800, goto_table:2</code>
+	</li>
+      </ul>
+    </field>
+
+    <field id="MFF_MPLS_TTL" title="MPLS Time-to-Live">
+      <p>
+        Holds the 8-bit time-to-live field from the MPLS label:
+      </p>
+
+      <diagram>
+	<header name="NXM_NX_MPLS_TTL">
+	  <bits name="TTL" above="8" width=".4"/>
+	</header>
+      </diagram>
+    </field>
+  </group>
+
+  <group title="Layer 3: IPv4 and IPv6">
+    <h2>IPv4 Specific Fields</h2>
+
+    <p>
+      These fields are applicable only to IPv4 flows, that is, flows that match
+      on the IPv4 Ethertype <code>0x0800</code>.
+    </p>
+
+    <field id="MFF_IPV4_SRC" title="IPv4 Source Address">
+      <p>
+        The source address from the IPv4 header:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x800" width="0.4"/>
+	</header>
+	<header name="IPv4">
+	  <bits name="..." width="0.4"/>
+	  <bits name="proto" above="8" width="0.4"/>
+	  <bits name="src" above="32" width="0.4" fill="yes"/>
+	  <bits name="dst" above="32" width="0.4"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+        For historical reasons, in an ARP or RARP flow, Open vSwitch interprets
+        matches on <code>nw_src</code> as actually referring to the ARP SPA.
+      </p>
+    </field>
+
+    <field id="MFF_IPV4_DST" title="IPv4 Destination Address">
+      <p>
+      The destination address from the IPv4 header:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x800" width="0.4"/>
+	</header>
+	<header name="IPv4">
+	  <bits name="..." width="0.4"/>
+	  <bits name="proto" above="8" width="0.4"/>
+	  <bits name="src" above="32" width="0.4"/>
+	  <bits name="dst" above="32" width="0.4" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+        For historical reasons, in an ARP or RARP flow, Open vSwitch interprets
+        matches on <code>nw_dst</code> as actually referring to the ARP TPA.
+      </p>
+    </field>
+
+    <h2>IPv6 Specific Fields</h2>
+
+    <p>
+      These fields apply only to IPv6 flows, that is, flows that match
+      on the IPv6 Ethertype <code>0x86dd</code>.
+    </p>
+
+    <field id="MFF_IPV6_SRC" title="IPv6 Source Address">
+      <p>
+        The source address from the IPv6 header:
+      </p>
+
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x86dd" width="0.4"/>
+	</header>
+	<header name="IPv6">
+	  <bits name="..." width="0.4"/>
+	  <bits name="next" above="8" width="0.3"/>
+	  <bits name="src" above="128" width="0.8" fill="yes"/>
+	  <bits name="dst" above="128" width="0.8"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+        Open vSwitch 1.8 added support for bitwise matching; earlier versions
+        supported only CIDR masks.
+      </p>
+    </field>
+    <field id="MFF_IPV6_DST" title="IPv6 Destination Address">
+      <p>
+        The destination address from the IPv6 header:
+      </p>
+      <diagram>
+	<header name="Ethernet">
+	  <bits name="dst" above="48" width="0.4"/>
+	  <bits name="src" above="48" width="0.4"/>
+	  <bits name="type" above="16" below="0x86dd" width="0.4"/>
+	</header>
+	<header name="IPv6">
+	  <bits name="..." width="0.4"/>
+	  <bits name="next" above="8" width="0.3"/>
+	  <bits name="src" above="128" width="0.8"/>
+	  <bits name="dst" above="128" width="0.8" fill="yes"/>
+	</header>
+	<dots/>
+      </diagram>
+
+      <p>
+        Open vSwitch 1.8 added support for bitwise matching; earlier versions
+        supported only CIDR masks.
+      </p>
+    </field>
+    <field id="MFF_IPV6_LABEL" title="IPv6 Flow Label">
+      <p>
+	The least significant 20 bits hold the flow label field from
+	the IPv6 header.  Other bits are zero:
+      </p>
+
+      <diagram>
+	<header name="OXM_OF_IPV6_FLABEL">
+	  <bits name="zero" above="12" below="0" width=".6"/>
+	  <bits name="label" above="20" width="1.0"/>
+	</header>
+      </diagram>
+    </field>
+
+    <h2>IPv4/IPv6 Fields</h2>
+
+    <p>
+      These fields exist with at least approximately the same meaning in both
+      IPv4 and IPv6, so they are treated as a single field for matching
+      purposes.  Any flow that matches on the IPv4 Ethertype
+      <code>0x0800</code> or the IPv6 Ethertype <code>0x86dd</code> may match
+      on these fields.
+    </p>
+
+    <field id="MFF_IP_PROTO" title="IPv4/v6 Protocol">
+      Matches the IPv4 or IPv6 protocol type.
+
+      <p>
+        For historical reasons, in an ARP or RARP flow, Open vSwitch interprets
+        matches on <code>nw_proto</code> as actually referring to the ARP
+        opcode.  The ARP opcode is a 16-bit field, so for matching purposes ARP
+        opcodes greater than 255 are treated as 0; this works adequately
+        because in practice ARP and RARP only use opcodes 1 through 4.
+      </p>
+    </field>
+
+    <field id="MFF_IP_TTL" title="IPv4/v6 TTL/Hop Limit"/>
+    <field id="MFF_IP_FRAG" title="IPv4/v6 Fragment Bitmask">
+      <p>
+        Specifies what kinds of IP fragments or non-fragments to match.  The
+        value for this field is most conveniently specified as one of the
+        following:
+      </p>
+
+      <dl>
+        <dt><code>no</code></dt>
+        <dd>
+          Match only non-fragmented packets.
+        </dd>
+
+        <dt><code>yes</code></dt>
+        <dd>
+          Matches all fragments.
+        </dd>
+
+        <dt><code>first</code></dt>
+        <dd>
+          Matches only fragments with offset 0.
+        </dd>
+
+        <dt><code>later</code></dt>
+        <dd>
+          Matches only fragments with nonzero offset.
+        </dd>
+
+        <dt><code>not_later</code></dt>
+        <dd>
+          Matches non-fragmented packets and fragments with zero offset.
+        </dd>
+      </dl>
+
+      <p>
+        The field is internally formatted as 2 bits: bit 0 is 1 for an IP
+        fragment with any offset (and otherwise 0), and bit 1 is 1 for an IP
+        fragment with nonzero offset (and otherwise 0), like so:
+      </p>
+
+      <diagram>
+	<header name="NXM_NX_IP_FRAG">
+	  <bits name="zero" above="6" below="0" width=".9"/>
+	  <bits name="later" above="1" width=".3"/>
+	  <bits name="any" above="1" width=".3"/>
+	</header>
+      </diagram>
+
+      <p>
+        Even though 2 bits have 4 possible values, this field only uses 3 of
+        them:
+      </p>
+
+      <ul>
+        <li>
+          A packet that is not an IP fragment has value 0.
+        </li>
+
+        <li>
+          A packet that is an IP fragment with offset 0 (the first fragment)
+          has bit 0 set and thus value 1.
+        </li>
+
+        <li>
+          A packet that is an IP fragment with nonzero offset has bits 0 and 1
+          set and thus value 3.
+        </li>
+      </ul>
+
+      <p>
+        The switch may reject matches against values that can never appear.
+      </p>
+
+      <p>
+        It is important to understand how this field interacts with the
+        OpenFlow fragment handling mode:
+      </p>
+
+      <ul>
+        <li>
+          In <code>OFPC_FRAG_DROP</code> mode, the OpenFlow switch drops all IP
+          fragments before they reach the flow table, so every packet that is
+          available for matching will have value 0 in this field.
+        </li>
+
+        <li>
+          Open vSwitch does not implement <code>OFPC_FRAG_REASM</code> mode,
+          but if it did then IP fragments would be reassembled before they
+          reached the flow table and again every packet available for matching
+          would always have value 0.
+        </li>
+
+        <li>
+          In <code>OFPC_FRAG_NORMAL</code> mode, all three values are possible,
+          but OpenFlow 1.0 says that fragments' transport ports are always 0,
+          even for the first fragment, so this does not provide much extra
+          information.
+        </li>
+
+        <li>
+          In <code>OFPC_FRAG_NX_MATCH</code> mode, all three values are
+          possible.  For fragments with offset 0, Open vSwitch makes L4 header
+          information available.
+        </li>
+      </ul>
+      
+      <p>
+        Thus, this field is likely to be most useful for an Open vSwitch switch
+        configured in <code>OFPC_FRAG_NX_MATCH</code> mode.  See the
+        description of the <code>set-frags</code> command in
+        <code>ovs-ofctl</code>(8), for more details.
+      </p>
+    </field>
+
+    <h3>IPv4/IPv6 TOS Fields</h3>
+
+    <field id="MFF_IP_DSCP" title="IPv4/v6 DSCP (Bits 2-7)">
+      <diagram>
+	<header name="NXM_OF_IP_TOS">
+	  <bits name="DSCP" above="6" width=".9"/>
+	  <bits name="zero" above="2" below="0" width=".3"/>
+	</header>
+      </diagram>
+    </field>
+    <field id="MFF_IP_DSCP_SHIFTED" title="IPv4/v6 DSCP (Bits 0-5)">
+      <diagram>
+	<header name="OXM_OF_IP_DSCP">
+	  <bits name="zero" above="2" below="0" width=".3"/>
+	  <bits name="DSCP" above="6" width=".9"/>
+	</header>
+      </diagram>
+    </field>
+    <field id="MFF_IP_ECN" title="IPv4/v6 ECN">
+      <diagram>
+	<header name="OXM_OF_IP_ECN">
+	  <bits name="zero" above="6" below="0" width=".9"/>
+	  <bits name="ECN" above="2" width=".35"/>
+	</header>
+      </diagram>
+    </field>
+
+  </group>
+
+  <group title="Layer 3: ARP">
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x806" width="0.4"/>
+      </header>
+      <header name="ARP">
+	<bits name="hrd" above="16" below="1" width=".3"/>
+	<bits name="pro" above="16" below="0x800" width=".3"/>
+	<bits name="hln" above="8" below="6" width=".2"/>
+	<bits name="pln" above="8" below="4" width=".2"/>
+	<bits name="op" above="16" width=".2"/>
+	<bits name="sha" above="48" width="0.5"/>
+	<bits name="spa" above="16" width="0.3"/>
+	<bits name="tha" above="48" width="0.5"/>
+	<bits name="tpa" above="16" width="0.3"/>
+      </header>
+    </diagram>
+    <field id="MFF_ARP_OP" title="ARP Opcode"/>
+    <field id="MFF_ARP_SPA" title="ARP Source IPv4 Address"/>
+    <field id="MFF_ARP_TPA" title="ARP Target IPv4 Address"/>
+    <field id="MFF_ARP_SHA" title="ARP Source Ethernet Address"/>
+    <field id="MFF_ARP_THA" title="ARP Target Ethernet Address"/>
+  </group>
+
+  <group title="Layer 4: TCP, UDP, and SCTP">
+    <p>
+      For matching purposes, no distinction is made whether these protocols are
+      encapsulated within IPv4 or IPv6.
+    </p>
+
+    <h2>TCP</h2>
+
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv4">
+	<bits name="..." width="0.4"/>
+	<bits name="proto" above="8" below="6" width="0.3"/>
+	<bits name="src" above="32" width="0.4"/>
+	<bits name="dst" above="32" width="0.4"/>
+      </header>
+      <header name="TCP">
+	<bits name="src" above="16" width=".2"/>
+	<bits name="dst" above="16" width=".2"/>
+	<bits name="..." width=".75"/>
+	<bits name="flags" above="12" width=".3"/>
+	<bits name="..." width=".6"/>
+      </header>
+      <dots/>
+    </diagram>
+    <field id="MFF_TCP_SRC" title="TCP Source Port">
+      Open vSwitch 1.6 added support for bitwise matching.
+    </field>
+    <field id="MFF_TCP_DST" title="TCP Destination Port">
+      Open vSwitch 1.6 added support for bitwise matching.
+    </field>
+    <field id="MFF_TCP_FLAGS" title="TCP Flags">
+      <p>
+        This field holds the TCP flags.  TCP currently defines 9 flag bits.  An
+        additional 3 bits are reserved.  For more information, see [RFC 793],
+        [RFC 3168], and [RFC 3540].
+      </p>
+
+      <p>
+        Matches on this field are most conveniently written in
+        terms of symbolic names (given in the diagram below), each preceded by
+        either <code>+</code> for a flag that must be set, or <code>-</code>
+        for a flag that must be unset, without any other delimiters between the
+        flags.  Flags not mentioned are wildcarded.  For example,
+        <code>tcp,tcp_flags=+syn-ack</code> matches TCP SYNs that are not ACKs.
+        Matches can also be written as
+        <code><var>flags</var>/<var>mask</var></code>, where <var>flags</var>
+        and <var>mask</var> are 16-bit numbers in decimal or in hexadecimal
+        prefixed by <code>0x</code>.
+      </p>
+
+      <p>
+        The flag bits are:
+      </p>
+
+      <diagram>
+	<header>
+	  <bits name="zero" above="4" below="0" width=".9"/>
+	</header>
+	<nospace/>
+	<header name="reserved">
+	  <bits name="800" above="1" width=".35"/>
+	  <bits name="400" above="1" width=".35"/>
+	  <bits name="200" above="1" width=".35"/>
+	</header>
+	<nospace/>
+	<header name="later RFCs">
+	  <bits name="NS" above="1" width=".35"/>
+	  <bits name="CWR" above="1" width=".35"/>
+	  <bits name="ECE" above="1" width=".35"/>
+	</header>
+	<nospace/>
+	<header name="RFC 793">
+	  <bits name="URG" above="1" width=".35"/>
+	  <bits name="ACK" above="1" width=".35"/>
+	  <bits name="PSH" above="1" width=".35"/>
+	  <bits name="RST" above="1" width=".35"/>
+	  <bits name="SYN" above="1" width=".35"/>
+	  <bits name="FIN" above="1" width=".35"/>
+	</header>
+      </diagram>
+    </field>
+
+    <h2>UDP</h2>
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv4">
+	<bits name="..." width="0.4"/>
+	<bits name="proto" above="8" below="17" width="0.3"/>
+	<bits name="src" above="32" width="0.4"/>
+	<bits name="dst" above="32" width="0.4"/>
+      </header>
+      <header name="UDP">
+	<bits name="src" above="16" width=".2"/>
+	<bits name="dst" above="16" width=".2"/>
+	<bits name="..." width=".4"/>
+      </header>
+      <dots/>
+    </diagram>
+    <field id="MFF_UDP_SRC" title="UDP Source Port"/>
+    <field id="MFF_UDP_DST" title="UDP Destination Port"/>
+
+    <h2>SCTP</h2>
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv4">
+	<bits name="..." width="0.4"/>
+	<bits name="proto" above="8" below="17" width="0.3"/>
+	<bits name="src" above="32" width="0.4"/>
+	<bits name="dst" above="32" width="0.4"/>
+      </header>
+      <header name="SCTP">
+	<bits name="src" above="16" width=".2"/>
+	<bits name="dst" above="16" width=".2"/>
+	<bits name="..." width=".8"/>
+      </header>
+      <dots/>
+    </diagram>
+    <field id="MFF_SCTP_SRC" title="SCTP Source Port"/>
+    <field id="MFF_SCTP_DST" title="SCTP Destination Port"/>
+  </group>
+
+  <group title="Layer 4: ICMPv4 and ICMPv6">
+    <h2>ICMPv4</h2>
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv4">
+	<bits name="..." width="0.4"/>
+	<bits name="proto" above="8" below="1" width="0.3"/>
+	<bits name="src" above="32" width="0.4"/>
+	<bits name="dst" above="32" width="0.4"/>
+      </header>
+      <header name="ICMPv4">
+	<bits name="type" above="8" width=".3"/>
+	<bits name="code" above="8" width=".3"/>
+	<bits name="..." width=".8"/>
+      </header>
+      <dots/>
+    </diagram>
+    <field id="MFF_ICMPV4_TYPE" title="ICMPv4 Type"/>
+    <field id="MFF_ICMPV4_CODE" title="ICMPv4 Code"/>
+
+    <h2>ICMPv6</h2>
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv6">
+	<bits name="..." width="0.2"/>
+	<bits name="next" above="8" below="58" width="0.3"/>
+	<bits name="src" above="128" width="0.4"/>
+	<bits name="dst" above="128" width="0.4"/>
+      </header>
+      <header name="ICMPv6">
+	<bits name="type" above="8" width=".3"/>
+	<bits name="code" above="8" width=".3"/>
+	<bits name="..." width=".8"/>
+      </header>
+      <dots/>
+    </diagram>
+    <field id="MFF_ICMPV6_TYPE" title="ICMPv6 Type"/>
+    <field id="MFF_ICMPV6_CODE" title="ICMPv6 Code"/>
+
+    <h2>ICMPv6 Neighbor Discovery</h2>
+    <diagram>
+      <header name="Ethernet">
+	<bits name="dst" above="48" width="0.4"/>
+	<bits name="src" above="48" width="0.4"/>
+	<bits name="type" above="16" below="0x800" width="0.4"/>
+      </header>
+      <header name="IPv6">
+	<bits name="..." width="0.2"/>
+	<bits name="next" above="8" below="58" width="0.3"/>
+	<bits name="src" above="128" width="0.4"/>
+	<bits name="dst" above="128" width="0.4"/>
+      </header>
+      <header name="ICMPv6">
+	<bits name="type" above="8" below="135/136" width=".3"/>
+	<bits name="code" above="8" below="0" width=".3"/>
+	<bits name="..." width=".8"/>
+      </header>
+      <header name="ICMPv6 ND">
+	<bits name="target" above="128" width=".4"/>
+	<bits name="option ..." width=".6"/>
+      </header>
+    </diagram>
+    <field id="MFF_ND_TARGET" title="ICMPv6 Neighbor Discovery Target IPv6"/>
+    <field id="MFF_ND_SLL"
+	   title="ICMPv6 Neighbor Discovery Source Ethernet Address"/>
+    <field id="MFF_ND_TLL"
+	   title="ICMPv6 Neighbor Discovery Target Ethernet Address"/>
+  </group>
+
+  <h1>References</h1>
+
+  <dl>
+    <dt>Casado</dt>
+    <dd>
+      M. Casado, M. J. Freedman, J. Pettit, J. Luo, N. McKeown, and
+      S. Shenker, ``Ethane: Taking Control of the Enterprise,''
+      Computer Communications Review, October 2007.
+    </dd>
+
+    <dt>EXT-56</dt>
+    <dd>
+      J. Tonsing, ``Permit one of a set of prerequisites to apply, e.g. don't
+      preclude non-Ethernet media,'' <url
+      href="https://rs.opennetworking.org/bugs/browse/EXT-56"/> (ONF
+      members only).
+    </dd>
+
+    <dt>EXT-112</dt>
+    <dd>
+      J. Tourrilhes, ``Support non-Ethernet packets throughout the
+      pipeline,'' <url
+      href="https://rs.opennetworking.org/bugs/browse/EXT-112"/> (ONF
+      members only).
+    </dd>
+
+    <dt>EXT-134</dt>
+    <dd>
+      J. Tourrilhes, ``Match first nibble of the MPLS payload,'' <url
+      href="https://rs.opennetworking.org/bugs/browse/EXT-134"/> (ONF
+      members only).
+    </dd>
+
+    <dt>IEEE OUI</dt>
+    <dd>
+      IEEE Standards Association, ``MAC Address Block Large (MA-L),''
+      <url
+      href="https://standards.ieee.org/develop/regauth/oui/index.html"/>.
+    </dd>
+
+    <dt>OpenFlow 1.0.1</dt>
+    <dd>
+      Open Networking Foundation, ``OpenFlow Switch Errata, Version
+      1.0.1,'' June 2012.
+    </dd>
+
+    <dt>OpenFlow 1.1</dt>
+    <dd>
+      OpenFlow Consortium, ``OpenFlow Switch Specification Version
+      1.1.0 Implemented (Wire Protocol 0x02),'' February 2011.
+    </dd>
+
+    <dt>OpenFlow 1.5</dt>
+    <dd>
+      Open Networking Foundation, ``OpenFlow Switch Specification Version
+      1.5.0 (Protocol version 0x06),'' December 2014.
+    </dd>
+
+    <dt>OpenFlow Extensions 1.3.x Package 2</dt>
+    <dd>
+      Open Networking Foundation, ``OpenFlow Extensions 1.3.x Package 2,''
+      December 2013.
+    </dd>
+
+    <dt>TCP Flags Match Field Extension</dt>
+    <dd>
+      Open Networking Foundation, ``TCP flags match field Extension,'' December
+      2014.  In [OpenFlow Extensions 1.3.x Package 2].
+    </dd>
+
+    <dt>Pepelnjak</dt>
+    <dd>
+      I. Pepelnjak, ``OpenFlow and Fermi Estimates,'' <url
+      href="http://blog.ipspace.net/2013/09/openflow-and-fermi-estimates.html"/>.
+    </dd>
+
+    <dt>RFC 793</dt>
+    <dd>
+      ``Transmission Control Protocol,'' <url
+      href="http://www.ietf.org/rfc/rfc793.txt"/>.
+    </dd>
+
+    <dt>RFC 3032</dt>
+    <dd>
+       E. Rosen, D. Tappan, G. Fedorkow, Y. Rekhter, D. Farinacci,
+       T. Li, and A. Conta, ``MPLS Label Stack Encoding,'' <url
+       href="http://www.ietf.org/rfc/rfc3032.txt"/>.
+    </dd>
+
+    <dt>RFC 3168</dt>
+    <dd>
+      K. Ramakrishnan, S. Floyd, and D. Black, ``The Addition of Explicit
+      Congestion Notification (ECN) to IP,'' <url href="https://tools.ietf.org/html/rfc3168"/>.
+    </dd>
+
+    <dt>RFC 3540</dt>
+    <dd>
+      N. Spring, D. Wetherall, and D. Ely, ``Robust Explicit Congestion
+      Notification (ECN) Signaling with Nonces,'' <url
+      href="https://tools.ietf.org/html/rfc3540"/>.
+    </dd>
+
+    <dt>RFC 4632</dt>
+    <dd>
+      V. Fuller and T. Li, ``Classless Inter-domain Routing (CIDR): The
+      Internet Address Assignment and Aggregation Plan,'' <url
+      href="https://tools.ietf.org/html/rfc4632"/>.
+    </dd>
+
+    <dt>RFC 5462</dt>
+    <dd>
+      L. Andersson and R. Asati, ``Multiprotocol Label Switching
+      (MPLS) Label Stack Entry: ``EXP'' Field Renamed to ``Traffic
+      Class'' Field,'' <url
+      href="http://www.ietf.org/rfc/rfc5462.txt"/>.
+    </dd>
+
+    <dt>RFC 6830</dt>
+    <dd>
+      D. Farinacci, V. Fuller, D. Meyer, and D. Lewis, ``The
+      Locator/ID Separation Protocol (LISP),'' <url
+      href="http://www.ietf.org/rfc/rfc6830.txt"/>.
+    </dd>
+
+    <dt>Srinivasan</dt>
+    <dd>
+      V. Srinivasan, S. Suriy, and G. Varghese, ``Packet
+      Classification using Tuple Space Search,'' SIGCOMM 1999.
+    </dd>
+
+    <dt>Pagiamtzis</dt>
+    <dd>
+      K. Pagiamtzis and A. Sheikholeslami, ``Content-addressable
+      memory (CAM) circuits and architectures: A tutorial and
+      survey,'' IEEE Journal of Solid-State Circuits, vol. 41, no. 3,
+      pp. 712-727, March 2006.
+    </dd>
+
+    <dt>VXLAN Group Policy Option</dt>
+    <dd>
+      M. Smith and L. Kreeger, `` VXLAN Group Policy Option.'' Internet-Draft.
+      <url href="https://tools.ietf.org/html/draft-smith-vxlan-group-policy"/>.
+    </dd>
+  </dl>
+
+  <h1>Authors</h1>
+
+  <p>
+    Ben Pfaff, with advice from Justin Pettit and Jean Tourrilhes.
+  </p>
+
+</fields>
+
+<!--
+    OXM fields not yet supported Future Directions References/See Also
+    OXM fields required by various versions and by the "Conformance Test Specification for OpenFlow Switch Specification 1.0.1"
+-->
diff --git a/ovn/ovn-architecture.7.xml b/ovn/ovn-architecture.7.xml
index b049e51..35b1265 100644
--- a/ovn/ovn-architecture.7.xml
+++ b/ovn/ovn-architecture.7.xml
@@ -857,7 +857,7 @@ 
 
       <p>
         Some logical flows can map to the Open vSwitch ``conjunctive match''
-        extension (see <code>ovs-ofctl</code>(8)).  Flows with a
+        extension (see <code>ovs-fields</code>(7)).  Flows with a
         <code>conjunction</code> action use an OpenFlow cookie of 0, because
         they can correspond to multiple logical flows.  The OpenFlow flow for a
         conjunctive match includes a match on <code>conj_id</code>.
diff --git a/ovn/utilities/ovn-trace.8.xml b/ovn/utilities/ovn-trace.8.xml
index 5d41f46..7891424 100644
--- a/ovn/utilities/ovn-trace.8.xml
+++ b/ovn/utilities/ovn-trace.8.xml
@@ -284,7 +284,7 @@ 
 
         <li>
           Some logical flows can map to the Open vSwitch ``conjunctive match''
-          extension (see <code>ovs-ofctl</code>(8)).  Currently
+          extension (see <code>ovs-fields</code>(7)).  Currently
           <code>ovn-trace</code> cannot display the flows with
           <code>conjunction</code> actions that effectively produce the
           <code>conj_id</code> match.
diff --git a/python/build/nroff.py b/python/build/nroff.py
index dd5f223..a04e9b3 100644
--- a/python/build/nroff.py
+++ b/python/build/nroff.py
@@ -1,4 +1,4 @@ 
-# Copyright (c) 2010, 2011, 2012, 2015 Nicira, Inc.
+# Copyright (c) 2010, 2011, 2012, 2015, 2016 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@  import sys
 from ovs.db import error
 
 
-def text_to_nroff(s, font=r'\fR'):
+def text_to_nroff(s, font=r'\fR', escape_dot=True):
     def escape(match):
         c = match.group(0)
 
@@ -47,9 +47,13 @@  def text_to_nroff(s, font=r'\fR'):
         elif c == "'":
             return r'\(cq'
         elif c == ".":
-            # groff(7) says that . can be escaped by \. but in practice groff
-            # still gives an error with \. at the beginning of a line.
-            return r'\[char46]'
+            if escape_dot:
+                # groff(7) says that . can be escaped by \. but in practice
+                # groff still gives an error with \. at the beginning of a
+                # line.
+                return r'\[char46]'
+            else:
+                return '.'
         else:
             raise error.Error("bad escape")
 
@@ -87,15 +91,27 @@  def inline_xml_to_nroff(node, font, to_upper=False, newline='\n'):
                 s += node.attributes['group'].nodeValue
             elif node.hasAttribute('db'):
                 s += node.attributes['db'].nodeValue
+            elif node.hasAttribute('field'):
+                s += node.attributes['field'].nodeValue
             else:
                 raise error.Error("'ref' lacks required attributes: %s"
                                   % list(node.attributes.keys()))
             return s + font
-        elif node.tagName in ['var', 'dfn', 'i']:
+        elif node.tagName in ['var', 'dfn', 'i', 'cite']:
             s = r'\fI'
             for child in node.childNodes:
                 s += inline_xml_to_nroff(child, r'\fI', to_upper, newline)
             return s + font
+        elif node.tagName in ['literal']:
+            s = r'\fL'
+            for child in node.childNodes:
+                s += inline_xml_to_nroff(child, r'\fL')
+            return s + font
+        elif node.tagName == 'url':
+            return ('\n.URL "'
+                    + text_to_nroff(node.attributes['href'].nodeValue,
+                                    escape_dot=False)
+                    + '"\n')
         else:
             raise error.Error("element <%s> unknown or invalid here"
                               % node.tagName)
@@ -116,6 +132,16 @@  def pre_to_nroff(nodes, para, font):
     return s
 
 
+def tbl_to_nroff(nodes, para):
+    s = para + '\n.TS\n'
+    for node in nodes:
+        if node.nodeType != node.TEXT_NODE:
+            fatal("<tbl> element may only have text children")
+        s += node.data + '\n'
+    s += '.TE\n'
+    return s
+
+
 def fatal(msg):
     sys.stderr.write('%s\n' % msg)
     sys.exit(1)
@@ -265,7 +291,12 @@  def block_xml_to_nroff(nodes, para='.PP'):
     s = ''
     for node in nodes:
         if node.nodeType == node.TEXT_NODE:
-            s += text_to_nroff(node.data)
+            if s == '' and para != '.IP':
+                s = para + '\n'
+            text = re.sub(r'\s+', ' ', node.data)
+            if s.endswith(' '):
+                text = text.lstrip()
+            s += text_to_nroff(text)
             s = s.lstrip()
         elif node.nodeType == node.ELEMENT_NODE:
             if node.tagName in ['ul', 'ol']:
@@ -321,16 +352,19 @@  def block_xml_to_nroff(nodes, para='.PP'):
                         s += "\n"
                     s += para + "\n"
                 s += block_xml_to_nroff(node.childNodes, para)
-            elif node.tagName in ('h1', 'h2', 'h3'):
+            elif node.tagName in ('h1', 'h2', 'h3', 'h4'):
                 if s != "":
                     if not s.endswith("\n"):
                         s += "\n"
-                nroffTag = {'h1': 'SH', 'h2': 'SS', 'h3': 'ST'}[node.tagName]
-                s += '.%s "' % nroffTag
+                nroffTag = {'h1': 'SH',
+                            'h2': 'SS',
+                            'h3': 'ST',
+                            'h4': 'SU'}[node.tagName]
+                to_upper = node.tagName == 'h1'
+                s += ".%s \"" % nroffTag
                 for child_node in node.childNodes:
-                    s += inline_xml_to_nroff(child_node, r'\fR',
-                                          to_upper=(nroffTag == 'SH'))
-                s += '"\n'
+                    s += inline_xml_to_nroff(child_node, r'\fR', to_upper)
+                s += "\"\n"
             elif node.tagName == 'pre':
                 fixed = node.getAttribute('fixed')
                 if fixed == 'yes':
@@ -338,6 +372,8 @@  def block_xml_to_nroff(nodes, para='.PP'):
                 else:
                     font = r'\fB'
                 s += pre_to_nroff(node.childNodes, para, font)
+            elif node.tagName == 'tbl':
+                s += tbl_to_nroff(node.childNodes, para)
             elif node.tagName == 'diagram':
                 s += diagram_to_nroff(node.childNodes, para)
             else:
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index af1eb2b..a3a29b1 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -672,7 +672,7 @@  understand IPv6.
 .SS "Flow Syntax"
 .PP
 Some \fBovs\-ofctl\fR commands accept an argument that describes a flow or
-flows.  Such flow descriptions comprise a series
+flows.  Such flow descriptions comprise a series of
 \fIfield\fB=\fIvalue\fR assignments, separated by commas or white
 space.  (Embedding spaces into a flow description normally requires
 quoting to prevent the shell from breaking the description into
@@ -689,287 +689,9 @@  protocol type) is wildcarded, so must be the L4 fields \fBtcp_dst\fR and
 \fBtcp_src\fR.  \fBovs\-ofctl\fR will warn about
 flows not in normal form.
 .PP
-The following field assignments describe how a flow matches a packet.
-If any of these assignments is omitted from the flow syntax, the field
-is treated as a wildcard; thus, if all of them are omitted, the
-resulting flow matches all packets.  The string \fB*\fR may be specified
-to explicitly mark any of these fields as a wildcard.
-(\fB*\fR should be quoted to protect it from shell expansion.)
-.
-.IP \fBin_port=\fIport\fR
-Matches OpenFlow port \fIport\fR, which may be an OpenFlow port number
-or keyword (e.g. \fBLOCAL\fR).
-\fBovs\-ofctl show\fR.
-.IP
-(The \fBresubmit\fR action can search OpenFlow flow tables with
-arbitrary \fBin_port\fR values, so flows that match port numbers that
-do not exist from an OpenFlow perspective can still potentially be
-matched.)
-.
-.IP \fBdl_vlan=\fIvlan\fR
-Matches IEEE 802.1q Virtual LAN tag \fIvlan\fR.  Specify \fB0xffff\fR
-as \fIvlan\fR to match packets that are not tagged with a Virtual LAN;
-otherwise, specify a number between 0 and 4095, inclusive, as the
-12-bit VLAN ID to match.
-.
-.IP \fBdl_vlan_pcp=\fIpriority\fR
-Matches IEEE 802.1q Priority Code Point (PCP) \fIpriority\fR, which is
-specified as a value between 0 and 7, inclusive.  A higher value
-indicates a higher frame priority level.
-.
-.IP \fBdl_src=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-.IQ \fBdl_dst=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-Matches an Ethernet source (or destination) address specified as 6
-pairs of hexadecimal digits delimited by colons
-(e.g. \fB00:0A:E4:25:6B:B0\fR).
-.
-.IP \fBdl_src=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB/\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-.IQ \fBdl_dst=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB/\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-Matches an Ethernet destination address specified as 6 pairs of
-hexadecimal digits delimited by colons (e.g. \fB00:0A:E4:25:6B:B0\fR),
-with a wildcard mask following the slash. Open vSwitch 1.8 and later
-support arbitrary masks for source and/or destination. Earlier
-versions only support masking the destination with the following masks:
-.RS
-.IP \fB01:00:00:00:00:00\fR
-Match only the multicast bit.  Thus,
-\fBdl_dst=01:00:00:00:00:00/01:00:00:00:00:00\fR matches all multicast
-(including broadcast) Ethernet packets, and
-\fBdl_dst=00:00:00:00:00:00/01:00:00:00:00:00\fR matches all unicast
-Ethernet packets.
-.IP \fBfe:ff:ff:ff:ff:ff\fR
-Match all bits except the multicast bit.  This is probably not useful.
-.IP \fBff:ff:ff:ff:ff:ff\fR
-Exact match (equivalent to omitting the mask).
-.IP \fB00:00:00:00:00:00\fR
-Wildcard all bits (equivalent to \fBdl_dst=*\fR.)
-.RE
-.
-.IP \fBdl_type=\fIethertype\fR
-Matches Ethernet protocol type \fIethertype\fR, which is specified as an
-integer between 0 and 65535, inclusive, either in decimal or as a 
-hexadecimal number prefixed by \fB0x\fR (e.g. \fB0x0806\fR to match ARP 
-packets).
-.
-.IP \fBnw_src=\fIip\fR[\fB/\fInetmask\fR]
-.IQ \fBnw_dst=\fIip\fR[\fB/\fInetmask\fR]
-When \fBdl_type\fR is 0x0800 (possibly via shorthand, e.g. \fBip\fR
-or \fBtcp\fR), matches IPv4 source (or destination) address \fIip\fR,
-which may be specified as an IP address or host name
-(e.g. \fB192.168.1.1\fR or \fBwww.example.com\fR).  The optional
-\fInetmask\fR allows restricting a match to an IPv4 address prefix.
-The netmask may be specified as a dotted quad
-(e.g. \fB192.168.1.0/255.255.255.0\fR) or as a CIDR block
-(e.g. \fB192.168.1.0/24\fR).  Open vSwitch 1.8 and later support
-arbitrary dotted quad masks; earlier versions support only CIDR masks,
-that is, the dotted quads that are equivalent to some CIDR block.
-.IP
-When \fBdl_type=0x0806\fR or \fBarp\fR is specified, matches the
-\fBar_spa\fR or \fBar_tpa\fR field, respectively, in ARP packets for
-IPv4 and Ethernet.
-.IP
-When \fBdl_type=0x8035\fR or \fBrarp\fR is specified, matches the
-\fBar_spa\fR or \fBar_tpa\fR field, respectively, in RARP packets for
-IPv4 and Ethernet.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800,
-0x0806, or 0x8035, the values of \fBnw_src\fR and \fBnw_dst\fR are ignored
-(see \fBFlow Syntax\fR above).
-.
-.IP \fBnw_proto=\fIproto\fR
-.IQ \fBip_proto=\fIproto\fR
-When \fBip\fR or \fBdl_type=0x0800\fR is specified, matches IP
-protocol type \fIproto\fR, which is specified as a decimal number
-between 0 and 255, inclusive (e.g. 1 to match ICMP packets or 6 to match
-TCP packets).
-.IP
-When \fBipv6\fR or \fBdl_type=0x86dd\fR is specified, matches IPv6
-header type \fIproto\fR, which is specified as a decimal number between
-0 and 255, inclusive (e.g. 58 to match ICMPv6 packets or 6 to match
-TCP).  The header type is the terminal header as described in the
-\fBtopics/design\fR document.
-.IP
-When \fBarp\fR or \fBdl_type=0x0806\fR is specified, matches the lower
-8 bits of the ARP opcode.  ARP opcodes greater than 255 are treated as
-0.
-.IP
-When \fBrarp\fR or \fBdl_type=0x8035\fR is specified, matches the lower
-8 bits of the ARP opcode.  ARP opcodes greater than 255 are treated as
-0.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800,
-0x0806, 0x8035 or 0x86dd, the value of \fBnw_proto\fR is ignored (see
-\fBFlow Syntax\fR above).
-.
-.IP \fBnw_tos=\fItos\fR
-Matches IP ToS/DSCP or IPv6 traffic class field \fItos\fR, which is
-specified as a decimal number between 0 and 255, inclusive.  Note that
-the two lower reserved bits are ignored for matching purposes.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800 or
-0x86dd, the value of \fBnw_tos\fR is ignored (see \fBFlow Syntax\fR
-above).
-.
-.IP \fBip_dscp=\fIdscp\fR
-Matches IP ToS/DSCP or IPv6 traffic class field \fIdscp\fR, which is
-specified as a decimal number between 0 and 63, inclusive.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800 or
-0x86dd, the value of \fBip_dscp\fR is ignored (see \fBFlow Syntax\fR
-above).
-.
-.IP \fBnw_ecn=\fIecn\fR
-.IQ \fBip_ecn=\fIecn\fR
-Matches \fIecn\fR bits in IP ToS or IPv6 traffic class fields, which is
-specified as a decimal number between 0 and 3, inclusive.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800 or
-0x86dd, the value of \fBnw_ecn\fR is ignored (see \fBFlow Syntax\fR
-above).
-.
-.IP \fBnw_ttl=\fIttl\fR
-Matches IP TTL or IPv6 hop limit value \fIttl\fR, which is
-specified as a decimal number between 0 and 255, inclusive.
-.IP
-When \fBdl_type\fR is wildcarded or set to a value other than 0x0800 or
-0x86dd, the value of \fBnw_ttl\fR is ignored (see \fBFlow Syntax\fR
-above).
-.IP
-.
-.IP \fBtcp_src=\fIport\fR
-.IQ \fBtcp_dst=\fIport\fR
-.IQ \fBudp_src=\fIport\fR
-.IQ \fBudp_dst=\fIport\fR
-.IQ \fBsctp_src=\fIport\fR
-.IQ \fBsctp_dst=\fIport\fR
-Matches a TCP, UDP, or SCTP source or destination port \fIport\fR,
-which is specified as a decimal number between 0 and 65535, inclusive.
-.IP
-When \fBdl_type\fR and \fBnw_proto\fR are wildcarded or set to values
-that do not indicate an appropriate protocol, the values of these
-settings are ignored (see \fBFlow Syntax\fR above).
-.
-.IP \fBtcp_src=\fIport\fB/\fImask\fR
-.IQ \fBtcp_dst=\fIport\fB/\fImask\fR
-.IQ \fBudp_src=\fIport\fB/\fImask\fR
-.IQ \fBudp_dst=\fIport\fB/\fImask\fR
-.IQ \fBsctp_src=\fIport\fB/\fImask\fR
-.IQ \fBsctp_dst=\fIport\fB/\fImask\fR
-Bitwise match on TCP (or UDP or SCTP) source or destination port.
-The \fIport\fR and \fImask\fR are 16-bit numbers
-written in decimal or in hexadecimal prefixed by \fB0x\fR.  Each 1-bit
-in \fImask\fR requires that the corresponding bit in \fIport\fR must
-match.  Each 0-bit in \fImask\fR causes the corresponding bit to be
-ignored.
-.IP
-Bitwise matches on transport ports are rarely useful in isolation, but
-a group of them can be used to reduce the number of flows required to
-match on a range of transport ports.  For example, suppose that the
-goal is to match TCP source ports 1000 to 1999, inclusive.  One way is
-to insert 1000 flows, each of which matches on a single source port.
-Another way is to look at the binary representations of 1000 and 1999,
-as follows:
-.br
-.B "01111101000"
-.br
-.B "11111001111"
-.br
-and then to transform those into a series of bitwise matches that
-accomplish the same results:
-.br
-.B "01111101xxx"
-.br
-.B "0111111xxxx"
-.br
-.B "10xxxxxxxxx"
-.br
-.B "110xxxxxxxx"
-.br
-.B "1110xxxxxxx"
-.br
-.B "11110xxxxxx"
-.br
-.B "1111100xxxx"
-.br
-which become the following when written in the syntax required by
-\fBovs\-ofctl\fR:
-.br
-.B "tcp,tcp_src=0x03e8/0xfff8"
-.br
-.B "tcp,tcp_src=0x03f0/0xfff0"
-.br
-.B "tcp,tcp_src=0x0400/0xfe00"
-.br
-.B "tcp,tcp_src=0x0600/0xff00"
-.br
-.B "tcp,tcp_src=0x0700/0xff80"
-.br
-.B "tcp,tcp_src=0x0780/0xffc0"
-.br
-.B "tcp,tcp_src=0x07c0/0xfff0"
-.IP
-Only Open vSwitch 1.6 and later supports bitwise matching on transport
-ports.
-.IP
-Like the exact-match forms described
-above, the bitwise match forms apply only when \fBdl_type\fR and
-\fBnw_proto\fR specify TCP or UDP or SCTP.
-.
-.IP \fBtp_src=\fIport\fR
-.IQ \fBtp_dst=\fIport\fR
-These are deprecated generic forms of L4 port matches.  In new code,
-please use the TCP-, UDP-, or SCTP-specific forms described above.
-.
-.IP \fBtcp_flags=\fIflags\fB/\fImask\fR
-.IQ \fBtcp_flags=\fR[\fB+\fIflag\fR...][\fB-\fIflag\fR...]
-Bitwise match on TCP flags.  The \fIflags\fR and \fImask\fR are 16-bit
-numbers written in decimal or in hexadecimal prefixed by \fB0x\fR.
-Each 1-bit in \fImask\fR requires that the corresponding bit in
-\fIflags\fR must match.  Each 0-bit in \fImask\fR causes the corresponding
-bit to be ignored.
-.IP
-Alternatively, the flags can be specified by their symbolic names
-(listed below), each preceded by either \fB+\fR for a flag that must
-be set, or \fB\-\fR for a flag that must be unset, without any other
-delimiters between the flags.  Flags not mentioned are wildcarded.
-For example, \fBtcp,tcp_flags=+syn\-ack\fR matches TCP SYNs that are
-not ACKs.
-.IP
-TCP protocol currently defines 9 flag bits, and additional 3 bits are
-reserved (must be transmitted as zero), see RFCs 793, 3168, and 3540.
-The flag bits are, numbering from the least significant bit:
-.RS
-.IP "\fB0: fin\fR"
-No more data from sender.
-.IP "\fB1: syn\fR"
-Synchronize sequence numbers.
-.IP "\fB2: rst\fR"
-Reset the connection.
-.IP "\fB3: psh\fR"
-Push function.
-.IP "\fB4: ack\fR"
-Acknowledgement field significant.
-.IP "\fB5: urg\fR"
-Urgent pointer field significant.
-.IP "\fB6: ece\fR"
-ECN Echo.
-.IP "\fB7: cwr\fR"
-Congestion Windows Reduced.
-.IP "\fB8: ns\fR"
-Nonce Sum.
-.IP "\fB9-11:\fR"
-Reserved.
-.IP "\fB12-15:\fR"
-Not matchable, must be zero.
-.RE
-.IP \fBicmp_type=\fItype\fR
-.IQ \fBicmp_code=\fIcode\fR
-When \fBdl_type\fR and \fBnw_proto\fR specify ICMP or ICMPv6, \fItype\fR
-matches the ICMP type and \fIcode\fR matches the ICMP code.  Each is
-specified as a decimal number between 0 and 255, inclusive.
-.IP
-When \fBdl_type\fR and \fBnw_proto\fR take other values, the values of
-these settings are ignored (see \fBFlow Syntax\fR above).
+\fBovs\-fields\fR(7) describes the supported fields and how to match
+them.  In addition to match fields, commands that operate on flow
+accept a few addition key-value pairs:
 .
 .IP \fBtable=\fInumber\fR
 For flow dump commands, limits the flows dumped to those in the table
@@ -1026,505 +748,10 @@  OpenFlow 1.2 and later allow flow deletion commands, but not other
 flow table modification commands, to operate on all flow tables, with
 the behavior described above for OpenFlow 1.0.
 .RE
-.
-.IP \fBmetadata=\fIvalue\fR[\fB/\fImask\fR]
-Matches \fIvalue\fR either exactly or with optional \fImask\fR in the metadata
-field. \fIvalue\fR and \fImask\fR are 64-bit integers, by default in decimal
-(use a \fB0x\fR prefix to specify hexadecimal). Arbitrary \fImask\fR values
-are allowed: a 1-bit in \fImask\fR indicates that the corresponding bit in
-\fIvalue\fR must match exactly, and a 0-bit wildcards that bit. Matching on
-metadata was added in Open vSwitch 1.8.
-.
-.PP
-The following shorthand notations are also available:
-.
-.IP \fBip\fR
-Same as \fBdl_type=0x0800\fR.
-.
-.IP \fBipv6\fR
-Same as \fBdl_type=0x86dd\fR.
-.
-.IP \fBicmp\fR
-Same as \fBdl_type=0x0800,nw_proto=1\fR.
-.
-.IP \fBicmp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=58\fR.
-.
-.IP \fBtcp\fR
-Same as \fBdl_type=0x0800,nw_proto=6\fR.
-.
-.IP \fBtcp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=6\fR.
-.
-.IP \fBudp\fR
-Same as \fBdl_type=0x0800,nw_proto=17\fR.
-.
-.IP \fBudp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=17\fR.
-.
-.IP \fBsctp\fR
-Same as \fBdl_type=0x0800,nw_proto=132\fR.
-.
-.IP \fBsctp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=132\fR.
-.
-.IP \fBarp\fR
-Same as \fBdl_type=0x0806\fR.
-.
-.IP \fBrarp\fR
-Same as \fBdl_type=0x8035\fR.
-.
-.IP \fBmpls\fR
-Same as \fBdl_type=0x8847\fR.
-.
-.IP \fBmplsm\fR
-Same as \fBdl_type=0x8848\fR.
-.
-.PP
-The following field assignments require support for the NXM (Nicira
-Extended Match) extension to OpenFlow.  When one of these is specified,
-\fBovs\-ofctl\fR will automatically attempt to negotiate use of this
-extension.  If the switch does not support NXM, then \fBovs\-ofctl\fR
-will report a fatal error.
-.
-.IP \fBvlan_tci=\fItci\fR[\fB/\fImask\fR]
-Matches modified VLAN TCI \fItci\fR.  If \fImask\fR is omitted,
-\fItci\fR is the exact VLAN TCI to match; if \fImask\fR is specified,
-then a 1-bit in \fImask\fR indicates that the corresponding bit in
-\fItci\fR must match exactly, and a 0-bit wildcards that bit.  Both
-\fItci\fR and \fImask\fR are 16-bit values that are decimal by
-default; use a \fB0x\fR prefix to specify them in hexadecimal.
-.
-.IP
-The value that \fBvlan_tci\fR matches against is 0 for a packet that
-has no 802.1Q header.  Otherwise, it is the TCI value from the 802.1Q
-header with the CFI bit (with value \fB0x1000\fR) forced to 1.
-.IP
-Examples:
-.RS
-.IP \fBvlan_tci=0\fR
-Match packets without an 802.1Q header.
-.IP \fBvlan_tci=0x1000/0x1000\fR
-Match packets with an 802.1Q header, regardless of VLAN and priority
-values.
-.IP \fBvlan_tci=0xf123\fR
-Match packets tagged with priority 7 in VLAN 0x123.
-.IP \fBvlan_tci=0x1123/0x1fff\fR
-Match packets tagged with VLAN 0x123 (and any priority).
-.IP \fBvlan_tci=0x5000/0xf000\fR
-Match packets tagged with priority 2 (in any VLAN).
-.IP \fBvlan_tci=0/0xfff\fR
-Match packets with no 802.1Q header or tagged with VLAN 0 (and any
-priority).
-.IP \fBvlan_tci=0x5000/0xe000\fR
-Match packets with no 802.1Q header or tagged with priority 2 (in any
-VLAN).
-.IP \fBvlan_tci=0/0xefff\fR
-Match packets with no 802.1Q header or tagged with VLAN 0 and priority
-0.
-.RE
-.IP
-Some of these matching possibilities can also be achieved with
-\fBdl_vlan\fR and \fBdl_vlan_pcp\fR.
-.
-.IP \fBip_frag=\fIfrag_type\fR
-When \fBdl_type\fR specifies IP or IPv6, \fIfrag_type\fR
-specifies what kind of IP fragments or non-fragments to match.  The
-following values of \fIfrag_type\fR are supported:
-.RS
-.IP "\fBno\fR"
-Matches only non-fragmented packets.
-.IP "\fByes\fR"
-Matches all fragments.
-.IP "\fBfirst\fR"
-Matches only fragments with offset 0.
-.IP "\fBlater\fR"
-Matches only fragments with nonzero offset.
-.IP "\fBnot_later\fR"
-Matches non-fragmented packets and fragments with zero offset.
-.RE
-.IP
-The \fBip_frag\fR match type is likely to be most useful in
-\fBnx\-match\fR mode.  See the description of the \fBset\-frags\fR
-command, above, for more details.
-.
-.IP \fBarp_spa=\fIip\fR[\fB/\fInetmask\fR]
-.IQ \fBarp_tpa=\fIip\fR[\fB/\fInetmask\fR]
-When \fBdl_type\fR specifies either ARP or RARP, \fBarp_spa\fR and
-\fBarp_tpa\fR match the source and target IPv4 address, respectively.
-An address may be specified as an IP address or host name
-(e.g. \fB192.168.1.1\fR or \fBwww.example.com\fR).  The optional
-\fInetmask\fR allows restricting a match to an IPv4 address prefix.
-The netmask may be specified as a dotted quad
-(e.g. \fB192.168.1.0/255.255.255.0\fR) or as a CIDR block
-(e.g. \fB192.168.1.0/24\fR).
-.
-.IP \fBarp_sha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-.IQ \fBarp_tha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-When \fBdl_type\fR specifies either ARP or RARP, \fBarp_sha\fR and
-\fBarp_tha\fR match the source and target hardware address, respectively.  An
-address is specified as 6 pairs of hexadecimal digits delimited by colons
-(e.g. \fB00:0A:E4:25:6B:B0\fR).
-.
-.IP \fBarp_sha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB/\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-.IQ \fBarp_tha=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB/\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-When \fBdl_type\fR specifies either ARP or RARP, \fBarp_sha\fR and
-\fBarp_tha\fR match the source and target hardware address, respectively.  An
-address is specified as 6 pairs of hexadecimal digits delimited by colons
-(e.g. \fB00:0A:E4:25:6B:B0\fR), with a wildcard mask following the slash.
-.
-.IP \fBarp_op=\fIopcode\fR
-When \fBdl_type\fR specifies either ARP or RARP, \fBarp_op\fR matches the
-ARP opcode.  Only ARP opcodes between 1 and 255 should be specified for
-matching.
-.
-.IP \fBipv6_src=\fIipv6\fR[\fB/\fInetmask\fR]
-.IQ \fBipv6_dst=\fIipv6\fR[\fB/\fInetmask\fR]
-When \fBdl_type\fR is 0x86dd (possibly via shorthand, e.g., \fBipv6\fR
-or \fBtcp6\fR), matches IPv6 source (or destination) address \fIipv6\fR,
-which may be specified as defined in RFC 2373.  The preferred format is 
-\fIx\fB:\fIx\fB:\fIx\fB:\fIx\fB:\fIx\fB:\fIx\fB:\fIx\fB:\fIx\fR, where
-\fIx\fR are the hexadecimal values of the eight 16-bit pieces of the
-address.  A single instance of \fB::\fR may be used to indicate multiple
-groups of 16-bits of zeros.  The optional \fInetmask\fR allows
-restricting a match to an IPv6 address prefix.  A netmask is specified
-as an IPv6 address (e.g. \fB2001:db8:3c4d:1::/ffff:ffff:ffff:ffff::\fR)
-or a CIDR block (e.g. \fB2001:db8:3c4d:1::/64\fR).  Open vSwitch 1.8
-and later support arbitrary masks; earlier versions support only CIDR
-masks, that is, CIDR block and IPv6 addresses that are equivalent to
-CIDR blocks.
-.
-.IP \fBipv6_label=\fIlabel\fR
-When \fBdl_type\fR is 0x86dd (possibly via shorthand, e.g., \fBipv6\fR
-or \fBtcp6\fR), matches IPv6 flow label \fIlabel\fR.
-.
-.IP \fBnd_target=\fIipv6\fR[\fB/\fInetmask\fR]
-When \fBdl_type\fR, \fBnw_proto\fR, and \fBicmp_type\fR specify
-IPv6 Neighbor Discovery (ICMPv6 type 135 or 136), matches the target address
-\fIipv6\fR.  \fIipv6\fR is in the same format described earlier for the
-\fBipv6_src\fR and \fBipv6_dst\fR fields.
-.
-.IP \fBnd_sll=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-When \fBdl_type\fR, \fBnw_proto\fR, and \fBicmp_type\fR specify IPv6
-Neighbor Solicitation (ICMPv6 type 135), matches the source link\-layer
-address option.  An address is specified as 6 pairs of hexadecimal
-digits delimited by colons.
-.
-.IP \fBnd_tll=\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fB:\fIxx\fR
-When \fBdl_type\fR, \fBnw_proto\fR, and \fBicmp_type\fR specify IPv6
-Neighbor Advertisement (ICMPv6 type 136), matches the target link\-layer
-address option.  An address is specified as 6 pairs of hexadecimal
-digits delimited by colons.
-.
-.IP \fBmpls_bos=\fIbos\fR
-When \fBdl_type\fR is 0x8847 or 0x8848 (possibly via shorthand e.g.,
-\fBmpls\fR or \fBmplsm\fR), matches the bottom-of-stack bit of the
-outer-most MPLS label stack entry. Valid values are 0 and 1.
-.IP
-If 1 then for a packet with a well-formed MPLS label stack the
-bottom-of-stack bit indicates that the outer label stack entry is also
-the inner-most label stack entry and thus that is that there is only one
-label stack entry present.  Conversely, if 0 then for a packet with a
-well-formed MPLS label stack the bottom-of-stack bit indicates that the
-outer label stack entry is not the inner-most label stack entry and
-thus there is more than one label stack entry present.
-.
-.IP \fBmpls_label=\fIlabel\fR
-When \fBdl_type\fR is 0x8847 or 0x8848 (possibly via shorthand e.g.,
-\fBmpls\fR or \fBmplsm\fR), matches the label of the outer
-MPLS label stack entry. The label is a 20-bit value that is decimal by default;
-use a \fB0x\fR prefix to specify them in hexadecimal.
-.
-.IP \fBmpls_tc=\fItc\fR
-When \fBdl_type\fR is 0x8847 or 0x8848 (possibly via shorthand e.g.,
-\fBmpls\fR or \fBmplsm\fR), matches the traffic-class of the outer
-MPLS label stack entry. Valid values are between 0 (lowest) and 7 (highest).
-.
-.IP \fBtun_id=\fItunnel-id\fR[\fB/\fImask\fR]
-.IQ \fBtunnel_id=\fItunnel-id\fR[\fB/\fImask\fR]
-Matches tunnel identifier \fItunnel-id\fR.  Only packets that arrive
-over a tunnel that carries a key (e.g. GRE with the RFC 2890 key
-extension and a nonzero key value) will have a nonzero tunnel ID.
-If \fImask\fR is omitted, \fItunnel-id\fR is the exact tunnel ID to match;
-if \fImask\fR is specified, then a 1-bit in \fImask\fR indicates that the
-corresponding bit in \fItunnel-id\fR must match exactly, and a 0-bit
-wildcards that bit.
-.
-.IP \fBtun_flags=\fIflags\fR
-Matches flags indicating various aspects of the tunnel encapsulation. Currently,
-there is only one flag defined:
-.IP
-\fBoam\fR: The tunnel protocol indicated that this is an OAM control packet.
-.IP
-Flags can be prefixed by \fB+\fR or \fB-\fR to indicate that the flag should
-be matched as either present or not present, respectively. In addition, flags
-can be specified without a prefix and separated by \fB|\fR to indicate an exact
-match.
-.IP
-Note that it is possible for newer version of Open vSwitch to introduce
-additional flags with varying meaning. It is therefore not recommended to use
-an exact match on this field since the behavior of these new flags is unknown
-and should be ignored.
-.IP
-For non-tunneled packets, the value is 0.
-.IP
-This field was introduced in Open vSwitch 2.5.
-.
-.IP \fBtun_src=\fIipv4\fR[\fB/\fInetmask\fR]
-.IQ \fBtun_dst=\fIipv4\fR[\fB/\fInetmask\fR]
-.IQ \fBtun_ipv6_src=\fIipv6\fR[\fB/\fInetmask\fR]
-.IQ \fBtun_ipv6_dst=\fIipv6\fR[\fB/\fInetmask\fR]
-Matches tunnel IP source (or destination) address \fIip\fR. Only packets
-that arrive over a tunnel will have nonzero tunnel addresses.
-The address may be specified as an IP address or host name
-(e.g. \fB192.168.1.1\fR or \fBwww.example.com\fR).  The optional
-\fInetmask\fR allows restricting a match to a masked IP address.
-The netmask may be specified as a dotted quad
-(e.g. \fB192.168.1.0/255.255.255.0\fR) or as a CIDR block
-(e.g. \fB192.168.1.0/24\fR).
-.
-.IP \fBtun_gbp_id=\fIvalue\fR[\fB/\fImask\fR]
-.IQ \fBtun_gbp_flags=\fIvalue\fR[\fB/\fImask\fR]
-Matches the group policy identifier and flags in the VXLAN header. Only
-packets that arrive over a VXLAN tunnel with the "gbp" extension
-enabled can have this field set. The fields may also be referred to by
-NXM_NX_TUN_GBP_ID[] (16 bits) and NXM_NX_TUN_GBP_FLAGS[] (8 bits) in
-the context of field manipulation actions. If these fields are set and
-the packet matched by the flow is encapsulated in a VXLAN-GBP tunnel,
-then the policy identifier and flags are transmitted to the destination
-VXLAN tunnel endpoint.
-.IP
-The \fBtun_gbp_flags\fR field has the following format:
-.IP
-.in +2
-\f(CR+-+-+-+-+-+-+-+-+\fR
-.br
-\f(CR|-|D|-|-|A|-|-|-|\fR
-.br
-\f(CR+-+-+-+-+-+-+-+-+\fR
-
-.B D :=
-Don't Learn bit. When set, this bit indicates that the egress
-tunnel endpoint MUST NOT learn the source address of the encapsulated
-frame.
-
-.B A :=
-Indicates that the group policy has already been applied to
-this packet. Policies MUST NOT be applied by devices when the A bit is
-set.
-.in -2
-.IP
-For more information, please see the corresponding IETF draft:
-https://tools.ietf.org/html/draft-smith-vxlan-group-policy
-.
-.IP "\fBtun_metadata\fIidx\fR[\fB=\fIvalue\fR[\fB/\fImask\fR]]"
-Matches \fIvalue\fR either exactly or with optional \fImask\fR in
-tunnel metadata field number \fIidx\fR (numbered from 0 to 63).
-The act of specifying a field implies a match on the existence
-of that field in the packet in addition to the masked value. As
-a shorthand, it is possible to specify only the field name to
-simply match on an option being present.
-.IP
-Tunnel metadata fields can be dynamically assigned onto the data
-contained in the option TLVs of packets (e.g. Geneve variable
-options stores zero or more options in TLV format and tunnel
-metadata can be assigned onto these option TLVs) using the
-commands described in the section \fBOpenFlow Switch Tunnel TLV Table
-Commands\fR. Once assigned, the length of the field is variable
-according to the size of the option. Before updating a mapping in
-the option table, flows with references to it should be removed,
-otherwise the result is non-deterministic.
-.IP
-These fields were introduced in Open vSwitch 2.5.
-.
-.IP "\fBreg\fIidx\fB=\fIvalue\fR[\fB/\fImask\fR]"
-Matches \fIvalue\fR either exactly or with optional \fImask\fR in
-register number \fIidx\fR.  The valid range of \fIidx\fR depends on
-the switch.  \fIvalue\fR and \fImask\fR are 32-bit integers, by
-default in decimal (use a \fB0x\fR prefix to specify hexadecimal).
-Arbitrary \fImask\fR values are allowed: a 1-bit in \fImask\fR
-indicates that the corresponding bit in \fIvalue\fR must match
-exactly, and a 0-bit wildcards that bit.
-.IP
-When a packet enters an OpenFlow switch, all of the registers are set
-to 0.  Only explicit actions change register values.
-.
-.IP "\fBxreg\fIidx\fB=\fIvalue\fR[\fB/\fImask\fR]"
-Matches \fIvalue\fR either exactly or with optional \fImask\fR in
-64-bit ``extended register'' number \fIidx\fR.  Each of the 64-bit
-extended registers overlays two of the 32-bit registers: \fBxreg0\fR
-overlays \fBreg0\fR and \fBreg1\fR, with \fBreg0\fR supplying the
-most-significant bits of \fBxreg0\fR and \fBreg1\fR the
-least-significant.  \fBxreg1\fR similarly overlays \fBreg2\fR and
-\fBreg3\fR, and so on.
-.IP
-These fields were added in Open vSwitch 2.3 to conform with the
-OpenFlow 1.5 specification.  OpenFlow 1.5 calls these fields
-just the ``packet registers,'' but Open vSwitch already had 32-bit
-registers by that name, which is why Open vSwitch refers to the
-standard registers as ``extended registers''.
-.
-.IP "\fBxxreg\fIidx\fB=\fIvalue\fR[\fB/\fImask\fR]"
-Matches \fIvalue\fR either exactly or with optional \fImask\fR in
-128-bit ``extended-extended register'' number \fIidx\fR.  Each of the
-128-bit extended registers overlays four of the 32-bit registers:
-\fBxxreg0\fR overlays \fBreg0\fR through \fBreg3\fR, with \fBreg0\fR
-supplying the most-significant bits of \fBxxreg0\fR and \fBreg3\fR the
-least-significant.  \fBxxreg1\fR similarly overlays \fBreg4\fR through
-\fBreg7\fR, and so on.
-.IP
-These fields were added in Open vSwitch 2.6.
-.
-.IP \fBpkt_mark=\fIvalue\fR[\fB/\fImask\fR]
-Matches packet metadata mark \fIvalue\fR either exactly or with optional
-\fImask\fR. The mark is associated data that may be passed into other
-system components in order to facilitate interaction between subsystems.
-On Linux this corresponds to the skb mark but the exact implementation is
-platform-dependent.
-.
-.IP \fBactset_output=\fIport\fR
-Matches the output port currently in the OpenFlow action set, where
-\fIport\fR may be an OpenFlow port number or keyword
-(e.g. \fBLOCAL\fR).  If there is no output port in the OpenFlow action
-set, or if the output port will be ignored (e.g. because there is an
-output group in the OpenFlow action set), then the value will be
-\fBUNSET\fR.
-.IP
-This field was introduced in Open vSwitch 2.4 to conform with the
-OpenFlow 1.5 specification.
-.
-.IP \fBconj_id=\fIvalue\fR
-Matches the given 32-bit \fIvalue\fR against the conjunction ID.  This
-is used only with the \fBconjunction\fR action (see below).
-.IP
-This field was introduced in Open vSwitch 2.4.
-.
-.IP \fBct_state=\fIflags\fB/\fImask\fR
-.IQ \fBct_state=\fR[\fB+\fIflag\fR...][\fB-\fIflag\fR...]
-Bitwise match on connection state flags. This is used with the \fBct\fR
-action (see below).
-.IP
-The \fBct_state\fR field provides information from a connection tracking
-module. It describes whether the packet has previously traversed the
-connection tracker (tracked, or trk) and, if it has been tracked, any
-additional information that the connection tracker was able to provide about
-the connection that the current packet belongs to.
-.IP
-Individual packets may be in one of two states: Untracked or tracked. When the
-\fBct\fR action is executed on a packet, it becomes tracked for the the
-remainder of OpenFlow pipeline processing. Once a packet has become tracked,
-the state of its corresponding connection may be determined. Note that the
-\fBct_state\fR is only significant for the current \fBct_zone\fR.
-.IP
-Connections may be in one of two states: uncommitted or committed. Connections
-are uncommitted by default. To determine ongoing information about a
-connection, like whether the connection is established or not, the connection
-must be committed. When the \fBct\fR action is executed on a packet with the
-\fBcommit\fR parameter, the connection will become committed and will remain in
-this state until the end of the connection. Committed connections store state
-beyond the duration of packet processing.
-.IP
-The \fIflags\fR and \fImask\fR are 32-bit numbers written in decimal or
-in hexadecimal prefixed by \fB0x\fR.  Each 1-bit in \fImask\fR requires
-that the corresponding bit in \fIflags\fR must match.  Each 0-bit in
-\fImask\fR causes the corresponding bit to be ignored.
-.IP
-Alternatively, the flags can be specified by their symbolic names
-(listed below), each preceded by either \fB+\fR for a flag that must
-be set, or \fB\-\fR for a flag that must be unset, without any other
-delimiters between the flags.  Flags not mentioned are wildcarded.  For
-example, \fBtcp,ct_state=+trk\-new\fR matches TCP packets that
-have been run through the connection tracker and do not establish a new
-connection.
-.IP
-The following flags describe the state of the tracking:
-.RS
-.IP "\fB0x01: new\fR"
-This is the beginning of a new connection. This flag may only be present for
-uncommitted connections.
-.IP "\fB0x02: est\fR"
-This is part of an already existing connection. This flag may only be present
-for committed connections.
-.IP "\fB0x04: rel\fR"
-This is a connection that is related to an existing connection, for
-instance ICMP "destination unreachable" messages or FTP data connections. This
-flag may only be present for committed connections.
-.IP "\fB0x08: rpl\fR"
-The flow is in the reply direction, meaning it did not initiate the
-connection. This flag may only be present for committed connections.
-.IP "\fB0x10: inv\fR"
-The state is invalid, meaning that the connection tracker couldn't identify the
-connection. This flag is a catch-all for any problems that the connection
-tracker may have, for example:
-.RS
-.PP
-- L3/L4 protocol handler is not loaded/unavailable. With the Linux kernel
-datapath, this may mean that the "nf_conntrack_ipv4" or "nf_conntrack_ipv6"
-modules are not loaded.
-.PP
-- L3/L4 protocol handler determines that the packet is malformed.
-.PP
-- Packets are unexpected length for protocol.
-.RE
-.IP "\fB0x20: trk\fR"
-This packet is tracked, meaning that it has previously traversed the connection
-tracker. If this flag is not set, then no other flags will be set. If this flag
-is set, then the packet is tracked and other flags may also be set.
-.IP "\fB0x40: snat\fR"
-This packet was transformed by source address/port translation by a
-preceding \fBct\fR action.
-.IP "\fB0x80: dnat\fR"
-This packet was transformed by destination address/port translation by
-a preceding \fBct\fR action.
-.PP
-This field was introduced in Open vSwitch 2.5.  The \fBsnat\fR and
-\fBdnat\fR bits were added in Open vSwitch 2.6.
-.RE
-.
-.PP
-The following fields are associated with the connection tracker and will only
-be populated for tracked packets. The \fBct\fR action will populate these
-fields, and allows modification of some of the below fields.
-.IP \fBct_zone=\fIzone
-Matches the given 16-bit connection \fIzone\fR exactly. This represents the
-most recent connection tracking context that \fBct\fR was executed in. Each
-zone is an independent connection tracking context, so if you wish to track
-the same packet in multiple contexts then you must use the \fBct\fR action
-multiple times. Introduced in Open vSwitch 2.5.
-.
-.IP \fBct_mark=\fIvalue\fR[\fB/\fImask\fR]
-Matches the given 32-bit connection mark \fIvalue\fR either exactly or with
-optional \fImask\fR. This represents metadata associated with the connection
-that the current packet is part of. Introduced in Open vSwitch 2.5.
-.
-.IP \fBct_label=\fIvalue\fR[\fB/\fImask\fR]
-Matches the given 128-bit connection labels \fIvalue\fR either exactly or with
-optional \fImask\fR. This represents metadata associated with the connection
-that the current packet is part of. Introduced in Open vSwitch 2.5.
-.
-.PP
-Defining IPv6 flows (those with \fBdl_type\fR equal to 0x86dd) requires
-support for NXM.  The following shorthand notations are available for
-IPv6-related flows:
-.
-.IP \fBipv6\fR
-Same as \fBdl_type=0x86dd\fR.
-.
-.IP \fBtcp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=6\fR.
-.
-.IP \fBudp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=17\fR.
-.
-.IP \fBsctp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=132\fR.
-.
-.IP \fBicmp6\fR
-Same as \fBdl_type=0x86dd,nw_proto=58\fR.
-.
-.PP
-Finally, field assignments to \fBduration\fR, \fBn_packets\fR, or
-\fBn_bytes\fR are ignored to allow output from the \fBdump\-flows\fR
+.IP "\fBduration=\fR..."
+.IQ "\fBn_packet=\fR..."
+.IQ "\fBn_bytes=\fR..."
+These ``fields'' are ignored to allow output from the \fBdump\-flows\fR
 command to be used as input for other commands that parse flows.
 .
 .PP
@@ -2409,205 +1636,8 @@  are ignored.  Actions in the action set is still executed (specify
 \fBclear_actions\fR before \fBexit\fR to discard them).
 .
 .IP "\fBconjunction(\fIid\fB, \fIk\fB/\fIn\fR\fB)\fR"
-An individual OpenFlow flow can match only a single value for each
-field.  However, situations often arise where one wants to match one
-of a set of values within a field or fields.  For matching a single
-field against a set, it is straightforward and efficient to add
-multiple flows to the flow table, one for each value in the set.  For
-example, one might use the following flows to send packets with IP
-source address \fIa\fR, \fIb\fR, \fIc\fR, or \fId\fR to the OpenFlow
-controller:
-.RS +1in
-.br
-\fBip,ip_src=\fIa\fB actions=controller\fR
-.br
-\fBip,ip_src=\fIb\fB actions=controller\fR
-.br
-\fBip,ip_src=\fIc\fB actions=controller\fR
-.br
-\fBip,ip_src=\fId\fB actions=controller\fR
-.br
-.RE
-.IP
-Similarly, these flows send packets with IP destination address
-\fIe\fR, \fIf\fR, \fIg\fR, or \fIh\fR to the OpenFlow controller:
-.RS +1in
-.br
-\fBip,ip_dst=\fIe\fB actions=controller\fR
-.br
-\fBip,ip_dst=\fIf\fB actions=controller\fR
-.br
-\fBip,ip_dst=\fIg\fB actions=controller\fR
-.br
-\fBip,ip_dst=\fIh\fB actions=controller\fR
-.br
-.RE
-.IP
-Installing all of the above flows in a single flow table yields a
-disjunctive effect: a packet is sent to the controller if \fBip_src\fR
-\[mo] {\fIa\fR,\fIb\fR,\fIc\fR,\fId\fR} or \fBip_dst\fR \[mo]
-{\fIe\fR,\fIf\fR,\fIg\fR,\fIh\fR} (or both).  (Pedantically, if both
-of the above sets of flows are present in the flow table, they should
-have different priorities, because OpenFlow says that the results are
-undefined when two flows with same priority can both match a single
-packet.)
-.IP
-Suppose, on the other hand, one wishes to match conjunctively, that
-is, to send a packet to the controller only if both \fBip_src\fR \[mo]
-{\fIa\fR,\fIb\fR,\fIc\fR,\fId\fR} and \fBip_dst\fR \[mo]
-{\fIe\fR,\fIf\fR,\fIg\fR,\fIh\fR}.  This requires 4 \[mu] 4 = 16
-flows, one for each possible pairing of \fBip_src\fR and \fBip_dst\fR.
-That is acceptable for our small example, but it does not gracefully
-extend to larger sets or greater numbers of dimensions.
-.IP
-The \fBconjunction\fR action is a solution for conjunctive matches
-that is built into Open vSwitch.  A \fBconjunction\fR action ties
-groups of individual OpenFlow flows into higher-level ``conjunctive
-flows''.  Each group corresponds to one dimension, and each flow
-within the group matches one possible value for the dimension.  A
-packet that matches one flow from each group matches the conjunctive
-flow.
-.IP
-To implement a conjunctive flow with \fBconjunction\fR, assign the
-conjunctive flow a 32-bit \fIid\fR, which must be unique within an
-OpenFlow table.  Assign each of the \fIn\fR \[>=] 2 dimensions a
-unique number from 1 to \fIn\fR; the ordering is unimportant.  Add one
-flow to the OpenFlow flow table for each possible value of each
-dimension with \fBconjunction(\fIid, \fIk\fB/\fIn\fB)\fR as the flow's
-actions, where \fIk\fR is the number assigned to the flow's dimension.
-Together, these flows specify the conjunctive flow's match condition.
-When the conjunctive match condition is met, Open vSwitch looks up one
-more flow that specifies the conjunctive flow's actions and receives
-its statistics.  This flow is found by setting \fBconj_id\fR to the
-specified \fIid\fR and then again searching the flow table.
-.IP
-The following flows provide an example.  Whenever the IP source is one
-of the values in the flows that match on the IP source (dimension 1 of
-2), \fIand\fR the IP destination is one of the values in the flows
-that match on IP destination (dimension 2 of 2), Open vSwitch searches
-for a flow that matches \fBconj_id\fR against the conjunction ID
-(1234), finding the first flow listed below.
-.RS +1in
-.br
-.B "conj_id=1234 actions=controller"
-.br
-.B "ip,ip_src=10.0.0.1 actions=conjunction(1234, 1/2)"
-.br
-.B "ip,ip_src=10.0.0.4 actions=conjunction(1234, 1/2)"
-.br
-.B "ip,ip_src=10.0.0.6 actions=conjunction(1234, 1/2)"
-.br
-.B "ip,ip_src=10.0.0.7 actions=conjunction(1234, 1/2)"
-.br
-.B "ip,ip_dst=10.0.0.2 actions=conjunction(1234, 2/2)"
-.br
-.B "ip,ip_dst=10.0.0.5 actions=conjunction(1234, 2/2)"
-.br
-.B "ip,ip_dst=10.0.0.7 actions=conjunction(1234, 2/2)"
-.br
-.B "ip,ip_dst=10.0.0.8 actions=conjunction(1234, 2/2)"
-.RE
-.IP
-Many subtleties exist:
-.RS
-.IP \(bu
-In the example above, every flow in a single dimension has the same
-form, that is, dimension 1 matches on \fBip_src\fR, dimension 2 on
-\fBip_dst\fR, but this is not a requirement.  Different flows within a
-dimension may match on different bits within a field (e.g. IP network
-prefixes of different lengths, or TCP/UDP port ranges as bitwise
-matches), or even on entirely different fields (e.g. to match packets
-for TCP source port 80 or TCP destination port 80).
-.IP \(bu
-The flows within a dimension can vary their matches across more than
-one field, e.g. to match only specific pairs of IP source and
-destination addresses or L4 port numbers.
-.IP \(bu
-A flow may have multiple \fBconjunction\fR actions, with different
-\fIid\fR values.  This is useful for multiple conjunctive flows with
-overlapping sets.  If one conjunctive flow matches packets with both
-\fBip_src\fR \[mo] {\fIa\fR,\fIb\fR} and \fBip_dst\fR \[mo]
-{\fId\fR,\fIe\fR} and a second conjunctive flow matches \fBip_src\fR
-\[mo] {\fIb\fR,\fIc\fR} and \fBip_dst\fR \[mo] {\fIf\fR,\fIg\fR}, for
-example, then the flow that matches \fBip_src=\fIb\fR would have two
-\fBconjunction\fR actions, one for each conjunctive flow.  The order
-of \fBconjunction\fR actions within a list of actions is not
-significant.
-.IP \(bu
-A flow with \fBconjunction\fR actions may also include \fBnote\fR
-actions for annotations, but not any other kind of actions.  (They
-would not be useful because they would never be executed.)
-.IP \(bu
-All of the flows that constitute a conjunctive flow with a given
-\fIid\fR must have the same priority.  (Flows with the same \fIid\fR
-but different priorities are currently treated as different
-conjunctive flows, that is, currently \fIid\fR values need only be
-unique within an OpenFlow table at a given priority.  This behavior
-isn't guaranteed to stay the same in later releases, so please use
-\fIid\fR values unique within an OpenFlow table.)
-.IP \(bu
-Conjunctive flows must not overlap with each other, at a given
-priority, that is, any given packet must be able to match at most one
-conjunctive flow at a given priority.  Overlapping conjunctive flows
-yield unpredictable results.
-.IP \(bu
-Following a conjunctive flow match, the search for the flow with
-\fBconj_id=\fIid\fR is done in the same general-purpose way as other flow
-table searches, so one can use flows with \fBconj_id=\fIid\fR to act
-differently depending on circumstances.  (One exception is that the
-search for the \fBconj_id=\fIid\fR flow itself ignores conjunctive flows,
-to avoid recursion.) If the search with \fBconj_id=\fIid\fR fails, Open
-vSwitch acts as if the conjunctive flow had not matched at all, and
-continues searching the flow table for other matching flows.
-.IP \(bu
-OpenFlow prerequisite checking occurs for the flow with
-\fBconj_id=\fIid\fR in the same way as any other flow, e.g. in an
-OpenFlow 1.1+ context, putting a \fBmod_nw_src\fR action into the
-example above would require adding an \fBip\fR match, like this:
-.RS +1in
-.br
-.B "conj_id=1234,ip actions=mod_nw_src:1.2.3.4,controller"
-.br
-.RE
-.IP \(bu
-OpenFlow prerequisite checking also occurs for the individual flows
-that comprise a conjunctive match in the same way as any other flow.
-.IP \(bu
-The flows that constitute a conjunctive flow do not have useful
-statistics.  They are never updated with byte or packet counts, and so
-on.  (For such a flow, therefore, the idle and hard timeouts work much
-the same way.)
-.IP \(bu
-Conjunctive flows can be a useful building block for negation, that
-is, inequality matches like \fBtcp_src\fR \[!=] 80.  To implement an
-inequality match, convert it to a pair of range matches, e.g. 0 \[<=]
-\fBtcp_src\fR < 80 and 80 < \fBtcp_src\fR \[<=] 65535, then convert each
-of the range matches into a collection of bitwise matches as explained
-above in the description of \fBtcp_src\fR.
-.IP \(bu
-Sometimes there is a choice of which flows include a particular match.
-For example, suppose that we added an extra constraint to our example,
-to match on \fBip_src\fR \[mo] {\fIa\fR,\fIb\fR,\fIc\fR,\fId\fR} and
-\fBip_dst\fR \[mo] {\fIe\fR,\fIf\fR,\fIg\fR,\fIh\fR} and \fBtcp_dst\fR
-= \fIi\fR.  One way to implement this is to add the new constraint to
-the \fBconj_id\fR flow, like this:
-.RS +1in
-.br
-\fBconj_id=1234,tcp,tcp_dst=\fIi\fB actions=mod_nw_src:1.2.3.4,controller\fR
-.br
-.RE
-.IP
-\fIbut this is not recommended\fR because of the cost of the extra
-flow table lookup.  Instead, add the constraint to the individual
-flows, either in one of the dimensions or (slightly better) all of
-them.
-.IP \(bu
-A conjunctive match must have \fIn\fR \[>=] 2 dimensions (otherwise a
-conjunctive match is not necessary).  Open vSwitch enforces this.
-.IP \(bu
-Each dimension within a conjunctive match should ordinarily have more
-than one flow.  Open vSwitch does not enforce this.
-.RE
+This action allows for sophisticated ``conjunctive match'' flows.
+Refer to \fBCONJUNCTIVE MATCH FIELDS\fR in \fBovs\-fields\fR(7) for details.
 .IP
 The \fBconjunction\fR action and \fBconj_id\fR field were introduced
 in Open vSwitch 2.4.
@@ -3286,6 +2316,7 @@  Additional examples may be found documented as part of related sections.
 .
 .SH "SEE ALSO"
 .
+.BR ovs\-fields (7),
 .BR ovs\-appctl (8),
-.BR ovs\-vswitchd (8)
+.BR ovs\-vswitchd (8),
 .BR ovs\-vswitchd.conf.db (8)
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index b4af5a5..f3dc8e7 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -2236,9 +2236,9 @@ 
             <li>
               <code>gbp</code>: VXLAN-GBP allows to transport the group policy
               context of a packet across the VXLAN tunnel to other network
-              peers. See the field description of <code>tun_gbp_id</code> and
-              <code>tun_gbp_flags</code> in ovs-ofctl(8) for additional
-              information.
+              peers. See the description of <code>tun_gbp_id</code> and
+              <code>tun_gbp_flags</code> in <code>ovs-fields</code>(7) for
+              additional information.
               (<code>https://tools.ietf.org/html/draft-smith-vxlan-group-policy</code>)
             </li>
           </ul>