]> git.proxmox.com Git - ovs.git/blobdiff - ovn/ovn-sb.xml
ovn-controller: use idl indexes for logical datapath
[ovs.git] / ovn / ovn-sb.xml
index 7defad9b5b2a156c66cf9c04738842e2f71ff8d4..08d784ac6689a0758a519411c9e4f49dc3be0f21 100644 (file)
     The OVN Southbound database sits at the center of the OVN
     architecture.  It is the one component that speaks both southbound
     directly to all the hypervisors and gateways, via
-    <code>ovn-controller</code>, and northbound to the Cloud Management
-    System, via <code>ovn-northd</code>:
+    <code>ovn-controller</code>/<code>ovn-controller-vtep</code>, and
+    northbound to the Cloud Management System, via <code>ovn-northd</code>:
   </p>
 
   <h2>Database Structure</h2>
 
   <p>
-    The OVN Southbound database contains three classes of data with
+    The OVN Southbound database contains classes of data with
     different properties, as described in the sections below.
   </p>
 
-  <h3>Physical Network (PN) data</h3>
+  <h3>Physical network</h3>
 
   <p>
-    PN tables contain information about the chassis nodes in the system.  This
-    contains all the information necessary to wire the overlay, such as IP
-    addresses, supported tunnel types, and security keys.
+    Physical network tables contain information about the chassis nodes in the
+    system.  This contains all the information necessary to wire the overlay,
+    such as IP addresses, supported tunnel types, and security keys.
   </p>
 
   <p>
-    The amount of PN data is small (O(n) in the number of chassis) and it
-    changes infrequently, so it can be replicated to every chassis.
+    The amount of physical network data is small (O(n) in the number of
+    chassis) and it changes infrequently, so it can be replicated to every
+    chassis.
   </p>
 
   <p>
-    The <ref table="Chassis"/> table comprises the PN tables.
+    The <ref table="Chassis"/> and <ref table="Encap"/> tables are the physical
+    network tables.
   </p>
 
-  <h3>Logical Network (LN) data</h3>
+  <h3>Logical Network</h3>
 
   <p>
-    LN tables contain the topology of logical switches and routers, ACLs,
-    firewall rules, and everything needed to describe how packets traverse a
-    logical network, represented as logical datapath flows (see Logical
-    Datapath Flows, below).
+    Logical network tables contain the topology of logical switches and
+    routers, ACLs, firewall rules, and everything needed to describe how
+    packets traverse a logical network, represented as logical datapath flows
+    (see Logical Datapath Flows, below).
   </p>
 
   <p>
-    LN data may be large (O(n) in the number of logical ports, ACL rules,
-    etc.).  Thus, to improve scaling, each chassis should receive only data
-    related to logical networks in which that chassis participates.  Past
-    experience shows that in the presence of large logical networks, even
-    finer-grained partitioning of data, e.g. designing logical flows so that
-    only the chassis hosting a logical port needs related flows, pays off
-    scale-wise.  (This is not necessary initially but it is worth bearing in
-    mind in the design.)
+    Logical network data may be large (O(n) in the number of logical ports, ACL
+    rules, etc.).  Thus, to improve scaling, each chassis should receive only
+    data related to logical networks in which that chassis participates.
   </p>
 
   <p>
-    The LN is a slave of the cloud management system running northbound of OVN.
-    That CMS determines the entire OVN logical configuration and therefore the
-    LN's content at any given time is a deterministic function of the CMS's
-    configuration, although that happens indirectly via the OVN Northbound DB
-    and <code>ovn-northd</code>.
+    The logical network data is ultimately controlled by the cloud management
+    system (CMS) running northbound of OVN.  That CMS determines the entire OVN
+    logical configuration and therefore the logical network data at any given
+    time is a deterministic function of the CMS's configuration, although that
+    happens indirectly via the <ref db="OVN_Northbound"/> database and
+    <code>ovn-northd</code>.
   </p>
 
   <p>
-    LN data is likely to change more quickly than PN data.  This is especially
-    true in a container environment where VMs are created and destroyed (and
-    therefore added to and deleted from logical switches) quickly.
+    Logical network data is likely to change more quickly than physical network
+    data.  This is especially true in a container environment where containers
+    are created and destroyed (and therefore added to and deleted from logical
+    switches) quickly.
   </p>
 
   <p>
-    <ref table="Logical_Flow"/> and <ref table="Multicast_Group"/> contain LN
-    data.
+    The <ref table="Logical_Flow"/>, <ref table="Multicast_Group"/>, <ref
+    table="Address_Group"/>, <ref table="DHCP_Options"/>, <ref
+    table="DHCPv6_Options"/>, and <ref table="DNS"/> tables contain logical
+    network data.
   </p>
 
-  <h3>Bindings data</h3>
+  <h3>Logical-physical bindings</h3>
 
   <p>
-    Bindings data link logical and physical components.  They show the current
+    These tables link logical and physical components.  They show the current
     placement of logical components (such as VMs and VIFs) onto chassis, and
     map logical entities to the values that represent them in tunnel
     encapsulations.
   </p>
 
   <p>
-    Bindings change frequently, at least every time a VM powers up or down
+    These tables change frequently, at least every time a VM powers up or down
     or migrates, and especially quickly in a container environment.  The
     amount of data per VM (or VIF) is small.
   </p>
     contain binding data.
   </p>
 
+  <h3>MAC bindings</h3>
+
+  <p>
+    The <ref table="MAC_Binding"/> table tracks the bindings from IP addresses
+    to Ethernet addresses that are dynamically discovered using ARP (for IPv4)
+    and neighbor discovery (for IPv6).  Usually, IP-to-MAC bindings for virtual
+    machines are statically populated into the <ref table="Port_Binding"/>
+    table, so <ref table="MAC_Binding"/> is primarily used to discover bindings
+    on physical networks.
+  </p>
+
   <h2>Common Columns</h2>
 
   <p>
     <dt><code>external_ids</code>: map of string-string pairs</dt>
     <dd>
       Key-value pairs for use by the software that manages the OVN Southbound
-      database rather than by <code>ovn-controller</code>.  In particular,
-      <code>ovn-northd</code> can use key-value pairs in this column to relate
-      entities in the southbound database to higher-level entities (such as
-      entities in the OVN Northbound database).  Individual key-value pairs in
-      this column may be documented in some cases to aid in understanding and
-      troubleshooting, but the reader should not mistake such documentation as
-      comprehensive.
+      database rather than by
+      <code>ovn-controller</code>/<code>ovn-controller-vtep</code>.  In
+      particular, <code>ovn-northd</code> can use key-value pairs in this
+      column to relate entities in the southbound database to higher-level
+      entities (such as entities in the OVN Northbound database).  Individual
+      key-value pairs in this column may be documented in some cases to aid
+      in understanding and troubleshooting, but the reader should not mistake
+      such documentation as comprehensive.
     </dd>
   </dl>
 
+  <table name="SB_Global" title="Southbound configuration">
+    <p>
+      Southbound configuration for an OVN system.  This table must have exactly
+      one row.
+    </p>
+
+    <group title="Status">
+      This column allow a client to track the overall configuration state of
+      the system.
+
+      <column name="nb_cfg">
+        Sequence number for the configuration.  When a CMS or
+        <code>ovn-nbctl</code> updates the northbound database, it increments
+        the <code>nb_cfg</code> column in the <code>NB_Global</code> table in
+        the northbound database.  In turn, when <code>ovn-northd</code> updates
+        the southbound database to bring it up to date with these changes, it
+        updates this column to the same value.
+      </column>
+    </group>
+
+    <group title="Common Columns">
+      <column name="external_ids">
+        See <em>External IDs</em> at the beginning of this document.
+      </column>
+    </group>
+    <group title="Connection Options">
+      <column name="connections">
+        Database clients to which the Open vSwitch database server should
+        connect or on which it should listen, along with options for how these
+        connections should be configured.  See the <ref table="Connection"/>
+        table for more information.
+      </column>
+      <column name="ssl">
+        Global SSL configuration.
+      </column>
+    </group>
+  </table>
+
   <table name="Chassis" title="Physical Network Hypervisor and Gateway Information">
     <p>
       Each row in this table represents a hypervisor or gateway (a chassis) in
-      the physical network (PN).  Each chassis, via
-      <code>ovn-controller</code>, adds and updates its own row, and keeps a
-      copy of the remaining rows to determine how to reach other hypervisors.
+      the physical network.  Each chassis, via
+      <code>ovn-controller</code>/<code>ovn-controller-vtep</code>, adds
+      and updates its own row, and keeps a copy of the remaining rows to
+      determine how to reach other hypervisors.
     </p>
 
     <p>
     </p>
 
     <column name="name">
-      A chassis name, taken from <ref key="system-id" table="Open_vSwitch"
-      column="external_ids" db="Open_vSwitch"/> in the Open_vSwitch
-      database's <ref table="Open_vSwitch" db="Open_vSwitch"/> table.  OVN does
-      not prescribe a particular format for chassis names.
+      OVN does not prescribe a particular format for chassis names.
+      ovn-controller populates this column using <ref key="system-id"
+      table="Open_vSwitch" column="external_ids" db="Open_vSwitch"/>
+      in the Open_vSwitch database's <ref table="Open_vSwitch"
+      db="Open_vSwitch"/> table.  ovn-controller-vtep populates this
+      column with <ref table="Physical_Switch" column="name"
+      db="hardware_vtep"/> in the hardware_vtep database's
+      <ref table="Physical_Switch" db="hardware_vtep"/> table.
+    </column>
+
+    <column name="hostname">
+      The hostname of the chassis, if applicable.  ovn-controller will populate
+      this column with the hostname of the host it is running on.
+      ovn-controller-vtep will leave this column empty.
+    </column>
+
+    <column name="nb_cfg">
+      Sequence number for the configuration.  When <code>ovn-controller</code>
+      updates the configuration of a chassis from the contents of the
+      southbound database, it copies <ref table="SB_Global" column="nb_cfg"/>
+      from the <ref table="SB_Global"/> table into this column.
+    </column>
+
+    <column name="external_ids" key="ovn-bridge-mappings">
+      <code>ovn-controller</code> populates this key with the set of bridge
+      mappings it has been configured to use.  Other applications should treat
+      this key as read-only.  See <code>ovn-controller</code>(8) for more
+      information.
     </column>
 
+    <column name="external_ids" key="datapath-type">
+      <code>ovn-controller</code> populates this key with the datapath type
+      configured in the <ref table="Bridge" column="datapath_type"/> column of
+      the Open_vSwitch database's <ref table="Bridge" db="Open_vSwitch"/>
+      table.  Other applications should treat this key as read-only. See
+      <code>ovn-controller</code>(8) for more information.
+    </column>
+
+    <column name="external_ids" key="iface-types">
+      <code>ovn-controller</code> populates this key with the interface types
+      configured in the <ref table="Open_vSwitch" column="iface_types"/> column
+      of the Open_vSwitch database's <ref table="Open_vSwitch"
+      db="Open_vSwitch"/> table.  Other applications should treat this key as
+      read-only. See <code>ovn-controller</code>(8) for more information.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+
     <group title="Encapsulation Configuration">
       <p>
         OVN uses encapsulation to transmit logical dataplane packets
       </column>
     </group>
 
-     <group title="Gateway Configuration">
-       <p>
+    <group title="Gateway Configuration">
+      <p>
         A <dfn>gateway</dfn> is a chassis that forwards traffic between the
         OVN-managed part of a logical network and a physical VLAN, extending a
         tunnel-based logical network into a physical network.  Gateways are
-        typically dedicated nodes that do not host VMs.
+        typically dedicated nodes that do not host VMs and will be controlled
+        by <code>ovn-controller-vtep</code>.
       </p>
 
       <column name="vtep_logical_switches">
-        Stores all vtep logical switch names connected by this gateway
-        chassis.
+        Stores all VTEP logical switch names connected by this gateway
+        chassis.  The <ref table="Port_Binding"/> table entry with
+        <ref column="options" table="Port_Binding"/>:<code>vtep-physical-switch</code>
+        equal <ref table="Chassis"/> <ref column="name" table="Chassis"/>, and
+        <ref column="options" table="Port_Binding"/>:<code>vtep-logical-switch</code>
+        value in <ref table="Chassis"/>
+        <ref column="vtep_logical_switches" table="Chassis"/>, will be
+        associated with this <ref table="Chassis"/>.
       </column>
-     </group>
+    </group>
   </table>
 
   <table name="Encap" title="Encapsulation Types">
       The <ref column="encaps" table="Chassis"/> column in the <ref
       table="Chassis"/> table refers to rows in this table to identify
       how OVN may transmit logical dataplane packets to this chassis.
-      Each chassis, via <code>ovn-controller</code>(8), adds and updates
-      its own rows and keeps a copy of the remaining rows to determine
-      how to reach other chassis.
+      Each chassis, via <code>ovn-controller</code>(8) or
+      <code>ovn-controller-vtep</code>(8), adds and updates its own rows
+      and keeps a copy of the remaining rows to determine how to reach
+      other chassis.
     </p>
 
     <column name="type">
     </column>
 
     <column name="options">
-      Options for configuring the encapsulation, e.g. IPsec parameters when
-      IPsec support is introduced.  No options are currently defined.
+      <p>
+        Options for configuring the encapsulation. Currently, the only
+        option that has been defined is <code>csum</code>.
+      </p>
+
+      <p>
+        <code>csum</code> indicates that encapsulation checksums can be
+        transmitted and received with reasonable performance. It is a hint
+        to senders transmitting data to this chassis that they should use
+        checksums to protect OVN metadata. <code>ovn-controller</code>
+        populates this key with the value defined in
+        <ref table="Open_vSwitch" column="external_ids:ovn-encap-csum"/> column
+        of the Open_vSwitch database's <ref table="Open_vSwitch"
+        db="Open_vSwitch"/> table.  Other applications should treat this key as
+        read-only. See <code>ovn-controller</code>(8) for more information.
+      </p>
+
+      <p>
+        In terms of performance, this actually significantly increases
+        throughput in most common cases when running on Linux based hosts
+        without NICs supporting encapsulation hardware offload (around 60% for
+        bulk traffic). The reason is that generally all NICs are capable of
+        offloading transmitted and received TCP/UDP checksums (viewed as
+        ordinary data packets and not as tunnels). The benefit comes on the
+        receive side where the validated outer checksum can be used to
+        additionally validate an inner checksum (such as TCP), which in turn
+        allows aggregation of packets to be more efficiently handled by the
+        rest of the stack.
+      </p>
+
+      <p>
+        Not all devices see such a benefit. The most notable exception is
+        hardware VTEPs. These devices are designed to not buffer entire
+        packets in their switching engines and are therefore unable to
+        efficiently compute or validate full packet checksums. In addition
+        certain versions of the Linux kernel are not able to fully take
+        advantage of encapsulation NIC offloads in the presence of checksums.
+        (This is actually a pretty narrow corner case though - earlier
+        versions of Linux don't support encapsulation offloads at all and
+        later versions support both offloads and checksums well.)
+      </p>
+
+      <p>
+        <code>csum</code> defaults to <code>false</code> for hardware VTEPs and
+        <code>true</code> for all other cases.
+      </p>
     </column>
 
     <column name="ip">
       The IPv4 address of the encapsulation tunnel endpoint.
     </column>
+    <column name="chassis_name">
+      The name of the chassis that created this encap.
+    </column>
+  </table>
+
+  <table name="Address_Set" title="Address Sets">
+    <p>
+      See the documentation for the <ref table="Address_Set"
+      db="OVN_Northbound"/> table in the <ref db="OVN_Northbound"/> database
+      for details.
+    </p>
+
+    <column name="name"/>
+    <column name="addresses"/>
   </table>
 
   <table name="Logical_Flow" title="Logical Network Flows">
     <p>
-      Each row in this table represents one logical flow.  The cloud management
-      system, via its OVN integration, populates this table with logical flows
-      that implement the L2 and L3 topology specified in the CMS configuration.
-      Each hypervisor, via <code>ovn-controller</code>, translates the logical
-      flows into OpenFlow flows specific to its hypervisor and installs them
-      into Open vSwitch.
+      Each row in this table represents one logical flow.
+      <code>ovn-northd</code> populates this table with logical flows
+      that implement the L2 and L3 topologies specified in the
+      <ref db="OVN_Northbound"/> database.  Each hypervisor, via
+      <code>ovn-controller</code>, translates the logical flows into
+      OpenFlow flows specific to its hypervisor and installs them into
+      Open vSwitch.
     </p>
 
     <p>
       flows are written in terms of logical ports and logical datapaths instead
       of physical ports and physical datapaths.  Translation between logical
       and physical flows helps to ensure isolation between logical datapaths.
-      (The logical flow abstraction also allows the CMS to do less work, since
-      it does not have to separately compute and push out physical flows to each
-      chassis.)
+      (The logical flow abstraction also allows the OVN centralized
+      components to do less work, since they do not have to separately
+      compute and push out physical flows to each chassis.)
     </p>
 
     <p>
       The default action when no flow matches is to drop packets.
     </p>
 
-    <p><em>Logical Life Cycle of a Packet</em></p>
+    <p><em>Architectural Logical Life Cycle of a Packet</em></p>
 
     <p>
       This following description focuses on the life cycle of a packet through
       a logical datapath, ignoring physical details of the implementation.
-      Please refer to <em>Life Cycle of a Packet</em> in
+      Please refer to <em>Architectural Physical Life Cycle of a Packet</em> in
       <code>ovn-architecture</code>(7) for the physical information.
     </p>
 
       depends on the current value of the <code>outport</code> field.  Suppose
       <code>outport</code> designates a logical port.  First, OVN compares
       <code>inport</code> to <code>outport</code>; if they are equal, it treats
-      the <code>output</code> as a no-op.  In the common case, where they are
-      different, the packet enters the egress pipeline.  This transition to the
-      egress pipeline discards register data, e.g. <code>reg0</code>
-      ... <code>reg5</code>, to achieve uniform behavior regardless of whether
-      the egress pipeline is on a different hypervisor (because registers
-      aren't preserve across tunnel encapsulation).
+      the <code>output</code> as a no-op by default.  In the common
+      case, where they are different, the packet enters the egress
+      pipeline.  This transition to the egress pipeline discards
+      register data, e.g. <code>reg0</code> ...  <code>reg9</code> and
+      connection tracking state, to achieve uniform behavior regardless
+      of whether the egress pipeline is on a different hypervisor
+      (because registers aren't preserve across tunnel encapsulation).
     </p>
 
     <p>
       the logical output port replaced by the group member.
     </p>
 
+    <p><em>Pipeline Stages</em></p>
+
+    <p>
+      <code>ovn-northd</code> populates the <ref table="Logical_Flow"/> table
+      with the logical flows described in detail in <code>ovn-northd</code>(8).
+    </p>
+
     <column name="logical_datapath">
       The logical datapath to which the logical flow belongs.
     </column>
         packet.
       </p>
 
+      <p>
+        Match expressions also support a kind of function syntax.  The
+        following functions are supported:
+      </p>
+
+      <dl>
+        <dt><code>is_chassis_resident(<var>lport</var>)</code></dt>
+        <dd>
+          Evaluates to true on a chassis on which logical port <var>lport</var>
+          (a quoted string) resides, and to false elsewhere.  This function was
+          introduced in OVN 2.7.
+        </dd>
+      </dl>
+
       <p><em>Symbols</em></p>
 
       <p>
         </code>...<code></code>''.
       </p>
 
+      <p>
+        You may refer to a set of IPv4, IPv6, or MAC addresses stored in the
+        <ref table="Address_Set"/> table by its <ref column="name"
+        table="Address_Set"/>.  An <ref table="Address_Set"/> with a name
+        of <code>set1</code> can be referred to as
+        <code>$set1</code>.
+      </p>
+
       <p><em>Miscellaneous</em></p>
 
       <p>
         symbols, only names within the flow's logical datapath may be used.
       </p>
 
+      <p>
+        The <code>reg</code><var>X</var> symbols are 32-bit integers.
+        The <code>xxreg</code><var>X</var> symbols are 128-bit integers,
+        which overlay 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-signficant.
+        <code>xxreg1</code> similarly overlays <code>reg4</code> through
+        <code>reg7</code>.
+      </p>
+
       <ul>
-        <li><code>reg0</code>...<code>reg5</code></li>
+        <li><code>reg0</code>...<code>reg9</code></li>
+        <li><code>xxreg0</code> <code>xxreg1</code></li>
         <li><code>inport</code> <code>outport</code></li>
+        <li><code>flags.loopback</code></li>
         <li><code>eth.src</code> <code>eth.dst</code> <code>eth.type</code></li>
         <li><code>vlan.tci</code> <code>vlan.vid</code> <code>vlan.pcp</code> <code>vlan.present</code></li>
         <li><code>ip.proto</code> <code>ip.dscp</code> <code>ip.ecn</code> <code>ip.ttl</code> <code>ip.frag</code></li>
         <li><code>icmp4.type</code> <code>icmp4.code</code></li>
         <li><code>icmp6.type</code> <code>icmp6.code</code></li>
         <li><code>nd.target</code> <code>nd.sll</code> <code>nd.tll</code></li>
+        <li><code>ct_mark</code> <code>ct_label</code></li>
+        <li>
+          <p>
+            <code>ct_state</code>, which has several Boolean subfields.  The
+            <code>ct_next</code> action initializes the following subfields:
+          </p>
+          <ul>
+            <li>
+              <code>ct.trk</code>: Always set to true by <code>ct_next</code>
+              to indicate that connection tracking has taken place.  All other
+              <code>ct</code> subfields have <code>ct.trk</code> as a
+              prerequisite.
+            </li>
+            <li><code>ct.new</code>: True for a new flow</li>
+            <li><code>ct.est</code>: True for an established flow</li>
+            <li><code>ct.rel</code>: True for a related flow</li>
+            <li><code>ct.rpl</code>: True for a reply flow</li>
+            <li><code>ct.inv</code>: True for a connection entry in a bad state</li>
+          </ul>
+          <p>
+            The <code>ct_dnat</code>, <code>ct_snat</code>, and
+            <code>ct_lb</code> actions initialize the following subfields:
+          </p>
+          <ul>
+            <li>
+              <code>ct.dnat</code>: True for a packet whose destination IP
+              address has been changed.
+            </li>
+            <li>
+              <code>ct.snat</code>: True for a packet whose source IP
+              address has been changed.
+            </li>
+          </ul>
+        </li>
       </ul>
 
+      <p>
+        The following predicates are supported:
+      </p>
+
+      <ul>
+        <li><code>eth.bcast</code> expands to <code>eth.dst == ff:ff:ff:ff:ff:ff</code></li>
+        <li><code>eth.mcast</code> expands to <code>eth.dst[40]</code></li>
+        <li><code>vlan.present</code> expands to <code>vlan.tci[12]</code></li>
+        <li><code>ip4</code> expands to <code>eth.type == 0x800</code></li>
+        <li><code>ip4.mcast</code> expands to <code>ip4.dst[28..31] == 0xe</code></li>
+        <li><code>ip6</code> expands to <code>eth.type == 0x86dd</code></li>
+        <li><code>ip</code> expands to <code>ip4 || ip6</code></li>
+        <li><code>icmp4</code> expands to <code>ip4 &amp;&amp; ip.proto == 1</code></li>
+        <li><code>icmp6</code> expands to <code>ip6 &amp;&amp; ip.proto == 58</code></li>
+        <li><code>icmp</code> expands to <code>icmp4 || icmp6</code></li>
+        <li><code>ip.is_frag</code> expands to <code>ip.frag[0]</code></li>
+        <li><code>ip.later_frag</code> expands to <code>ip.frag[1]</code></li>
+        <li><code>ip.first_frag</code> expands to <code>ip.is_frag &amp;&amp; !ip.later_frag</code></li>
+        <li><code>arp</code> expands to <code>eth.type == 0x806</code></li>
+        <li><code>nd</code> expands to <code>icmp6.type == {135, 136} &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
+        <li><code>nd_ns</code> expands to <code>icmp6.type == 135 &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
+        <li><code>nd_na</code> expands to <code>icmp6.type == 136 &amp;&amp; icmp6.code == 0 &amp;&amp; ip.ttl == 255</code></li>
+        <li><code>tcp</code> expands to <code>ip.proto == 6</code></li>
+        <li><code>udp</code> expands to <code>ip.proto == 17</code></li>
+        <li><code>sctp</code> expands to <code>ip.proto == 132</code></li>
+      </ul>
     </column>
 
     <column name="actions">
       </p>
 
       <p>
-       The following actions are defined:
+        The following actions are defined:
       </p>
 
       <dl>
         <dt><code>output;</code></dt>
         <dd>
           <p>
-           In the ingress pipeline, this action executes the
-           <code>egress</code> pipeline as a subroutine.  If
-           <code>outport</code> names a logical port, the egress pipeline
-           executes once; if it is a multicast group, the egress pipeline runs
-           once for each logical port in the group.
+            In the ingress pipeline, this action executes the
+            <code>egress</code> pipeline as a subroutine.  If
+            <code>outport</code> names a logical port, the egress pipeline
+            executes once; if it is a multicast group, the egress pipeline runs
+            once for each logical port in the group.
           </p>
 
           <p>
           </p>
 
           <p>
-            Output to the input port is implicitly dropped, that is,
-            <code>output</code> becomes a no-op if <code>outport</code> ==
-            <code>inport</code>.
+            By default, output to the input port is implicitly dropped,
+            that is, <code>output</code> becomes a no-op if
+            <code>outport</code> == <code>inport</code>.  Occasionally
+            it may be useful to override this behavior, e.g. to send an
+            ARP reply to an ARP request; to do so, use
+            <code>flags.loopback = 1</code> to allow the packet to
+            "hair-pin" back to the input port.
           </p>
-       </dd>
+        </dd>
 
         <dt><code>next;</code></dt>
+        <dt><code>next(<var>table</var>);</code></dt>
+        <dt><code>next(pipeline=<var>pipeline</var>, table=<var>table</var>);</code></dt>
         <dd>
-          Executes the next logical datapath table as a subroutine.
+          Executes the given logical datapath <var>table</var> in
+          <var>pipeline</var> as a subroutine.  The default <var>table</var> is
+          just after the current one.  If <var>pipeline</var> is specified, it
+          may be <code>ingress</code> or <code>egress</code>; the default
+          <var>pipeline</var> is the one currently executing.  Actions in the
+          ingress pipeline may not use <code>next</code> to jump into the
+          egress pipeline (use the <code>output</code> instead), but
+          transitions in the opposite direction are allowed.
         </dd>
 
         <dt><code><var>field</var> = <var>constant</var>;</code></dt>
         <dd>
           <p>
-           Sets data or metadata field <var>field</var> to constant value
-           <var>constant</var>, e.g. <code>outport = "vif0";</code> to set the
-           logical output port.  To set only a subset of bits in a field,
-           specify a subfield for <var>field</var> or a masked
-           <var>constant</var>, e.g. one may use <code>vlan.pcp[2] = 1;</code>
-           or <code>vlan.pcp = 4/4;</code> to set the most sigificant bit of
-           the VLAN PCP.
+            Sets data or metadata field <var>field</var> to constant value
+            <var>constant</var>, e.g. <code>outport = "vif0";</code> to set the
+            logical output port.  To set only a subset of bits in a field,
+            specify a subfield for <var>field</var> or a masked
+            <var>constant</var>, e.g. one may use <code>vlan.pcp[2] = 1;</code>
+            or <code>vlan.pcp = 4/4;</code> to set the most sigificant bit of
+            the VLAN PCP.
           </p>
 
           <p>
             <code>ingress</code> pipeline but not in the <code>egress</code>
             pipeline.
           </p>
-       </dd>
-      </dl>
-
-      <p>
-        The following actions will likely be useful later, but they have not
-        been thought out carefully.
-      </p>
+        </dd>
 
-      <dl>
         <dt><code><var>field1</var> = <var>field2</var>;</code></dt>
         <dd>
-          Extends the assignment action to allow copying between fields.
-        </dd>
+          <p>
+            Sets data or metadata field <var>field1</var> to the value of data
+            or metadata field <var>field2</var>, e.g. <code>reg0 =
+            ip4.src;</code> copies <code>ip4.src</code> into <code>reg0</code>.
+            To modify only a subset of a field's bits, specify a subfield for
+            <var>field1</var> or <var>field2</var> or both, e.g. <code>vlan.pcp
+            = reg0[0..2];</code> copies the least-significant bits of
+            <code>reg0</code> into the VLAN PCP.
+          </p>
 
-        <dt><code>learn</code></dt>
+          <p>
+            <var>field1</var> and <var>field2</var> must be the same type,
+            either both string or both integer fields.  If they are both
+            integer fields, they must have the same width.
+          </p>
 
-        <dt><code>conntrack</code></dt>
+          <p>
+            If <var>field1</var> or <var>field2</var> has prerequisites, they
+            are added implicitly to <ref column="match"/>.  It is possible to
+            write an assignment with contradictory prerequisites, such as
+            <code>ip4.src = ip6.src[0..31];</code>, but the contradiction means
+            that a logical flow with such an assignment will never be matched.
+          </p>
+        </dd>
 
-        <dt><code>dec_ttl { <var>action</var>, </code>...<code> } { <var>action</var>; </code>...<code>};</code></dt>
+        <dt><code><var>field1</var> &lt;-&gt; <var>field2</var>;</code></dt>
         <dd>
-          decrement TTL; execute first set of actions if
-          successful, second set if TTL decrement fails
+          <p>
+            Similar to <code><var>field1</var> = <var>field2</var>;</code>
+            except that the two values are exchanged instead of copied.  Both
+            <var>field1</var> and <var>field2</var> must modifiable.
+          </p>
         </dd>
 
-        <dt><code>icmp_reply { <var>action</var>, </code>...<code> };</code></dt>
-        <dd>generate ICMP reply from packet, execute <var>action</var>s</dd>
-
-        <dt><code>arp { <var>action</var>, </code>...<code> }</code></dt>
-        <dd>generate ARP from packet, execute <var>action</var>s</dd>
-      </dl>
-    </column>
-  </table>
+        <dt><code>ip.ttl--;</code></dt>
+        <dd>
+          <p>
+            Decrements the IPv4 or IPv6 TTL.  If this would make the TTL zero
+            or negative, then processing of the packet halts; no further
+            actions are processed.  (To properly handle such cases, a
+            higher-priority flow should match on
+            <code>ip.ttl == {0, 1};</code>.)
+          </p>
 
-  <table name="Multicast_Group" title="Logical Port Multicast Groups">
-    <p>
-      The rows in this table define multicast groups of logical ports.
-      Multicast groups allow a single packet transmitted over a tunnel to a
-      hypervisor to be delivered to multiple VMs on that hypervisor, which
-      uses bandwidth more efficiently.
-    </p>
+          <p><b>Prerequisite:</b> <code>ip</code></p>
+        </dd>
 
-    <p>
-      Each row in this table defines a logical multicast group numbered <ref
-      column="tunnel_key"/> within <ref column="datapath"/>, whose logical
-      ports are listed in the <ref column="ports"/> column.
-    </p>
+        <dt><code>ct_next;</code></dt>
+        <dd>
+          <p>
+            Apply connection tracking to the flow, initializing
+            <code>ct_state</code> for matching in later tables.
+            Automatically moves on to the next table, as if followed by
+            <code>next</code>.
+          </p>
 
-    <column name="datapath">
-      The logical datapath in which the multicast group resides.
-    </column>
+          <p>
+            As a side effect, IP fragments will be reassembled for matching.
+            If a fragmented packet is output, then it will be sent with any
+            overlapping fragments squashed.  The connection tracking state is
+            scoped by the logical port when the action is used in a flow for
+            a logical switch, so overlapping addresses may be used.  To allow
+            traffic related to the matched flow, execute <code>ct_commit
+            </code>.  Connection tracking state is scoped by the logical
+            topology when the action is used in a flow for a router.
+          </p>
 
-    <column name="tunnel_key">
-      The value used to designate this logical egress port in tunnel
-      encapsulations.  An index forces the key to be unique within the <ref
-      column="datapath"/>.  The unusual range ensures that multicast group IDs
-      do not overlap with logical port IDs.
-    </column>
+          <p>
+            It is possible to have actions follow <code>ct_next</code>,
+            but they will not have access to any of its side-effects and
+            is not generally useful.
+          </p>
+        </dd>
 
-    <column name="name">
-      <p>
-        The logical multicast group's name.  An index forces the name to be
-        unique within the <ref column="datapath"/>.  Logical flows in the
-        ingress pipeline may output to the group just as for individual logical
-        ports, by assigning the group's name to <code>outport</code> and
-        executing an <code>output</code> action.
-      </p>
+        <dt><code>ct_commit;</code></dt>
+        <dt><code>ct_commit(ct_mark=<var>value[/mask]</var>);</code></dt>
+        <dt><code>ct_commit(ct_label=<var>value[/mask]</var>);</code></dt>
+        <dt><code>ct_commit(ct_mark=<var>value[/mask]</var>, ct_label=<var>value[/mask]</var>);</code></dt>
+        <dd>
+          <p>
+            Commit the flow to the connection tracking entry associated with it
+            by a previous call to <code>ct_next</code>.  When
+            <code>ct_mark=<var>value[/mask]</var></code> and/or
+            <code>ct_label=<var>value[/mask]</var></code> are supplied,
+            <code>ct_mark</code> and/or <code>ct_label</code> will be set to the
+            values indicated by <var>value[/mask]</var> on the connection
+            tracking entry. <code>ct_mark</code> is a 32-bit field.
+            <code>ct_label</code> is a 128-bit field. The <var>value[/mask]</var>
+            should be specified in hex string if more than 64bits are to be used.
+          </p>
 
-      <p>
-        Multicast group names and logical port names share a single namespace
-        and thus should not overlap (but the database schema cannot enforce
-        this).  To try to avoid conflicts, <code>ovn-northd</code> uses names
-        that begin with <code>_MC_</code>.
-      </p>
-    </column>
+          <p>
+            Note that if you want processing to continue in the next table,
+            you must execute the <code>next</code> action after
+            <code>ct_commit</code>.  You may also leave out <code>next</code>
+            which will commit connection tracking state, and then drop the
+            packet.  This could be useful for setting <code>ct_mark</code>
+            on a connection tracking entry before dropping a packet,
+            for example.
+          </p>
+        </dd>
 
-    <column name="ports">
-      The logical ports included in the multicast group.  All of these ports
-      must be in the <ref column="datapath"/> logical datapath (but the
-      database schema cannot enforce this).
-    </column>
-  </table>
+        <dt><code>ct_dnat;</code></dt>
+        <dt><code>ct_dnat(<var>IP</var>);</code></dt>
+        <dd>
+          <p>
+            <code>ct_dnat</code> sends the packet through the DNAT zone in
+            connection tracking table to unDNAT any packet that was DNATed in
+            the opposite direction.  The packet is then automatically sent to
+            to the next tables as if followed by <code>next;</code> action.
+            The next tables will see the changes in the packet caused by
+            the connection tracker.
+          </p>
+          <p>
+            <code>ct_dnat(<var>IP</var>)</code> sends the packet through the
+            DNAT zone to change the destination IP address of the packet to
+            the one provided inside the parentheses and commits the connection.
+            The packet is then automatically sent to the next tables as if
+            followed by <code>next;</code> action.  The next tables will see
+            the changes in the packet caused by the connection tracker.
+          </p>
+        </dd>
 
-  <table name="Datapath_Binding" title="Physical-Logical Datapath Bindings">
-    <p>
-      Each row in this table identifies physical bindings of a logical
-      datapath.  A logical datapath implements a logical pipeline among the
-      ports in the <ref table="Port_Binding"/> table associated with it.  In
-      practice, the pipeline in a given logical datapath implements either a
-      logical switch or a logical router.
-    </p>
+        <dt><code>ct_snat;</code></dt>
+        <dt><code>ct_snat(<var>IP</var>);</code></dt>
+        <dd>
+          <p>
+            <code>ct_snat</code> sends the packet through the SNAT zone to
+            unSNAT any packet that was SNATed in the opposite direction.  The
+            behavior on gateway routers differs from the behavior on a
+            distributed router:
+          </p>
+          <ul>
+            <li>
+              On a gateway router, if the packet needs to be sent to the next
+              tables, then it should be followed by a <code>next;</code>
+              action.  The next tables will not see the changes in the packet
+              caused by the connection tracker.
+            </li>
+            <li>
+              On a distributed router, if the connection tracker finds a
+              connection that was SNATed in the opposite direction, then the
+              destination IP address of the packet is UNSNATed.  The packet is
+              automatically sent to the next tables as if followed by the
+              <code>next;</code> action.  The next tables will see the changes
+              in the packet caused by the connection tracker.
+            </li>
+          </ul>
+          <p>
+            <code>ct_snat(<var>IP</var>)</code> sends the packet through the
+            SNAT zone to change the source IP address of the packet to
+            the one provided inside the parenthesis and commits the connection.
+            The packet is then automatically sent to the next tables as if
+            followed by <code>next;</code> action.  The next tables will see the
+            changes in the packet caused by the connection tracker.
+          </p>
+        </dd>
 
-    <column name="tunnel_key">
-      The tunnel key value to which the logical datapath is bound.
-      The <code>Tunnel Encapsulation</code> section in
-      <code>ovn-architecture</code>(7) describes how tunnel keys are
-      constructed for each supported encapsulation.
-    </column>
+        <dt><code>ct_clear;</code></dt>
+        <dd>
+          Clears connection tracking state.
+        </dd>
 
-    <column name="external_ids" key="logical-switch" type='{"type": "uuid"}'>
-      Each row in <ref table="Datapath_Binding"/> is associated with some
-      logical datapath.  <code>ovn-northd</code> uses this key to store the
-      UUID of the logical datapath <ref table="Logical_Switch"
-      db="OVN_Northbound"/> row in the <ref db="OVN_Northbound"/> database.
-    </column>
+        <dt><code>clone { <var>action</var>; </code>...<code> };</code></dt>
+        <dd>
+          Makes a copy of the packet being processed and executes each
+          <code>action</code> on the copy.  Actions following the
+          <var>clone</var> action, if any, apply to the original, unmodified
+          packet.  This can be used as a way to ``save and restore'' the packet
+          around a set of actions that may modify it and should not persist.
+        </dd>
 
-    <group title="Common Columns">
-      The overall purpose of these columns is described under <code>Common
-      Columns</code> at the beginning of this document.
+        <dt><code>arp { <var>action</var>; </code>...<code> };</code></dt>
+        <dd>
+          <p>
+            Temporarily replaces the IPv4 packet being processed by an ARP
+            packet and executes each nested <var>action</var> on the ARP
+            packet.  Actions following the <var>arp</var> action, if any, apply
+            to the original, unmodified packet.
+          </p>
 
-      <column name="external_ids"/>
-    </group>
-  </table>
+          <p>
+            The ARP packet that this action operates on is initialized based on
+            the IPv4 packet being processed, as follows.  These are default
+            values that the nested actions will probably want to change:
+          </p>
 
-  <table name="Port_Binding" title="Physical-Logical Port Bindings">
-    <p>
-      Each row in this table identifies the physical location of a logical
-      port.
-    </p>
+          <ul>
+            <li><code>eth.src</code> unchanged</li>
+            <li><code>eth.dst</code> unchanged</li>
+            <li><code>eth.type = 0x0806</code></li>
+            <li><code>arp.op = 1</code> (ARP request)</li>
+            <li><code>arp.sha</code> copied from <code>eth.src</code></li>
+            <li><code>arp.spa</code> copied from <code>ip4.src</code></li>
+            <li><code>arp.tha = 00:00:00:00:00:00</code></li>
+            <li><code>arp.tpa</code> copied from <code>ip4.dst</code></li>
+          </ul>
 
-    <p>
-      For every <code>Logical_Port</code> record in <code>OVN_Northbound</code>
-      database, <code>ovn-northd</code> creates a record in this table.
-      <code>ovn-northd</code> populates and maintains every column except
-      the <code>chassis</code> column, which it leaves empty in new records.
-    </p>
+          <p>
+            The ARP packet has the same VLAN header, if any, as the IP packet
+            it replaces.
+          </p>
 
-    <p>
-      <code>ovn-controller</code> populates the <code>chassis</code> column
-      for the records that identify the logical ports that are located on its
-      hypervisor, which <code>ovn-controller</code> in turn finds out by
-      monitoring the local hypervisor's Open_vSwitch database, which
-      identifies logical ports via the conventions described in
-      <code>IntegrationGuide.md</code>.
-    </p>
+          <p><b>Prerequisite:</b> <code>ip4</code></p>
+        </dd>
 
-    <p>
-      When a chassis shuts down gracefully, it should clean up the
-      <code>chassis</code> column that it previously had populated.
-      (This is not critical because resources hosted on the chassis are equally
-      unreachable regardless of whether their rows are present.)  To handle the
-      case where a VM is shut down abruptly on one chassis, then brought up
-      again on a different one, <code>ovn-controller</code> must overwrite the
-      <code>chassis</code> column with new information.
-    </p>
+        <dt><code>get_arp(<var>P</var>, <var>A</var>);</code></dt>
 
-    <column name="datapath">
-      The logical datapath to which the logical port belongs.
-    </column>
+        <dd>
+          <p>
+            <b>Parameters</b>: logical port string field <var>P</var>, 32-bit
+            IP address field <var>A</var>.
+          </p>
 
-    <column name="logical_port">
-      A logical port, taken from <ref table="Logical_Port" column="name"
-      db="OVN_Northbound"/> in the OVN_Northbound database's
-      <ref table="Logical_Port" db="OVN_Northbound"/> table.  OVN does not
-      prescribe a particular format for the logical port ID.
-    </column>
+          <p>
+            Looks up <var>A</var> in <var>P</var>'s mac binding table.
+            If an entry is found, stores its Ethernet address in
+            <code>eth.dst</code>, otherwise stores
+            <code>00:00:00:00:00:00</code> in <code>eth.dst</code>.
+          </p>
 
-    <column name="type">
-      <p>
-      A type for this logical port.  Logical ports can be used to model
-      other types of connectivity into an OVN logical switch.  Leaving this column
-      blank maintains the default logical port behavior.
-      </p>
+          <p><b>Example:</b> <code>get_arp(outport, ip4.dst);</code></p>
+        </dd>
 
-      <p>
-      There are no other logical port types implemented yet.
-      </p>
-    </column>
+        <dt>
+          <code>put_arp(<var>P</var>, <var>A</var>, <var>E</var>);</code>
+        </dt>
 
-    <column name="options">
-        This column provides key/value settings specific to the logical port
-        <ref column="type"/>.
-    </column>
+        <dd>
+          <p>
+            <b>Parameters</b>: logical port string field <var>P</var>, 32-bit
+            IP address field <var>A</var>, 48-bit Ethernet address field
+            <var>E</var>.
+          </p>
 
-    <column name="tunnel_key">
-      <p>
-        A number that represents the logical port in the key (e.g. STT key or
-        Geneve TLV) field carried within tunnel protocol packets.
-      </p>
+          <p>
+            Adds or updates the entry for IP address <var>A</var> in
+            logical port <var>P</var>'s mac binding table, setting its
+            Ethernet address to <var>E</var>.
+          </p>
 
-      <p>
-        The tunnel ID must be unique within the scope of a logical datapath.
-      </p>
-    </column>
+          <p><b>Example:</b> <code>put_arp(inport, arp.spa, arp.sha);</code></p>
+        </dd>
 
-    <column name="parent_port">
-      For containers created inside a VM, this is taken from
-      <ref table="Logical_Port" column="parent_name" db="OVN_Northbound"/>
-      in the OVN_Northbound database's <ref table="Logical_Port"
-      db="OVN_Northbound"/> table.  It is left empty if
-      <ref column="logical_port"/> belongs to a VM or a container created
-      in the hypervisor.
-    </column>
+        <dt>
+          <code>nd_na { <var>action</var>; </code>...<code> };</code>
+        </dt>
 
-    <column name="tag">
-      When <ref column="logical_port"/> identifies the interface of a container
-      spawned inside a VM, this column identifies the VLAN tag in
-      the network traffic associated with that container's network interface.
-      It is left empty if <ref column="logical_port"/> belongs to a VM or a
-      container created in the hypervisor.
-    </column>
+        <dd>
+          <p>
+            Temporarily replaces the IPv6 neighbor solicitation packet
+            being processed by an IPv6 neighbor advertisement (NA)
+            packet and executes each nested <var>action</var> on the NA
+            packet.  Actions following the <code>nd_na</code> action,
+            if any, apply to the original, unmodified packet.
+          </p>
+
+          <p>
+            The NA packet that this action operates on is initialized based on
+            the IPv6 packet being processed, as follows. These are default
+            values that the nested actions will probably want to change:
+          </p>
+
+          <ul>
+            <li><code>eth.dst</code> exchanged with <code>eth.src</code></li>
+            <li><code>eth.type = 0x86dd</code></li>
+            <li><code>ip6.dst</code> copied from <code>ip6.src</code></li>
+            <li><code>ip6.src</code> copied from <code>nd.target</code></li>
+            <li><code>icmp6.type = 136</code> (Neighbor Advertisement)</li>
+            <li><code>nd.target</code> unchanged</li>
+            <li><code>nd.sll = 00:00:00:00:00:00</code></li>
+            <li><code>nd.tll</code> copied from <code>eth.dst</code></li>
+          </ul>
+
+          <p>
+            The ND packet has the same VLAN header, if any, as the IPv6 packet
+            it replaces.
+          </p>
+
+          <p>
+            <b>Prerequisite:</b> <code>nd_ns</code>
+          </p>
+        </dd>
+
+        <dt><code>get_nd(<var>P</var>, <var>A</var>);</code></dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: logical port string field <var>P</var>, 128-bit
+            IPv6 address field <var>A</var>.
+          </p>
+
+          <p>
+            Looks up <var>A</var> in <var>P</var>'s mac binding table.
+            If an entry is found, stores its Ethernet address in
+            <code>eth.dst</code>, otherwise stores
+            <code>00:00:00:00:00:00</code> in <code>eth.dst</code>.
+          </p>
+
+          <p><b>Example:</b> <code>get_nd(outport, ip6.dst);</code></p>
+        </dd>
+
+        <dt>
+          <code>put_nd(<var>P</var>, <var>A</var>, <var>E</var>);</code>
+        </dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: logical port string field <var>P</var>,
+            128-bit IPv6 address field <var>A</var>, 48-bit Ethernet
+            address field <var>E</var>.
+          </p>
+
+          <p>
+            Adds or updates the entry for IPv6 address <var>A</var> in
+            logical port <var>P</var>'s mac binding table, setting its
+            Ethernet address to <var>E</var>.
+          </p>
+
+          <p><b>Example:</b> <code>put_nd(inport, nd.target, nd.tll);</code></p>
+        </dd>
+
+        <dt>
+          <code><var>R</var> = put_dhcp_opts(<var>D1</var> = <var>V1</var>, <var>D2</var> = <var>V2</var>, ..., <var>Dn</var> = <var>Vn</var>);</code>
+        </dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: one or more DHCP option/value pairs, which must
+            include an <code>offerip</code> option (with code 0).
+          </p>
+
+          <p>
+            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
+          </p>
+
+          <p>
+            Valid only in the ingress pipeline.
+          </p>
+
+          <p>
+            When this action is applied to a DHCP request packet (DHCPDISCOVER
+            or DHCPREQUEST), it changes the packet into a DHCP reply (DHCPOFFER
+            or DHCPACK, respectively), replaces the options by those specified
+            as parameters, and stores 1 in <var>R</var>.
+          </p>
+
+          <p>
+            When this action is applied to a non-DHCP packet or a DHCP packet
+            that is not DHCPDISCOVER or DHCPREQUEST, it leaves the packet
+            unchanged and stores 0 in <var>R</var>.
+          </p>
+
+          <p>
+            The contents of the <ref table="DHCP_Option"/> table control the
+            DHCP option names and values that this action supports.
+          </p>
+
+          <p>
+            <b>Example:</b>
+            <code>
+              reg0[0] = put_dhcp_opts(offerip = 10.0.0.2, router = 10.0.0.1,
+              netmask = 255.255.255.0, dns_server = {8.8.8.8, 7.7.7.7});
+            </code>
+          </p>
+        </dd>
+
+        <dt>
+          <code><var>R</var> = put_dhcpv6_opts(<var>D1</var> = <var>V1</var>, <var>D2</var> = <var>V2</var>, ..., <var>Dn</var> = <var>Vn</var>);</code>
+        </dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: one or more DHCPv6 option/value pairs.
+          </p>
+
+          <p>
+            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
+          </p>
+
+          <p>
+            Valid only in the ingress pipeline.
+          </p>
+
+          <p>
+            When this action is applied to a DHCPv6 request packet, it changes
+            the packet into a DHCPv6 reply, replaces the options by those
+            specified as parameters, and stores 1 in <var>R</var>.
+          </p>
+
+          <p>
+            When this action is applied to a non-DHCPv6 packet or an invalid
+            DHCPv6 request packet , it leaves the packet unchanged and stores
+            0 in <var>R</var>.
+          </p>
+
+          <p>
+            The contents of the <ref table="DHCPv6_Options"/> table control the
+            DHCPv6 option names and values that this action supports.
+          </p>
+
+          <p>
+            <b>Example:</b>
+            <code>
+              reg0[3] = put_dhcpv6_opts(ia_addr = aef0::4, server_id = 00:00:00:00:10:02,
+              dns_server={ae70::1,ae70::2});
+            </code>
+          </p>
+        </dd>
+
+        <dt>
+          <code>set_queue(<var>queue_number</var>);</code>
+        </dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: Queue number <var>queue_number</var>, in the range 0 to 61440.
+          </p>
+
+          <p>
+            This is a logical equivalent of the OpenFlow <code>set_queue</code>
+            action.  It affects packets that egress a hypervisor through a
+            physical interface.  For nonzero <var>queue_number</var>, it
+            configures packet queuing to match the settings configured for the
+            <ref table="Port_Binding"/> with
+            <code>options:qdisc_queue_id</code> matching
+            <var>queue_number</var>.  When <var>queue_number</var> is zero, it
+            resets queuing to the default strategy.
+          </p>
+
+          <p><b>Example:</b> <code>set_queue(10);</code></p>
+        </dd>
+
+        <dt><code>ct_lb;</code></dt>
+        <dt><code>ct_lb(</code><var>ip</var>[<code>:</code><var>port</var>]...<code>);</code></dt>
+        <dd>
+          <p>
+            With one or more arguments, <code>ct_lb</code> commits the packet
+            to the connection tracking table and DNATs the packet's destination
+            IP address (and port) to the IP address or addresses (and optional
+            ports) specified in the string.  If multiple comma-separated IP
+            addresses are specified, each is given equal weight for picking the
+            DNAT address.  Processing automatically moves on to the next table,
+            as if <code>next;</code> were specified, and later tables act on
+            the packet as modified by the connection tracker.  Connection
+            tracking state is scoped by the logical port when the action is
+            used in a flow for a logical switch, so overlapping
+            addresses may be used.  Connection tracking state is scoped by the
+            logical topology when the action is used in a flow for a router.
+          </p>
+          <p>
+            Without arguments, <code>ct_lb</code> sends the packet to the
+            connection tracking table to NAT the packets.  If the packet is
+            part of an established connection that was previously committed to
+            the connection tracker via <code>ct_lb(</code>...<code>)</code>, it
+            will automatically get DNATed to the same IP address as the first
+            packet in that connection.
+          </p>
+        </dd>
+
+        <dt>
+          <code><var>R</var> = dns_lookup();</code>
+        </dt>
+
+        <dd>
+          <p>
+            <b>Parameters</b>: No parameters.
+          </p>
+
+          <p>
+            <b>Result</b>: stored to a 1-bit subfield <var>R</var>.
+          </p>
+
+          <p>
+            Valid only in the ingress pipeline.
+          </p>
+
+          <p>
+            When this action is applied to a valid DNS request (a UDP packet
+            typically directed to port 53), it attempts to resolve the query
+            using the contents of the <ref table="DNS"/> table.  If it is
+            successful, it changes the packet into a DNS reply and stores 1 in
+            <var>R</var>.  If the action is applied to a non-DNS packet, an
+            invalid DNS request packet, or a valid DNS request for which the
+            <ref table="DNS"/> table does not supply an answer, it leaves the
+            packet unchanged and stores 0 in <var>R</var>.
+          </p>
+
+          <p>
+            Regardless of success, the action does not make any of the changes
+            to the flow that are necessary to direct the packet back to the
+            requester.  The logical pipeline can implement this behavior with
+            matches and actions in later tables.
+          </p>
+
+          <p>
+            <b>Example:</b>
+            <code>
+              reg0[3] = dns_lookup();
+            </code>
+          </p>
+
+          <p>
+            <b>Prerequisite:</b> <code>udp</code>
+          </p>
+        </dd>
+      </dl>
+
+      <dl>
+        <dt>
+          <code>log(<var>key</var>=<var>value</var>, </code>...<code>);</code>
+        </dt>
+
+        <dd>
+          <p>
+            Causes <code>ovn-controller</code> to log the packet on the chassis
+            that processes it.  Packet logging currently uses the same logging
+            mechanism as other Open vSwitch and OVN messages, which means that
+            whether and where log messages appear depends on the local logging
+            configuration that can be configured with <code>ovs-appctl</code>,
+            etc.
+          </p>
+          <p>
+            The <code>log</code> action takes zero or more of the following
+            key-value pair arguments that control what is logged:
+          </p>
+          <dl>
+            <dt><code>name=</code><var>string</var></dt>
+            <dd>
+              An optional name for the ACL.  The <var>string</var> is
+              currently limited to 64 bytes.
+            </dd>
+            <dt><code>severity=</code><var>level</var></dt>
+            <dd>
+              Indicates the severity of the event.  The <var>level</var> is one
+              of following (from more to less serious): <code>alert</code>,
+              <code>warning</code>, <code>notice</code>, <code>info</code>, or
+              <code>debug</code>.  If a severity is not provided, the default
+              is <code>info</code>.
+            </dd>
+            <dt><code>verdict=</code><var>value</var></dt>
+            <dd>
+              The verdict for packets matching the flow.  The value must be one
+              of <code>allow</code>, <code>deny</code>, or <code>reject</code>.
+            </dd>
+          </dl>
+        </dd>
+      </dl>
+
+      <p>
+        The following actions will likely be useful later, but they have not
+        been thought out carefully.
+      </p>
+
+      <dl>
+        <dt><code>icmp4 { <var>action</var>; </code>...<code> };</code></dt>
+        <dd>
+          <p>
+            Temporarily replaces the IPv4 packet being processed by an ICMPv4
+            packet and executes each nested <var>action</var> on the ICMPv4
+            packet.  Actions following the <var>icmp4</var> action, if any,
+            apply to the original, unmodified packet.
+          </p>
+
+          <p>
+            The ICMPv4 packet that this action operates on is initialized based
+            on the IPv4 packet being processed, as follows.  These are default
+            values that the nested actions will probably want to change.
+            Ethernet and IPv4 fields not listed here are not changed:
+          </p>
+
+          <ul>
+            <li><code>ip.proto = 1</code> (ICMPv4)</li>
+            <li><code>ip.frag = 0</code> (not a fragment)</li>
+            <li><code>icmp4.type = 3</code> (destination unreachable)</li>
+            <li><code>icmp4.code = 1</code> (host unreachable)</li>
+          </ul>
+
+          <p>
+            Details TBD.
+          </p>
+
+          <p><b>Prerequisite:</b> <code>ip4</code></p>
+        </dd>
+
+        <dt><code>tcp_reset;</code></dt>
+        <dd>
+          <p>
+            This action transforms the current TCP packet according to the
+            following pseudocode:
+          </p>
+
+          <pre>
+if (tcp.ack) {
+        tcp.seq = tcp.ack;
+} else {
+        tcp.ack = tcp.seq + length(tcp.payload);
+        tcp.seq = 0;
+}
+tcp.flags = RST;
+</pre>
+
+          <p>
+            Then, the action drops all TCP options and payload data, and
+            updates the TCP checksum.
+          </p>
+
+          <p>
+            Details TBD.
+          </p>
+
+          <p><b>Prerequisite:</b> <code>tcp</code></p>
+        </dd>
+      </dl>
+    </column>
+
+    <column name="external_ids" key="stage-name">
+      Human-readable name for this flow's stage in the pipeline.
+    </column>
+
+    <column name="external_ids" key="stage-hint" type='{"type": "uuid"}'>
+      UUID of a <ref db="OVN_Northbound"/> record that caused this logical flow
+      to be created.  Currently used only for attribute of logical flows to
+      northbound <ref db="OVN_Northbound" table="ACL"/> records.
+    </column>
+
+    <column name="external_ids" key="source">
+      Source file and line number of the code that added this flow to the
+      pipeline.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+
+  <table name="Multicast_Group" title="Logical Port Multicast Groups">
+    <p>
+      The rows in this table define multicast groups of logical ports.
+      Multicast groups allow a single packet transmitted over a tunnel to a
+      hypervisor to be delivered to multiple VMs on that hypervisor, which
+      uses bandwidth more efficiently.
+    </p>
+
+    <p>
+      Each row in this table defines a logical multicast group numbered <ref
+      column="tunnel_key"/> within <ref column="datapath"/>, whose logical
+      ports are listed in the <ref column="ports"/> column.
+    </p>
+
+    <column name="datapath">
+      The logical datapath in which the multicast group resides.
+    </column>
+
+    <column name="tunnel_key">
+      The value used to designate this logical egress port in tunnel
+      encapsulations.  An index forces the key to be unique within the <ref
+      column="datapath"/>.  The unusual range ensures that multicast group IDs
+      do not overlap with logical port IDs.
+    </column>
+
+    <column name="name">
+      <p>
+        The logical multicast group's name.  An index forces the name to be
+        unique within the <ref column="datapath"/>.  Logical flows in the
+        ingress pipeline may output to the group just as for individual logical
+        ports, by assigning the group's name to <code>outport</code> and
+        executing an <code>output</code> action.
+      </p>
+
+      <p>
+        Multicast group names and logical port names share a single namespace
+        and thus should not overlap (but the database schema cannot enforce
+        this).  To try to avoid conflicts, <code>ovn-northd</code> uses names
+        that begin with <code>_MC_</code>.
+      </p>
+    </column>
+
+    <column name="ports">
+      The logical ports included in the multicast group.  All of these ports
+      must be in the <ref column="datapath"/> logical datapath (but the
+      database schema cannot enforce this).
+    </column>
+  </table>
+
+  <table name="Datapath_Binding" title="Physical-Logical Datapath Bindings">
+    <p>
+      Each row in this table represents a logical datapath, which implements a
+      logical pipeline among the ports in the <ref table="Port_Binding"/> table
+      associated with it.  In practice, the pipeline in a given logical
+      datapath implements either a logical switch or a logical router.
+    </p>
+
+    <p>
+      The main purpose of a row in this table is provide a physical binding for
+      a logical datapath.  A logical datapath does not have a physical
+      location, so its physical binding information is limited: just <ref
+      column="tunnel_key"/>.  The rest of the data in this table does not
+      affect packet forwarding.
+    </p>
+
+    <column name="tunnel_key">
+      The tunnel key value to which the logical datapath is bound.
+      The <code>Tunnel Encapsulation</code> section in
+      <code>ovn-architecture</code>(7) describes how tunnel keys are
+      constructed for each supported encapsulation.
+    </column>
+
+    <group title="OVN_Northbound Relationship">
+      <p>
+        Each row in <ref table="Datapath_Binding"/> is associated with some
+        logical datapath.  <code>ovn-northd</code> uses these keys to track the
+        association of a logical datapath with concepts in the <ref
+        db="OVN_Northbound"/> database.
+      </p>
+
+      <column name="external_ids" key="logical-switch" type='{"type": "uuid"}'>
+        For a logical datapath that represents a logical switch,
+        <code>ovn-northd</code> stores in this key the UUID of the
+        corresponding <ref table="Logical_Switch" db="OVN_Northbound"/> row in
+        the <ref db="OVN_Northbound"/> database.
+      </column>
+
+      <column name="external_ids" key="logical-router" type='{"type": "uuid"}'>
+        For a logical datapath that represents a logical router,
+        <code>ovn-northd</code> stores in this key the UUID of the
+        corresponding <ref table="Logical_Router" db="OVN_Northbound"/> row in
+        the <ref db="OVN_Northbound"/> database.
+      </column>
+
+      <group title="Naming">
+        <p>
+          <code>ovn-northd</code> copies these from the name fields in the <ref
+          db="OVN_Northbound"/> database, either from <ref
+          table="Logical_Router" db="OVN_Northbound" column="name"/> and <ref
+          table="Logical_Router" db="OVN_Northbound" column="external_ids"
+          key="neutron:router_name"/> in the <ref table="Logical_Router"
+          db="OVN_Northbound"/> table or from <ref table="Logical_Switch"
+          db="OVN_Northbound" column="name"/> and <ref table="Logical_Switch"
+          db="OVN_Northbound" column="external_ids"
+          key="neutron:network_name"/> in the <ref table="Logical_Switch"
+          db="OVN_Northbound"/> table.
+        </p>
+
+        <column name="external_ids" key="name">
+          A name for the logical datapath.
+        </column>
+
+        <column name="external_ids" key="name2">
+          Another name for the logical datapath.
+        </column>
+      </group>
+    </group>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+
+  <table name="Port_Binding" title="Physical-Logical Port Bindings">
+    <p>
+      Each row in this table binds a logical port to a realization.  For most
+      logical ports, this means binding to some physical location, for example
+      by binding a logical port to a VIF that belongs to a VM running on a
+      particular hypervisor.  Other logical ports, such as logical patch ports,
+      can be realized without a specific physical location, but their bindings
+      are still expressed through rows in this table.
+    </p>
+
+    <p>
+      For every <code>Logical_Switch_Port</code> record in
+      <code>OVN_Northbound</code> database, <code>ovn-northd</code>
+      creates a record in this table.  <code>ovn-northd</code> populates
+      and maintains every column except the <code>chassis</code> column,
+      which it leaves empty in new records.
+    </p>
+
+    <p>
+      <code>ovn-controller</code>/<code>ovn-controller-vtep</code>
+      populates the <code>chassis</code> column for the records that
+      identify the logical ports that are located on its hypervisor/gateway,
+      which <code>ovn-controller</code>/<code>ovn-controller-vtep</code> in
+      turn finds out by monitoring the local hypervisor's Open_vSwitch
+      database, which identifies logical ports via the conventions described
+      in <code>IntegrationGuide.rst</code>.  (The exceptions are for
+      <code>Port_Binding</code> records with <code>type</code> of
+      <code>l3gateway</code>, whose locations are identified by
+      <code>ovn-northd</code> via the <code>options:l3gateway-chassis</code>
+      column in this table.  <code>ovn-controller</code> is still responsible
+      to populate the <code>chassis</code> column.)
+    </p>
+
+    <p>
+      When a chassis shuts down gracefully, it should clean up the
+      <code>chassis</code> column that it previously had populated.
+      (This is not critical because resources hosted on the chassis are equally
+      unreachable regardless of whether their rows are present.)  To handle the
+      case where a VM is shut down abruptly on one chassis, then brought up
+      again on a different one,
+      <code>ovn-controller</code>/<code>ovn-controller-vtep</code> must
+      overwrite the <code>chassis</code> column with new information.
+    </p>
+
+    <group title="Core Features">
+      <column name="datapath">
+        The logical datapath to which the logical port belongs.
+      </column>
+
+      <column name="logical_port">
+        A logical port, taken from <ref table="Logical_Switch_Port"
+        column="name" db="OVN_Northbound"/> in the OVN_Northbound
+        database's <ref table="Logical_Switch_Port" db="OVN_Northbound"/>
+        table.  OVN does not prescribe a particular format for the
+        logical port ID.
+      </column>
+
+      <column name="chassis">
+        The meaning of this column depends on the value of the <ref column="type"/>
+        column.  This is the meaning for each <ref column="type"/>
+
+        <dl>
+          <dt>(empty string)</dt>
+          <dd>
+            The physical location of the logical port.  To successfully identify a
+            chassis, this column must be a <ref table="Chassis"/> record.  This is
+            populated by <code>ovn-controller</code>.
+          </dd>
+
+          <dt>vtep</dt>
+          <dd>
+            The physical location of the hardware_vtep gateway.  To successfully
+            identify a chassis, this column must be a <ref table="Chassis"/> record.
+            This is populated by <code>ovn-controller-vtep</code>.
+          </dd>
+
+          <dt>localnet</dt>
+          <dd>
+            Always empty.  A localnet port is realized on every chassis that has
+            connectivity to the corresponding physical network.
+          </dd>
+
+          <dt>localport</dt>
+          <dd>
+            Always empty.  A localport port is present on every chassis.
+          </dd>
+
+          <dt>l3gateway</dt>
+          <dd>
+            The physical location of the L3 gateway.  To successfully identify a
+            chassis, this column must be a <ref table="Chassis"/> record.  This is
+            populated by <code>ovn-controller</code> based on the value of
+            the <code>options:l3gateway-chassis</code> column in this table.
+          </dd>
+
+          <dt>l2gateway</dt>
+          <dd>
+            The physical location of this L2 gateway.  To successfully identify a
+            chassis, this column must be a <ref table="Chassis"/> record.
+            This is populated by <code>ovn-controller</code> based on the value
+            of the <code>options:l2gateway-chassis</code> column in this table.
+          </dd>
+        </dl>
+
+      </column>
+
+      <column name="gateway_chassis">
+        <p>
+          A list of <ref table="Gateway_Chassis"/>.
+        </p>
+        <p>
+          This should only be populated for ports with
+          <ref column="type"/> set to <code>chassisredirect</code>.
+          This column defines the list of chassis used as gateways where
+          traffic will be redirected through.
+        </p>
+      </column>
+
+      <column name="tunnel_key">
+        <p>
+          A number that represents the logical port in the key (e.g. STT key or
+          Geneve TLV) field carried within tunnel protocol packets.
+        </p>
+
+        <p>
+          The tunnel ID must be unique within the scope of a logical datapath.
+        </p>
+      </column>
+
+      <column name="mac">
+        <p>
+          The Ethernet address or addresses used as a source address on the
+          logical port, each in the form
+          <var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>.
+          The string <code>unknown</code> is also allowed to indicate that the
+          logical port has an unknown set of (additional) source addresses.
+        </p>
+
+        <p>
+          A VM interface would ordinarily have a single Ethernet address.  A
+          gateway port might initially only have <code>unknown</code>, and then
+          add MAC addresses to the set as it learns new source addresses.
+        </p>
+      </column>
+
+      <column name="type">
+        <p>
+          A type for this logical port.  Logical ports can be used to model other
+          types of connectivity into an OVN logical switch.  The following types
+          are defined:
+        </p>
+
+        <dl>
+          <dt>(empty string)</dt>
+          <dd>VM (or VIF) interface.</dd>
+
+          <dt><code>patch</code></dt>
+          <dd>
+            One of a pair of logical ports that act as if connected by a patch
+            cable.  Useful for connecting two logical datapaths, e.g. to connect
+            a logical router to a logical switch or to another logical router.
+          </dd>
+
+          <dt><code>l3gateway</code></dt>
+          <dd>
+            One of a pair of logical ports that act as if connected by a patch
+            cable across multiple chassis.  Useful for connecting a logical
+            switch with a Gateway router (which is only resident on a
+            particular chassis).
+          </dd>
+
+          <dt><code>localnet</code></dt>
+          <dd>
+            A connection to a locally accessible network from each
+            <code>ovn-controller</code> instance.  A logical switch can only
+            have a single <code>localnet</code> port attached.  This is used
+            to model direct connectivity to an existing network.
+          </dd>
+
+          <dt><code>localport</code></dt>
+          <dd>
+            A connection to a local VIF. Traffic that arrives on a
+            <code>localport</code> is never forwarded over a tunnel to another
+            chassis. These ports are present on every chassis and have the same
+            address in all of them. This is used to model connectivity to local
+            services that run on every hypervisor.
+          </dd>
+
+          <dt><code>l2gateway</code></dt>
+          <dd>
+            An L2 connection to a physical network.  The chassis this
+            <ref table="Port_Binding"/> is bound to will serve as
+            an L2 gateway to the network named by
+            <ref column="options" table="Port_Binding"/>:<code>network_name</code>.
+          </dd>
+
+          <dt><code>vtep</code></dt>
+          <dd>
+            A port to a logical switch on a VTEP gateway chassis.  In order to
+            get this port correctly recognized by the OVN controller, the <ref
+            column="options"
+            table="Port_Binding"/>:<code>vtep-physical-switch</code> and <ref
+            column="options"
+            table="Port_Binding"/>:<code>vtep-logical-switch</code> must also
+            be defined.
+          </dd>
+
+          <dt><code>chassisredirect</code></dt>
+          <dd>
+            A logical port that represents a particular instance, bound
+            to a specific chassis, of an otherwise distributed parent
+            port (e.g. of type <code>patch</code>).  A
+            <code>chassisredirect</code> port should never be used as an
+            <code>inport</code>.  When an ingress pipeline sets the
+            <code>outport</code>, it may set the value to a logical port
+            of type <code>chassisredirect</code>.  This will cause the
+            packet to be directed to a specific chassis to carry out the
+            egress pipeline.  At the beginning of the egress pipeline,
+            the <code>outport</code> will be reset to the value of the
+            distributed port.
+          </dd>
+        </dl>
+      </column>
+    </group>
+
+    <group title="Patch Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> of
+        <code>patch</code>.
+      </p>
+
+      <column name="options" key="peer">
+        The <ref column="logical_port"/> in the <ref table="Port_Binding"/>
+        record for the other side of the patch.  The named <ref
+        column="logical_port"/> must specify this <ref column="logical_port"/>
+        in its own <code>peer</code> option.  That is, the two patch logical
+        ports must have reversed <ref column="logical_port"/> and
+        <code>peer</code> values.
+      </column>
+
+      <column name="nat_addresses">
+        MAC address followed by a list of SNAT and DNAT external IP
+        addresses, followed by
+        <code>is_chassis_resident("<var>lport</var>")</code>, where
+        <var>lport</var> is the name of a logical port on the same chassis
+        where the corresponding NAT rules are applied.  This is used to
+        send gratuitous ARPs for SNAT and DNAT external IP addresses via
+        <code>localnet</code>, from the chassis where <var>lport</var>
+        resides.  Example: <code>80:fa:5b:06:72:b7 158.36.44.22
+        158.36.44.24 is_chassis_resident("foo1")</code>.  This would result
+        in generation of gratuitous ARPs for IP addresses 158.36.44.22 and
+        158.36.44.24 with a MAC address of 80:fa:5b:06:72:b7 from the chassis
+        where the logical port "foo1" resides.
+      </column>
+    </group>
+
+    <group title="L3 Gateway Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> of
+        <code>l3gateway</code>.
+      </p>
+
+      <column name="options" key="peer">
+        The <ref column="logical_port"/> in the <ref table="Port_Binding"/>
+        record for the other side of the 'l3gateway' port.  The named <ref
+        column="logical_port"/> must specify this <ref column="logical_port"/>
+        in its own <code>peer</code> option.  That is, the two 'l3gateway'
+        logical ports must have reversed <ref column="logical_port"/> and
+        <code>peer</code> values.
+      </column>
+
+      <column name="options" key="l3gateway-chassis">
+        The <code>chassis</code> in which the port resides.
+      </column>
+
+      <column name="options" key="nat-addresses">
+        MAC address of the <code>l3gateway</code> port followed by a list of
+        SNAT and DNAT external IP addresses.  This is used to send gratuitous
+        ARPs for SNAT and DNAT external IP addresses via <code>localnet</code>.
+        Example: <code>80:fa:5b:06:72:b7 158.36.44.22 158.36.44.24</code>.
+        This would result in generation of gratuitous ARPs for IP addresses
+        158.36.44.22 and 158.36.44.24 with a MAC address of 80:fa:5b:06:72:b7.
+        This is used in OVS versions prior to 2.8.
+      </column>
+
+      <column name="nat_addresses">
+        MAC address of the <code>l3gateway</code> port followed by a list of
+        SNAT and DNAT external IP addresses.  This is used to send gratuitous
+        ARPs for SNAT and DNAT external IP addresses via <code>localnet</code>.
+        Example: <code>80:fa:5b:06:72:b7 158.36.44.22 158.36.44.24</code>.
+        This would result in generation of gratuitous ARPs for IP addresses
+        158.36.44.22 and 158.36.44.24 with a MAC address of 80:fa:5b:06:72:b7.
+        This is used in OVS version 2.8 and later versions.
+      </column>
+    </group>
+
+    <group title="Localnet Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> of
+        <code>localnet</code>.
+      </p>
+
+      <column name="options" key="network_name">
+        Required.  <code>ovn-controller</code> uses the configuration entry
+        <code>ovn-bridge-mappings</code> to determine how to connect to this
+        network.  <code>ovn-bridge-mappings</code> is a list of network names
+        mapped to a local OVS bridge that provides access to that network.  An
+        example of configuring <code>ovn-bridge-mappings</code> would be:
+
+        <pre>$ ovs-vsctl set open . external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1</pre>
+
+        <p>
+          When a logical switch has a <code>localnet</code> port attached,
+          every chassis that may have a local vif attached to that logical
+          switch must have a bridge mapping configured to reach that
+          <code>localnet</code>.  Traffic that arrives on a
+          <code>localnet</code> port is never forwarded over a tunnel to
+          another chassis.
+        </p>
+      </column>
+
+      <column name="tag">
+        If set, indicates that the port represents a connection to a specific
+        VLAN on a locally accessible network. The VLAN ID is used to match
+        incoming traffic and is also added to outgoing traffic.
+      </column>
+    </group>
+
+    <group title="L2 Gateway Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> of
+        <code>l2gateway</code>.
+      </p>
+
+      <column name="options" key="network_name">
+        Required.  <code>ovn-controller</code> uses the configuration entry
+        <code>ovn-bridge-mappings</code> to determine how to connect to this
+        network.  <code>ovn-bridge-mappings</code> is a list of network names
+        mapped to a local OVS bridge that provides access to that network.  An
+        example of configuring <code>ovn-bridge-mappings</code> would be:
+
+        <pre>$ ovs-vsctl set open . external-ids:ovn-bridge-mappings=physnet1:br-eth0,physnet2:br-eth1</pre>
+
+        <p>
+          When a logical switch has a <code>l2gateway</code> port attached,
+          the chassis that the <code>l2gateway</code> port is bound to
+          must have a bridge mapping configured to reach the network
+          identified by <code>network_name</code>.
+        </p>
+      </column>
+
+      <column name="options" key="l2gateway-chassis">
+        Required. The <code>chassis</code> in which the port resides.
+      </column>
+
+      <column name="tag">
+        If set, indicates that the gateway is connected to a specific
+        VLAN on the physical network. The VLAN ID is used to match
+        incoming traffic and is also added to outgoing traffic.
+      </column>
+    </group>
+
+    <group title="VTEP Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> of
+        <code>vtep</code>.
+      </p>
+
+      <column name="options" key="vtep-physical-switch">
+        Required. The name of the VTEP gateway.
+      </column>
+
+      <column name="options" key="vtep-logical-switch">
+        Required.  A logical switch name connected by the VTEP gateway.  Must
+        be set when <ref column="type"/> is <code>vtep</code>.
+      </column>
+    </group>
+
+    <group title="VMI (or VIF) Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/> having
+        (empty string)
+      </p>
+
+      <column name="options" key="qos_max_rate">
+        If set, indicates the maximum rate for data sent from this interface,
+        in bit/s. The traffic will be shaped according to this limit.
+      </column>
+
+      <column name="options" key="qos_burst">
+        If set, indicates the maximum burst size for data sent from this
+        interface, in bits.
+      </column>
+
+      <column name="options" key="qdisc_queue_id"
+              type='{"type": "integer", "minInteger": 1, "maxInteger": 61440}'>
+        Indicates the queue number on the physical device. This is same as the
+        <code>queue_id</code> used in OpenFlow in <code>struct
+        ofp_action_enqueue</code>.
+      </column>
+    </group>
+
+    <group title="Chassis Redirect Options">
+      <p>
+        These options apply to logical ports with <ref column="type"/>
+        of <code>chassisredirect</code>.
+      </p>
+
+      <column name="options" key="distributed-port">
+        The name of the distributed port for which this
+        <code>chassisredirect</code> port represents a particular instance.
+      </column>
+
+      <column name="options" key="redirect-chassis">
+        The <code>chassis</code> that this <code>chassisredirect</code> port
+        is bound to.  This is taken from <ref table="Logical_Router_Port"
+        column="options" key="redirect-chassis" db="OVN_Northbound"/>
+        in the OVN_Northbound database's <ref table="Logical_Router_Port"
+        db="OVN_Northbound"/> table.
+      </column>
+    </group>
+
+    <group title="Nested Containers">
+      <p>
+        These columns support containers nested within a VM.  Specifically,
+        they are used when <ref column="type"/> is empty and <ref
+        column="logical_port"/> identifies the interface of a container spawned
+        inside a VM.  They are empty for containers or VMs that run directly on
+        a hypervisor.
+      </p>
+
+      <column name="parent_port">
+        This is taken from
+        <ref table="Logical_Switch_Port" column="parent_name"
+        db="OVN_Northbound"/> in the OVN_Northbound database's
+        <ref table="Logical_Switch_Port" db="OVN_Northbound"/> table.
+      </column>
+
+      <column name="tag">
+        <p>
+          Identifies the VLAN tag in the network traffic associated with that
+          container's network interface.
+        </p>
+
+        <p>
+          This column is used for a different purpose when <ref column="type"/>
+          is <code>localnet</code> (see <code>Localnet Options</code>, above)
+          or <code>l2gateway</code> (see <code>L2 Gateway Options</code>, above).
+        </p>
+      </column>
+    </group>
+
+    <group title="Naming">
+      <column name="external_ids" key="name">
+        <p>
+          For a logical switch port, <code>ovn-northd</code> copies this from
+          <ref table="Logical_Switch_Port" db="OVN_Northbound"
+          column="external_ids" key="neutron:port_name"/> in the <ref
+          table="Logical_Switch_Port" db="OVN_Northbound"/> table in the
+          OVN_Northbound database, if it is a nonempty string.
+        </p>
+
+        <p>
+          For a logical switch port, <code>ovn-northd</code> does not currently
+          set this key.
+        </p>
+      </column>
+    </group>
+
+    <group title="Common Columns">
+      <column name="external_ids">
+        <p>
+          See <em>External IDs</em> at the beginning of this document.
+        </p>
+
+        <p>
+          The <code>ovn-northd</code> program populates this column with
+          all entries into the <ref column="external_ids"/> column of the
+          <ref table="Logical_Switch_Port"/> table of the
+          <ref db="OVN_Northbound"/> database.
+        </p>
+      </column>
+    </group>
+  </table>
+
+  <table name="MAC_Binding" title="IP to MAC bindings">
+    <p>
+      Each row in this table specifies a binding from an IP address to an
+      Ethernet address that has been discovered through ARP (for IPv4) or
+      neighbor discovery (for IPv6).  This table is primarily used to discover
+      bindings on physical networks, because IP-to-MAC bindings for virtual
+      machines are usually populated statically into the <ref
+      table="Port_Binding"/> table.
+    </p>
+
+    <p>
+      This table expresses a functional relationship: <ref
+      table="MAC_Binding"/>(<ref column="logical_port"/>, <ref column="ip"/>) =
+      <ref column="mac"/>.
+    </p>
+
+    <p>
+      In outline, the lifetime of a logical router's MAC binding looks like
+      this:
+    </p>
+
+    <ol>
+      <li>
+        On hypervisor 1, a logical router determines that a packet should be
+        forwarded to IP address <var>A</var> on one of its router ports.  It
+        uses its logical flow table to determine that <var>A</var> lacks a
+        static IP-to-MAC binding and the <code>get_arp</code> action to
+        determine that it lacks a dynamic IP-to-MAC binding.
+      </li>
+
+      <li>
+        Using an OVN logical <code>arp</code> action, the logical router
+        generates and sends a broadcast ARP request to the router port.  It
+        drops the IP packet.
+      </li>
+
+      <li>
+        The logical switch attached to the router port delivers the ARP request
+        to all of its ports.  (It might make sense to deliver it only to ports
+        that have no static IP-to-MAC bindings, but this could also be
+        surprising behavior.)
+      </li>
+
+      <li>
+        A host or VM on hypervisor 2 (which might be the same as hypervisor 1)
+        attached to the logical switch owns the IP address in question.  It
+        composes an ARP reply and unicasts it to the logical router port's
+        Ethernet address.
+      </li>
+
+      <li>
+        The logical switch delivers the ARP reply to the logical router port.
+      </li>
+
+      <li>
+        The logical router flow table executes a <code>put_arp</code> action.
+        To record the IP-to-MAC binding, <code>ovn-controller</code> adds a row
+        to the <ref table="MAC_Binding"/> table.
+      </li>
+
+      <li>
+        On hypervisor 1, <code>ovn-controller</code> receives the updated <ref
+        table="MAC_Binding"/> table from the OVN southbound database.  The next
+        packet destined to <var>A</var> through the logical router is sent
+        directly to the bound Ethernet address.
+      </li>
+    </ol>
+
+    <column name="logical_port">
+      The logical port on which the binding was discovered.
+    </column>
+
+    <column name="ip">
+      The bound IP address.
+    </column>
+
+    <column name="mac">
+      The Ethernet address to which the IP is bound.
+    </column>
+    <column name="datapath">
+      The logical datapath to which the logical port belongs.
+    </column>
+  </table>
+
+  <table name="DHCP_Options" title="DHCP Options supported by native OVN DHCP">
+    <p>
+      Each row in this table stores the DHCP Options supported by native OVN
+      DHCP. <code>ovn-northd</code> populates this table with the supported
+      DHCP options. <code>ovn-controller</code> looks up this table to get the
+      DHCP codes of the DHCP options defined in the "put_dhcp_opts" action.
+      Please refer to the RFC 2132 <code>"https://tools.ietf.org/html/rfc2132"</code>
+      for the possible list of DHCP options that can be defined here.
+    </p>
+
+    <column name="name">
+      <p>
+        Name of the DHCP option.
+      </p>
+
+      <p>
+        Example. name="router"
+      </p>
+    </column>
+
+    <column name="code">
+      <p>
+        DHCP option code for the DHCP option as defined in the RFC 2132.
+      </p>
+
+      <p>
+        Example. code=3
+      </p>
+    </column>
+
+    <column name="type">
+      <p>
+        Data type of the DHCP option code.
+      </p>
+
+      <dl>
+        <dt><code>value: bool</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is a bool.
+          </p>
+
+          <p>
+            Example. "name=ip_forward_enable", "code=19", "type=bool".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., ip_forward_enable = 1,...)
+          </p>
+        </dd>
 
-    <column name="chassis">
-      The physical location of the logical port.  To successfully identify a
-      chassis, this column must be a <ref table="Chassis"/> record.  This is
-      populated by <code>ovn-controller</code>.
+        <dt><code>value: uint8</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is an unsigned
+            int8 (8 bits)
+          </p>
+
+          <p>
+            Example. "name=default_ttl", "code=23", "type=uint8".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., default_ttl = 50,...)
+          </p>
+        </dd>
+
+        <dt><code>value: uint16</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is an unsigned
+            int16 (16 bits).
+          </p>
+
+          <p>
+            Example. "name=mtu", "code=26", "type=uint16".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., mtu = 1450,...)
+          </p>
+        </dd>
+
+        <dt><code>value: uint32</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is an unsigned
+            int32 (32 bits).
+          </p>
+
+          <p>
+            Example. "name=lease_time", "code=51", "type=uint32".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., lease_time = 86400,...)
+          </p>
+        </dd>
+
+        <dt><code>value: ipv4</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is an IPv4
+            address or addresses.
+          </p>
+
+          <p>
+            Example. "name=router", "code=3", "type=ipv4".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., router = 10.0.0.1,...)
+          </p>
+
+          <p>
+            Example. "name=dns_server", "code=6", "type=ipv4".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., dns_server = {8.8.8.8 7.7.7.7},...)
+          </p>
+        </dd>
+
+        <dt><code>value: static_routes</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option contains a pair of
+            IPv4 route and next hop addresses.
+          </p>
+
+          <p>
+            Example. "name=classless_static_route", "code=121", "type=static_routes".
+          </p>
+
+          <p>
+            put_dhcp_opts(..., classless_static_route = {30.0.0.0/24,10.0.0.4,0.0.0.0/0,10.0.0.1}...)
+          </p>
+        </dd>
+
+        <dt><code>value: str</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCP option is a string.
+          </p>
+
+          <p>
+            Example. "name=host_name", "code=12", "type=str".
+          </p>
+        </dd>
+      </dl>
     </column>
+  </table>
+
+  <table name="DHCPv6_Options" title="DHCPv6 Options supported by native OVN DHCPv6">
+    <p>
+      Each row in this table stores the DHCPv6 Options supported by native OVN
+      DHCPv6. <code>ovn-northd</code> populates this table with the supported
+      DHCPv6 options. <code>ovn-controller</code> looks up this table to get
+      the DHCPv6 codes of the DHCPv6 options defined in the
+      <code>put_dhcpv6_opts</code> action. Please refer to RFC 3315 and RFC
+      3646 for the list of DHCPv6 options that can be defined here.
+    </p>
+
+    <column name="name">
+      <p>
+        Name of the DHCPv6 option.
+      </p>
+
+      <p>
+        Example. name="ia_addr"
+      </p>
+    </column>
+
+    <column name="code">
+      <p>
+        DHCPv6 option code for the DHCPv6 option as defined in the appropriate
+        RFC.
+      </p>
+
+      <p>
+        Example. code=3
+      </p>
+    </column>
+
+    <column name="type">
+      <p>
+        Data type of the DHCPv6 option code.
+      </p>
+
+      <dl>
+        <dt><code>value: ipv6</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCPv6 option is an IPv6
+            address(es).
+          </p>
+
+          <p>
+            Example. "name=ia_addr", "code=5", "type=ipv6".
+          </p>
+
+          <p>
+            put_dhcpv6_opts(..., ia_addr = ae70::4,...)
+          </p>
+        </dd>
+
+        <dt><code>value: str</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCPv6 option is a string.
+          </p>
+
+          <p>
+            Example. "name=domain_search", "code=24", "type=str".
+          </p>
+
+          <p>
+            put_dhcpv6_opts(..., domain_search = ovn.domain,...)
+          </p>
+        </dd>
+
+        <dt><code>value: mac</code></dt>
+        <dd>
+          <p>
+            This indicates that the value of the DHCPv6 option is a MAC address.
+          </p>
+
+          <p>
+            Example. "name=server_id", "code=2", "type=mac".
+          </p>
+
+          <p>
+            put_dhcpv6_opts(..., server_id = 01:02:03:04L05:06,...)
+          </p>
+        </dd>
+      </dl>
+    </column>
+  </table>
+  <table name="Connection" title="OVSDB client connections.">
+    <p>
+      Configuration for a database connection to an Open vSwitch database
+      (OVSDB) client.
+    </p>
+
+    <p>
+      This table primarily configures the Open vSwitch database server
+      (<code>ovsdb-server</code>).
+    </p>
+
+    <p>
+      The Open vSwitch database server can initiate and maintain active
+      connections to remote clients.  It can also listen for database
+      connections.
+    </p>
+
+    <group title="Core Features">
+      <column name="target">
+        <p>Connection methods for clients.</p>
+        <p>
+          The following connection methods are currently supported:
+        </p>
+        <dl>
+          <dt><code>ssl:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            <p>
+              The specified SSL <var>port</var> on the host at the given
+              <var>ip</var>, which must be expressed as an IP address
+              (not a DNS name). A valid SSL configuration must be provided
+              when this form is used, this configuration can be specified
+              via command-line options or the <ref table="SSL"/> table.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always
+              built as part of Open vSwitch.
+            </p>
+          </dd>
+
+          <dt><code>tcp:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            <p>
+              The specified TCP <var>port</var> on the host at the given
+              <var>ip</var>, which must be expressed as an IP address (not a
+              DNS name), where <var>ip</var> can be IPv4 or IPv6 address.  If
+              <var>ip</var> is an IPv6 address, wrap it in square brackets,
+              e.g. <code>tcp:[::1]:6640</code>.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+          </dd>
+          <dt><code>pssl:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            <p>
+              Listens for SSL connections on the specified TCP <var>port</var>.
+              Specify 0 for <var>port</var> to have the kernel automatically
+              choose an available port.  If <var>ip</var>, which must be
+              expressed as an IP address (not a DNS name), is specified, then
+              connections are restricted to the specified local IP address
+              (either IPv4 or IPv6 address).  If <var>ip</var> is an IPv6
+              address, wrap in square brackets,
+              e.g. <code>pssl:6640:[::1]</code>.  If <var>ip</var> is not
+              specified then it listens only on IPv4 (but not IPv6) addresses.
+              A valid SSL configuration must be provided when this form is used,
+              this can be specified either via command-line options or the
+              <ref table="SSL"/> table.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always built as
+              part of Open vSwitch.
+            </p>
+          </dd>
+          <dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            <p>
+              Listens for connections on the specified TCP <var>port</var>.
+              Specify 0 for <var>port</var> to have the kernel automatically
+              choose an available port.  If <var>ip</var>, which must be
+              expressed as an IP address (not a DNS name), is specified, then
+              connections are restricted to the specified local IP address
+              (either IPv4 or IPv6 address).  If <var>ip</var> is an IPv6
+              address, wrap it in square brackets,
+              e.g. <code>ptcp:6640:[::1]</code>.  If <var>ip</var> is not
+              specified then it listens only on IPv4 addresses.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+          </dd>
+        </dl>
+        <p>When multiple clients are configured, the <ref column="target"/>
+        values must be unique.  Duplicate <ref column="target"/> values yield
+        unspecified results.</p>
+      </column>
+
+      <column name="read_only">
+        <code>true</code> to restrict these connections to read-only
+        transactions, <code>false</code> to allow them to modify the database.
+      </column>
+      <column name="role">
+        String containing role name for this connection entry.
+      </column>
+    </group>
+
+    <group title="Client Failure Detection and Handling">
+      <column name="max_backoff">
+        Maximum number of milliseconds to wait between connection attempts.
+        Default is implementation-specific.
+      </column>
+
+      <column name="inactivity_probe">
+        Maximum number of milliseconds of idle time on connection to the client
+        before sending an inactivity probe message.  If Open vSwitch does not
+        communicate with the client for the specified number of seconds, it
+        will send a probe.  If a response is not received for the same
+        additional amount of time, Open vSwitch assumes the connection has been
+        broken and attempts to reconnect.  Default is implementation-specific.
+        A value of 0 disables inactivity probes.
+      </column>
+    </group>
+
+    <group title="Status">
+      <p>
+        Key-value pair of <ref column="is_connected"/> is always updated.
+        Other key-value pairs in the status columns may be updated depends
+        on the <ref column="target"/> type.
+      </p>
 
-    <column name="mac">
       <p>
-        The Ethernet address or addresses used as a source address on the
-        logical port, each in the form
-        <var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>:<var>xx</var>.
-        The string <code>unknown</code> is also allowed to indicate that the
-        logical port has an unknown set of (additional) source addresses.
+        When <ref column="target"/> specifies a connection method that
+        listens for inbound connections (e.g. <code>ptcp:</code> or
+        <code>punix:</code>), both <ref column="n_connections"/> and
+        <ref column="is_connected"/> may also be updated while the
+        remaining key-value pairs are omitted.
       </p>
 
       <p>
-        A VM interface would ordinarily have a single Ethernet address.  A
-        gateway port might initially only have <code>unknown</code>, and then
-        add MAC addresses to the set as it learns new source addresses.
+        On the other hand, when <ref column="target"/> specifies an
+        outbound connection, all key-value pairs may be updated, except
+        the above-mentioned two key-value pairs associated with inbound
+        connection targets. They are omitted.
+      </p>
+
+      <column name="is_connected">
+        <code>true</code> if currently connected to this client,
+        <code>false</code> otherwise.
+      </column>
+
+      <column name="status" key="last_error">
+        A human-readable description of the last error on the connection
+        to the manager; i.e. <code>strerror(errno)</code>.  This key
+        will exist only if an error has occurred.
+      </column>
+
+      <column name="status" key="state"
+              type='{"type": "string", "enum": ["set", ["VOID", "BACKOFF", "CONNECTING", "ACTIVE", "IDLE"]]}'>
+        <p>
+          The state of the connection to the manager:
+        </p>
+        <dl>
+          <dt><code>VOID</code></dt>
+          <dd>Connection is disabled.</dd>
+
+          <dt><code>BACKOFF</code></dt>
+          <dd>Attempting to reconnect at an increasing period.</dd>
+
+          <dt><code>CONNECTING</code></dt>
+          <dd>Attempting to connect.</dd>
+
+          <dt><code>ACTIVE</code></dt>
+          <dd>Connected, remote host responsive.</dd>
+
+          <dt><code>IDLE</code></dt>
+          <dd>Connection is idle.  Waiting for response to keep-alive.</dd>
+        </dl>
+        <p>
+          These values may change in the future.  They are provided only for
+          human consumption.
+        </p>
+      </column>
+
+      <column name="status" key="sec_since_connect"
+              type='{"type": "integer", "minInteger": 0}'>
+        The amount of time since this client last successfully connected
+        to the database (in seconds). Value is empty if client has never
+        successfully been connected.
+      </column>
+
+      <column name="status" key="sec_since_disconnect"
+              type='{"type": "integer", "minInteger": 0}'>
+        The amount of time since this client last disconnected from the
+        database (in seconds). Value is empty if client has never
+        disconnected.
+      </column>
+
+      <column name="status" key="locks_held">
+        Space-separated list of the names of OVSDB locks that the connection
+        holds.  Omitted if the connection does not hold any locks.
+      </column>
+
+      <column name="status" key="locks_waiting">
+        Space-separated list of the names of OVSDB locks that the connection is
+        currently waiting to acquire.  Omitted if the connection is not waiting
+        for any locks.
+      </column>
+
+      <column name="status" key="locks_lost">
+        Space-separated list of the names of OVSDB locks that the connection
+        has had stolen by another OVSDB client.  Omitted if no locks have been
+        stolen from this connection.
+      </column>
+
+      <column name="status" key="n_connections"
+              type='{"type": "integer", "minInteger": 2}'>
+        When <ref column="target"/> specifies a connection method that
+        listens for inbound connections (e.g. <code>ptcp:</code> or
+        <code>pssl:</code>) and more than one connection is actually active,
+        the value is the number of active connections.  Otherwise, this
+        key-value pair is omitted.
+      </column>
+
+      <column name="status" key="bound_port" type='{"type": "integer"}'>
+        When <ref column="target"/> is <code>ptcp:</code> or
+        <code>pssl:</code>, this is the TCP port on which the OVSDB server is
+        listening.  (This is particularly useful when <ref
+        column="target"/> specifies a port of 0, allowing the kernel to
+        choose any available port.)
+      </column>
+    </group>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+      <column name="other_config"/>
+    </group>
+  </table>
+  <table name="SSL">
+    SSL configuration for ovn-sb database access.
+
+    <column name="private_key">
+      Name of a PEM file containing the private key used as the switch's
+      identity for SSL connections to the controller.
+    </column>
+
+    <column name="certificate">
+      Name of a PEM file containing a certificate, signed by the
+      certificate authority (CA) used by the controller and manager,
+      that certifies the switch's private key, identifying a trustworthy
+      switch.
+    </column>
+
+    <column name="ca_cert">
+      Name of a PEM file containing the CA certificate used to verify
+      that the switch is connected to a trustworthy controller.
+    </column>
+
+    <column name="bootstrap_ca_cert">
+      If set to <code>true</code>, then Open vSwitch will attempt to
+      obtain the CA certificate from the controller on its first SSL
+      connection and save it to the named PEM file. If it is successful,
+      it will immediately drop the connection and reconnect, and from then
+      on all SSL connections must be authenticated by a certificate signed
+      by the CA certificate thus obtained.  <em>This option exposes the
+      SSL connection to a man-in-the-middle attack obtaining the initial
+      CA certificate.</em>  It may still be useful for bootstrapping.
+    </column>
+
+    <column name="ssl_protocols">
+      List of SSL protocols to be enabled for SSL connections. The default
+      when this option is omitted is <code>TLSv1,TLSv1.1,TLSv1.2</code>.
+    </column>
+
+    <column name="ssl_ciphers">
+      List of ciphers (in OpenSSL cipher string format) to be supported
+      for SSL connections. The default when this option is omitted is
+      <code>HIGH:!aNULL:!MD5</code>.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+  <table name="DNS" title="Native DNS resolution">
+    <p>
+      Each row in this table stores the DNS records. The OVN action
+      <code>dns_lookup</code> uses this table for DNS resolution.
+    </p>
+
+    <column name="records">
+      Key-value pair of DNS records with <code>DNS query name</code> as the key
+      and a string of IP address(es) separated by comma or space as the
+      value.
+
+      <p><b>Example: </b> "vm1.ovn.org" = "10.0.0.4 aef0::4"</p>
+    </column>
+
+    <column name="datapaths">
+      The DNS records defined in the column <ref column="records"/> will be
+      applied only to the DNS queries originating from the datapaths defined
+      in this column.
+    </column>
+
+    <group title="Common Columns">
+      <column name="external_ids">
+        See <em>External IDs</em> at the beginning of this document.
+      </column>
+    </group>
+  </table>
+
+  <table name="RBAC_Role">
+    Role table for role-based access controls.
+
+    <column name="name">
+        The role name, corresponding to the <code>role</code>
+        column in the <code>Connection</code> table.
+    </column>
+
+    <column name="permissions">
+        A mapping of table names to rows in the
+        <code>RBAC_Permission</code> table.
+    </column>
+  </table>
+  <table name="RBAC_Permission">
+    Permissions table for role-based access controls.
+
+    <column name="table">
+      Name of table to which this row applies.
+    </column>
+
+    <column name="authorization">
+        Set of strings identifying columns and column:key pairs to be compared
+        with client ID. At least one match is required in order to be
+        authorized.  A zero-length string is treated as a special value
+        indicating all clients should be considered authorized.
+    </column>
+
+    <column name="insert_delete">
+        When "true", row insertions and authorized row
+        deletions are permitted.
+    </column>
+    <column name="update">
+        Set of strings identifying columns and column:key pairs that authorized
+        clients are allowed to modify.
+    </column>
+  </table>
+  <table name="Gateway_Chassis">
+    <p>
+      Association of <ref table="Port_Binding"/> rows of
+      <ref table="Port_Binding" column="type"/> <code>chassisredirect</code> to
+      a <ref table="Chassis"/>. The traffic going out through a specific
+      <code>chassisredirect</code> port will be redirected to a chassis,
+      or a set of them in high availability configurations.
+    </p>
+
+    <column name="name">
+      <p>
+        Name of the <ref table="Gateway_Chassis"/>.
+      </p>
+      <p>
+        A suggested, but not required naming convention is
+        <code>${port_name}_${chassis_name}</code>.
       </p>
     </column>
+
+    <column name="chassis">
+      The <ref table="Chassis"/> to which we send the traffic.
+    </column>
+
+    <column name="priority">
+      This is the priority the specific <ref table="Chassis"/> among all
+      Gateway_Chassis belonging to the same <ref table="Port_Binding"/>.
+    </column>
+
+    <column name="options">
+      Reserved for future use.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
   </table>
 </database>