{"id":2229777,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2229777/?format=json","web_url":"http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-4-mmichels@redhat.com/","project":{"id":68,"url":"http://patchwork.ozlabs.org/api/1.1/projects/68/?format=json","name":"Open Virtual Network development","link_name":"ovn","list_id":"ovs-dev.openvswitch.org","list_email":"ovs-dev@openvswitch.org","web_url":"http://openvswitch.org/","scm_url":"","webscm_url":""},"msgid":"<20260428174509.145440-4-mmichels@redhat.com>","date":"2026-04-28T17:45:03","name":"[ovs-dev,3/5] northd: Split logical flow docs into ovn-logical-flows(7).","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"fe5923b0224df923ad768056fe0797abf3a6f014","submitter":{"id":71978,"url":"http://patchwork.ozlabs.org/api/1.1/people/71978/?format=json","name":"Mark Michelson","email":"mmichels@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-4-mmichels@redhat.com/mbox/","series":[{"id":501914,"url":"http://patchwork.ozlabs.org/api/1.1/series/501914/?format=json","web_url":"http://patchwork.ozlabs.org/project/ovn/list/?series=501914","date":"2026-04-28T17:45:02","name":"Fix up northd documentation.","version":1,"mbox":"http://patchwork.ozlabs.org/series/501914/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2229777/comments/","check":"fail","checks":"http://patchwork.ozlabs.org/api/patches/2229777/checks/","tags":{},"headers":{"Return-Path":"<ovs-dev-bounces@openvswitch.org>","X-Original-To":["incoming@patchwork.ozlabs.org","dev@openvswitch.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","ovs-dev@lists.linuxfoundation.org"],"Authentication-Results":["legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KUcU0B7N;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp2.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KUcU0B7N","smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=KUcU0B7N"],"Received":["from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4nsd2d5Tz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 03:45:56 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id B0B9940863;\n\tTue, 28 Apr 2026 17:45:54 +0000 (UTC)","from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 8V6Lfe4Hl89M; Tue, 28 Apr 2026 17:45:51 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id 1AD654083D;\n\tTue, 28 Apr 2026 17:45:51 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id E0FC2C04FB;\n\tTue, 28 Apr 2026 17:45:50 +0000 (UTC)","from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 2A31CC04FA\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:49 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 97277834F4\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:31 +0000 (UTC)","from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id lUI2Of4HP3rq for <dev@openvswitch.org>;\n Tue, 28 Apr 2026 17:45:24 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 5E47883409\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:22 +0000 (UTC)","from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-597-yg7Zn2ZvMkyX-uJEGtKwDQ-1; Tue,\n 28 Apr 2026 13:45:14 -0400","from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id DB1FA195609D\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:13 +0000 (UTC)","from localhost.localdomain.com (unknown [10.22.88.208])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 063BD19560B7\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:12 +0000 (UTC)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1AD654083D","OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5E47883409"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=mmichels@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp1.osuosl.org 5E47883409","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777398321;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=4MlCRUuvywFWV0+R98WVT4LktWlovIqQPQO2kONVL0M=;\n b=KUcU0B7NU2RPhMDv4jMXYQiezbqKj8nRBOKPRB5eo5mja8kKR5Y3OgSutCsEz4Yz1uAFPx\n 34O+g+yulTkfOAIqsMP8lnLjzolq50O/ZWKjY2xngHu35yxd8rErWQbk4HH3v/e37RXn38\n 5nEQO83nwv38ZCd6sTh7l4E4N263Foo=","X-MC-Unique":"yg7Zn2ZvMkyX-uJEGtKwDQ-1","X-Mimecast-MFC-AGG-ID":"yg7Zn2ZvMkyX-uJEGtKwDQ_1777398314","To":"dev@openvswitch.org","Date":"Tue, 28 Apr 2026 13:45:03 -0400","Message-ID":"<20260428174509.145440-4-mmichels@redhat.com>","In-Reply-To":"<20260428174509.145440-1-mmichels@redhat.com>","References":"<20260428174509.145440-1-mmichels@redhat.com>","MIME-Version":"1.0","X-Scanned-By":"MIMEDefang 3.0 on 10.30.177.12","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"lU2VETdYzhliCu9pL0n-elvgwYsv9keE8jzjkHPRR48_1777398314","X-Mimecast-Originator":"redhat.com","Subject":"[ovs-dev] [PATCH ovn 3/5] northd: Split logical flow docs into\n ovn-logical-flows(7).","X-BeenThere":"ovs-dev@openvswitch.org","X-Mailman-Version":"2.1.30","Precedence":"list","List-Id":"<ovs-dev.openvswitch.org>","List-Unsubscribe":"<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>","List-Archive":"<http://mail.openvswitch.org/pipermail/ovs-dev/>","List-Post":"<mailto:ovs-dev@openvswitch.org>","List-Help":"<mailto:ovs-dev-request@openvswitch.org?subject=help>","List-Subscribe":"<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>","From":"Mark Michelson via dev <ovs-dev@openvswitch.org>","Reply-To":"Mark Michelson <mmichels@redhat.com>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"},"content":"Move the \"Logical Flow Table Structure\" and \"Drop sampling\" sections\nfrom ovn-northd.8.xml into a new ovn-logical-flows.7.xml manpage.\nThis separates the logical flow pipeline reference documentation from\nthe ovn-northd daemon description. A cross-reference stub remains in\novn-northd(8) pointing readers to the new manpage.\n\nAssisted-by: Claude Code (Claude Opus 4.6)\nSigned-off-by: Mark Michelson <mmichels@redhat.com>\n---\n northd/automake.mk             |    3 +\n northd/ovn-logical-flows.7.xml | 6080 ++++++++++++++++++++++++++++++++\n northd/ovn-northd.8.xml        | 6065 +------------------------------\n 3 files changed, 6088 insertions(+), 6060 deletions(-)\n create mode 100644 northd/ovn-logical-flows.7.xml","diff":"diff --git a/northd/automake.mk b/northd/automake.mk\nindex 8cd4fb3a1..47142a5b0 100644\n--- a/northd/automake.mk\n+++ b/northd/automake.mk\n@@ -71,3 +71,6 @@ northd_ovn_northd_LDADD = \\\n man_MANS += northd/ovn-northd.8\n EXTRA_DIST += northd/ovn-northd.8.xml\n CLEANFILES += northd/ovn-northd.8\n+man_MANS += northd/ovn-logical-flows.7\n+EXTRA_DIST += northd/ovn-logical-flows.7.xml\n+CLEANFILES += northd/ovn-logical-flows.7\ndiff --git a/northd/ovn-logical-flows.7.xml b/northd/ovn-logical-flows.7.xml\nnew file mode 100644\nindex 000000000..b8d353695\n--- /dev/null\n+++ b/northd/ovn-logical-flows.7.xml\n@@ -0,0 +1,6080 @@\n+<?xml version=\"1.0\" encoding=\"utf-8\"?>\n+<manpage program=\"ovn-logical-flows\" section=\"7\" title=\"OVN Logical Flows\">\n+    <h1>Name</h1>\n+    <p>ovn-logical-flows -- OVN logical flow table reference</p>\n+\n+    <h1>Description</h1>\n+    <p>\n+      This document describes the logical flow tables that\n+      <code>ovn-northd</code>(8) populates in the\n+      <code>OVN_Southbound</code> database.  It covers both logical\n+      switch and logical router datapath pipelines, as well as\n+      drop sampling behavior.\n+    </p>\n+\n+    <h1>Logical Flow Table Structure</h1>\n+\n+    <p>\n+      One of the main purposes of <code>ovn-northd</code> is to populate the\n+      <code>Logical_Flow</code> table in the <code>OVN_Southbound</code>\n+      database.  This section describes how <code>ovn-northd</code> does this\n+      for switch and router logical datapaths.\n+    </p>\n+\n+    <h2>Logical Switch Datapaths</h2>\n+\n+    <h3>Ingress Table 0: Admission Control and Ingress Port Security check</h3>\n+\n+    <p>\n+      Ingress table 0 contains these logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        Priority 100 flows to drop packets with VLAN tags or multicast Ethernet\n+        source addresses.\n+      </li>\n+\n+      <li>\n+        For each disabled logical port, a priority 100 flow is added which\n+        matches on all packets and applies the action\n+        <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code> so that the packets are\n+        dropped in the next stage.\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each logical port that's defined as a target of routing protocol\n+          redirecting (via <code>routing-protocol-redirect</code> option set on\n+          Logical Router Port), a filter is set in place that disallows\n+          following traffic exiting this port:\n+        </p>\n+        <ul>\n+          <li>\n+            ARP replies\n+          </li>\n+          <li>\n+            IPv6 Neighbor Discovery - Router Advertisements\n+          </li>\n+          <li>\n+            IPv6 Neighbor Discovery - Neighbor Advertisements\n+          </li>\n+        </ul>\n+        <p>\n+          Since this port shares IP and MAC addresses with the Logical Router\n+          Port, we wan't to prevent duplicate replies and advertisements. This\n+          is achieved by a rule with priority 80 that sets\n+          <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        For each logical switch that has connected physical ports\n+        (localnet or l2gateway) and is also connected to a distributed router,\n+        filtering rules are added for ARP requests coming from localnet or\n+        l2gateway ports, allowed for processing on gateway chassis.\n+        The <code>REGBIT_EXT_ARP</code> register is set for all ARP requests\n+        originating from physical ports with priority 75 flow.\n+      </li>\n+\n+      <li>\n+        For each (enabled) vtep logical port, a priority 70 flow is added which\n+        matches on all packets and applies the action\n+        <code>next(pipeline=ingress, table=S_SWITCH_IN_L3_LKUP) = 1;</code>\n+        to skip most stages of ingress pipeline and go directly to ingress L2\n+        lookup table to determine the output port. Packets from VTEP (RAMP)\n+        switch should not be subjected to any ACL checks. Egress pipeline will\n+        do the ACL checks.\n+      </li>\n+\n+      <li>\n+        For each enabled logical port configured with qdisc queue id in the\n+        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/>, a priority 70 flow is added which\n+        matches on all packets and applies the action\n+        <code>set_queue(id);\n+        REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;\"</code>.\n+      </li>\n+\n+      <li>\n+        A priority 1 flow is added which matches on all packets for all the\n+        logical ports and applies the action\n+        <code>REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;</code> to\n+        evaluate the port security.  The action <code>check_in_port_sec</code>\n+        applies the port security rules defined in the\n+        <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 1: Ingress Port Security - Apply</h3>\n+\n+    <p>\n+      For each logical switch port <var>P</var> of type router connected to a\n+      gw router a priority-120 flow that matches 'recirculated' icmp{4,6} error\n+      'packet too big' and <code>eth.src == <var>D</var> &amp;&amp;\n+      outport == <var>P</var> &amp;&amp; flags.tunnel_rx == 1</code> where\n+      <var>D</var> is the peer logical router port <var>RP</var> mac address,\n+      swaps inport and outport and applies the action <code>next</code>.\n+    </p>\n+\n+    <p>\n+      For each logical switch port <var>P</var> of type router connected to a\n+      distributed router a priority-120 flow that matches 'recirculated'\n+      icmp{4,6} error 'packet too big' and <code>eth.dst == <var>D</var>\n+      &amp;&amp; flags.tunnel_rx == 1</code> where <var>D</var> is the peer\n+      logical router port <var>RP</var> mac address, swaps inport and outport\n+      and applies the action <code> next(pipeline=S_SWITCH_IN_L2_LKUP)</code>.\n+    </p>\n+\n+    <p>\n+      For each logical switch port <var>P</var> a priority-110 flow that\n+      matches 'recirculated' icmp{4,6} error 'packet too big' and <code>\n+      eth.src == <var>D</var> &amp;&amp; outport == <var>P</var> &amp;&amp;\n+      !is_chassis_resident(\"<var>P</var>\") &amp;&amp; flags.tunnel_rx == 1\n+      </code> where <var>D</var> is the logical switch port mac address,\n+      swaps inport and outport and applies the action <code>next</code>.\n+    </p>\n+\n+    <p>\n+      This table adds a priority-105 flow that matches 'recirculated' icmp{4,6}\n+      error 'packet too big' to drop the packet.\n+    </p>\n+\n+    <p>\n+      This table drops the packets if the port security check failed\n+      in the previous stage i.e the register bit\n+      <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n+    </p>\n+\n+    <p>\n+      Ingress table 1 contains these logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-50 fallback flow that drops the packet if the register\n+        bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+\n+      <li>\n+        Priority 75: Allows <code>REGBIT_EXT_ARP</code> packets only on gateway\n+        chassis and chassis with distributed NAT entries.\n+        Priority 70: Drops <code>REGBIT_EXT_ARP</code> packets on non-gateway\n+        chassis (complements the priority 75 flow).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 2: Mirror </h3>\n+\n+    <p>\n+      Overlay remote mirror table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For each logical switch port with an attached mirror, a logical flow\n+        with a priority of 100 is added. This flow matches all incoming packets\n+        to the attached port, clones them, and forwards the cloned packets to\n+        the mirror target port.\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+\n+      <li>\n+        A logical flow added for each Mirror Rule in Mirror table attached\n+        to logical switch ports, matches all incoming packets that match\n+        rules and clones the packet and sends cloned packet to mirror\n+        target port.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 3: Lookup MAC address learning table</h3>\n+\n+    <p>\n+      This table looks up the MAC learning table of the logical switch\n+      datapath to check if the <code>port-mac</code> pair is present\n+      or not. MAC is learnt for logical switch VIF ports whose\n+      port security is disabled and 'unknown' address setn as well as\n+      for localnet ports with option localnet_learn_fdb. A localnet\n+      port entry does not overwrite a VIF port entry.\n+      Logical switch ports with type <code>switch</code> have implicit\n+      'unknown' addresses and so they are also eligible for MAC learning.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each such VIF logical port <var>p</var> whose port security\n+          is disabled and 'unknown' address set following flow\n+          is added.\n+        </p>\n+\n+        <ul>\n+          <li>\n+            Priority 100 flow with the match\n+            <code>inport == <var>p</var></code> and action\n+            <code>reg0[11] = lookup_fdb(inport, eth.src); next;</code>\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each such localnet logical port <var>p</var> following flow\n+          is added.\n+        </p>\n+\n+        <ul>\n+          <li>\n+            Priority 100 flow with the match\n+            <code>inport == <var>p</var></code> and action\n+            <code>flags.localnet = 1;</code>\n+            <code>reg0[11] = lookup_fdb(inport, eth.src); next;</code>\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 4: Learn MAC of 'unknown' ports.</h3>\n+\n+    <p>\n+      This table learns the MAC addresses seen on the VIF or 'switch' logical\n+      ports whose port security is disabled and 'unknown' address set (note:\n+      'switch' ports have implicit 'unknown' addresses) as well\n+      as on localnet ports with localnet_learn_fdb option set\n+      if the <code>lookup_fdb</code> action returned false in the\n+      previous table. For localnet ports (with flags.localnet = 1),\n+      lookup_fdb returns true if (port, mac) is found or if a mac\n+      is found for a port of type vif.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each such VIF logical port <var>p</var> whose port security is\n+          disabled and 'unknown' address set and localnet port following flow\n+          is added.\n+        </p>\n+\n+        <ul>\n+          <li>\n+            Priority 100 flow with the match\n+            <code>inport == <var>p</var> &amp;&amp; reg0[11] == 0</code> and\n+            action <code>put_fdb(inport, eth.src); next;</code> which stores\n+            the <code>port-mac</code> in the mac learning table of the\n+            logical switch datapath and advances the packet to the next table.\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 5: <code>from-lport</code> Pre-ACLs</h3>\n+\n+    <p>\n+      This table prepares flows for possible stateful ACL processing in\n+      ingress table <code>ACLs</code>.  It contains a priority-0 flow that\n+      simply moves traffic to the next table.  If stateful ACLs are used in the\n+      logical datapath, a priority-100 flow is added that sets a hint\n+      (with <code>reg0[0] = 1; next;</code>) for table\n+      <code>Pre-stateful</code> to send IP packets to the connection tracker\n+      before eventually advancing to ingress table <code>ACLs</code>. If\n+      special ports such as route ports or localnet ports can't use ct(), a\n+      priority-110 flow is added to skip over stateful ACLs.  This\n+      priority-110 flow is not addd for router ports if the option\n+      enable_router_port_acl is set to true in\n+      <ref column=\"options:enable_router_port_acl\"\n+      table=\"Logical_Switch_Port\" db=\"OVN_Northbound\"/> column of\n+      <ref table=\"Logical_Switch_Port\" db=\"OVN_Northbound\"/>.  Multicast, IPv6\n+      Neighbor Discovery and MLD traffic also skips stateful ACLs. For\n+      \"allow-stateless\" ACLs, a flow is added to bypass setting the hint for\n+      connection tracker processing when there are stateful ACLs or LB rules;\n+      <code>REGBIT_ACL_STATELESS</code> is set for traffic matching stateless\n+      ACL flows.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>eth.dst == <var>E</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>E</var>\n+      is the service monitor mac defined in the\n+      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> table.\n+    </p>\n+\n+    <h3>Ingress Table 6: Pre-LB</h3>\n+\n+    <p>\n+      This table prepares flows for possible stateful load balancing processing\n+      in ingress table <code>LB</code> and <code>Stateful</code>.  It contains\n+      a priority-0 flow that simply moves traffic to the next table. Moreover\n+      it contains two priority-110 flows to move multicast, IPv6 Neighbor\n+      Discovery and MLD traffic to the next table. It also contains two\n+      priority-110 flows to move stateless traffic, i.e traffic for which\n+      <code>REGBIT_ACL_STATELESS</code> is set, to the next table. If load\n+      balancing rules with virtual IP addresses (and ports) are configured in\n+      <code>OVN_Northbound</code> database for a logical switch datapath, a\n+      priority-100 flow is added with the match <code>ip</code> to match on IP\n+      packets and sets the action <code>reg0[2] = 1; next;</code> to act as a\n+      hint for table <code>Pre-stateful</code> to send IP packets to the\n+      connection tracker for packet de-fragmentation (and to possibly do DNAT\n+      for already established load balanced traffic) before eventually\n+      advancing to ingress table <code>Stateful</code>.\n+      If controller_event has been enabled and load balancing rules with\n+      empty backends have been added in <code>OVN_Northbound</code>, a 130 flow\n+      is added to trigger ovn-controller events whenever the chassis receives a\n+      packet for that particular VIP. If <code>event-elb</code> meter has been\n+      previously created, it will be associated to the empty_lb logical flow\n+    </p>\n+\n+    <p>\n+      Prior to <code>OVN 20.09</code> we were setting the\n+      <code>reg0[0] = 1</code> only if the IP destination matches the load\n+      balancer VIP. However this had few issues cases where a logical switch\n+      doesn't have any ACLs with <code>allow-related</code> action.\n+      To understand the issue lets a take a TCP load balancer -\n+      <code>10.0.0.10:80=10.0.0.3:80</code>. If a logical port - p1 with\n+      IP - 10.0.0.5 opens a TCP connection with the VIP - 10.0.0.10, then the\n+      packet in the ingress pipeline of 'p1' is sent to the p1's conntrack zone\n+      id and the packet is load balanced to the backend - 10.0.0.3. For the\n+      reply packet from the backend lport, it is not sent to the conntrack of\n+      backend lport's zone id. This is fine as long as the packet is valid.\n+      Suppose the backend lport sends an invalid TCP packet (like incorrect\n+      sequence number), the packet gets delivered to the lport 'p1' without\n+      unDNATing the packet to the VIP - 10.0.0.10. And this causes the\n+      connection to be reset by the lport p1's VIF.\n+    </p>\n+\n+    <p>\n+      We can't fix this issue by adding a logical flow to drop ct.inv packets\n+      in the egress pipeline since it will drop all other connections not\n+      destined to the load balancers. To fix this issue, we send all the\n+      packets to the conntrack in the ingress pipeline if a load balancer is\n+      configured. We can now add a lflow to drop ct.inv packets.\n+    </p>\n+\n+    <p>\n+      This table also has priority-120 flows that punt all IGMP/MLD packets to\n+      <code>ovn-controller</code> if the switch is an interconnect switch\n+      with multicast snooping enabled.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>eth.dst == <var>E</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>E</var>\n+      is the service monitor mac defined in the\n+      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> table.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>inport == <var>I</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>I</var>\n+      is the peer of a logical router port. This flow is added to\n+      skip the connection tracking of packets which enter from\n+      logical router datapath to logical switch datapath.\n+    </p>\n+\n+    <h3>Ingress Table 7: Pre-stateful</h3>\n+\n+    <p>\n+      This table prepares flows for all possible stateful processing\n+      in next tables.  It contains a priority-0 flow that simply moves\n+      traffic to the next table.\n+    </p>\n+    <ul>\n+      <li>\n+        Priority-120 flows that send the packets to connection tracker using\n+        <code>ct_lb_mark;</code> as the action so that the already established\n+        traffic destined to the load balancer VIP gets DNATted. These flows\n+        match each VIPs IP and port. For IPv4 traffic the flows also load the\n+        original destination IP and transport port in registers\n+        <code>reg1</code> and <code>reg2</code>.  For IPv6 traffic the flows\n+        also load the original destination IP and transport port in\n+        registers <code>xxreg1</code> and <code>reg2</code>.\n+      </li>\n+\n+      <li>\n+         A priority-110 flow sends the packets that don't match the above flows\n+         to connection tracker based on a hint provided by the previous tables\n+         (with a match for <code>reg0[2] == 1</code>) by using the\n+         <code>ct_lb_mark;</code> action.\n+      </li>\n+\n+      <li>\n+         A priority-105 added enabled when enable-stateless-acl-with-lb and\n+         send all packet directed to VIP that don't match the above flows to\n+         connection tracker.\n+      </li>\n+\n+      <li>\n+         A priority-100 flow sends the packets to connection tracker based\n+         on a hint provided by the previous tables\n+         (with a match for <code>reg0[0] == 1</code>) by using the\n+         <code>ct_next;</code> action.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 8: <code>from-lport</code> ACL hints</h3>\n+\n+    <p>\n+      This table consists of logical flows that set hints\n+      (<code>reg0</code> bits) to be used in the next stage, in the ACL\n+      processing table, if stateful ACLs or load balancers are configured.\n+      Multiple hints can be set for the same packet.\n+      The possible hints are:\n+    </p>\n+    <ul>\n+      <li>\n+        <code>reg0[7]</code>: the packet might match an\n+        <code>allow-related</code> ACL and might have to commit the\n+        connection to conntrack.\n+      </li>\n+      <li>\n+        <code>reg0[8]</code>: the packet might match an\n+        <code>allow-related</code> ACL but there will be no need to commit\n+        the connection to conntrack because it already exists.\n+      </li>\n+      <li>\n+        <code>reg0[9]</code>: the packet might match a\n+        <code>drop/reject</code>.\n+      </li>\n+      <li>\n+        <code>reg0[10]</code>: the packet might match a\n+        <code>drop/reject</code> ACL but the connection was previously\n+        allowed so it might have to be committed again with\n+        <code>ct_label=1/1</code>.\n+      </li>\n+    </ul>\n+\n+    <p>\n+      The table contains the following flows:\n+    </p>\n+    <ul>\n+      <li>\n+        A priority-65535 flow to advance to the next table if the logical\n+        switch has <code>no</code> ACLs configured, otherwise a\n+        priority-0 flow to advance to the next table.\n+      </li>\n+    </ul>\n+\n+    <ul>\n+      <li>\n+        A priority-7 flow that matches on packets that initiate a new session.\n+        This flow sets <code>reg0[7]</code> and <code>reg0[9]</code> and\n+        then advances to the next table.\n+      </li>\n+      <li>\n+        A priority-6 flow that matches on packets that are in the request\n+        direction of an already existing session that has been marked\n+        as blocked. This flow sets <code>reg0[7]</code> and\n+        <code>reg0[9]</code> and then advances to the next table.\n+      </li>\n+      <li>\n+        A priority-5 flow that matches untracked packets. This flow sets\n+        <code>reg0[8]</code> and <code>reg0[9]</code> and then advances to\n+        the next table.\n+      </li>\n+      <li>\n+        A priority-4 flow that matches on packets that are in the request\n+        direction of an already existing session that has not been marked\n+        as blocked. This flow sets <code>reg0[8]</code> and\n+        <code>reg0[10]</code> and then advances to the next table.\n+      </li>\n+      <li>\n+        A priority-3 flow that matches on packets that are in not part of\n+        established sessions. This flow sets <code>reg0[9]</code> and then\n+        advances to the next table.\n+      </li>\n+      <li>\n+        A priority-2 flow that matches on packets that are part of an\n+        established session that has been marked as blocked.\n+        This flow sets <code>reg0[9]</code> and then advances to the next\n+        table.\n+      </li>\n+      <li>\n+        A priority-1 flow that matches on packets that are part of an\n+        established session that has not been marked as blocked.\n+        This flow sets <code>reg0[10]</code> and then advances to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress table 9: <code>from-lport</code> ACL evaluation before LB</h3>\n+\n+    <p>\n+      Logical flows in this table closely reproduce those in the\n+      <code>ACL</code> table in the <code>OVN_Northbound</code> database\n+      for the <code>from-lport</code> direction without the option\n+      <code>apply-after-lb</code> set or set to <code>false</code>.\n+      The <code>priority</code> values from the <code>ACL</code> table have a\n+      limited range and have 1000 added to them to leave room for OVN default\n+      flows at both higher and lower priorities.\n+    </p>\n+    <ul>\n+      <li>\n+        This table is responsible for evaluating ACLs, and setting a register\n+        bit to indicate whether the ACL decided to allow, drop, or reject the\n+        traffic. The allow bit is <code>reg8[16]</code>. The drop bit is\n+        <code>reg8[17]</code>. All flows in this table will advance the packet\n+        to the next table, where the bits from before are evaluated to\n+        determine what to do with the packet. Any flows in this table that\n+        intend for the packet to pass will set <code>reg8[16]</code> to 1,\n+        even if an ACL with an allow-type action was not matched. This lets the\n+        next table know to allow the traffic to pass. These bits will be\n+        referred to as the \"allow\", \"drop\", and \"reject\" bits in the upcoming\n+        paragraphs.\n+      </li>\n+      <li>\n+        If the <code>tier</code> column has been configured on the ACL, then\n+        OVN will also match the current tier counter against the configured\n+        ACL tier. OVN keeps count of the current tier in\n+        <code>reg8[30..31]</code>.\n+      </li>\n+      <li>\n+        <code>allow</code> ACLs translate into logical flows that set the allow\n+        bit to 1 and advance the packet to the next table. If there are any\n+        stateful ACLs on this datapath, then <code>allow</code> ACLs set the\n+        allow bit to one and in addition perform <code>ct_commit;</code> (which\n+        acts as a hint for future tables to commit the connection to\n+        conntrack). In case the <code>ACL</code> has a label then\n+        <code>reg3</code> is loaded with the label value and\n+        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n+        next tables to commit the label to conntrack).\n+      </li>\n+      <li>\n+        <code>allow-related</code> ACLs translate into logical flows that set\n+        the allow bit and additionally have <code>ct_commit { ct_label=0/1; };\n+        next;</code> actions for new connections and <code>reg0[1] = 1;\n+        next;</code> for existing connections.  In case the <code>ACL</code>\n+        has a label then <code>reg3</code> is loaded with the label value and\n+        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n+        next tables to commit the label to conntrack).\n+      </li>\n+      <li>\n+        For <code>allow</code> and <code>allow-related</code> ACL, an\n+        additonal set of registers get set in case the ACL has the column\n+        <code>network_function_group</code> set to the <var>id</var> of one\n+        of the entities in <code>Network_Function_Group</code> table. The\n+        <var>id</var> is an internally generated unique identifier for a\n+        <code>Network_Function_Group</code> entity. The flow sets\n+        <code>reg8[21] = 1</code> (to indicate need for packet redirection),\n+        <code>reg8[22] = 1</code> (to indicate this is a request packet) and\n+        <code>reg0[22..29] = <var>id</var></code>. These registers are later\n+        used in the <code>Network Function</code> table.\n+      </li>\n+\n+      <li>\n+        <code>allow-stateless</code> ACLs translate into logical flows that set\n+        the allow bit and advance to the next table.\n+      </li>\n+      <li>\n+        <code>reject</code> ACLs translate into logical flows with that set the\n+        reject bit and advance to the next table.\n+      </li>\n+      <li>\n+        <code>pass</code> ACLs translate into logical flows that do not set the\n+        allow, drop, or reject bit and advance to the next table.\n+      </li>\n+      <li>\n+        Other ACLs set the drop bit and advance to the next table for new or\n+        untracked connections. For known connections, they set the drop bit,\n+        as well as running the <code>ct_commit { ct_label=1/1; };</code>\n+        action.  Setting <code>ct_label</code> marks a connection as one that\n+        was previously allowed, but should no longer be allowed due to a policy\n+        change.\n+      </li>\n+    </ul>\n+\n+    <p>\n+      This table contains a priority-65535 flow to set the allow bit and\n+      advance to the next table if the logical switch has <code>no</code>\n+      ACLs configured, otherwise a priority-0 flow to advance to the next\n+      table is added. This flow does not set the allow bit, so that the next\n+      table can decide whether to allow or drop the packet based on the value\n+      of the <ref column=\"options:default_acl_drop\" table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> column of the <ref table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> table.\n+    </p>\n+\n+    <p>\n+      A priority-65532 flow is added that sets the allow bit for\n+      IPv6 Neighbor solicitation, Neighbor discover, Router solicitation,\n+      Router advertisement and MLD packets regardless of other ACLs defined.\n+    </p>\n+\n+    <p>\n+      If the logical datapath has a stateful ACL or a load balancer with VIP\n+      configured, the following flows will also be added:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        If <ref column=\"options:default_acl_drop\" table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> is <code>false</code> or not set, a priority-1\n+        flow that sets the hint to commit IP traffic that is not part of\n+        established sessions to the connection tracker (with action\n+        <code>reg0[1] = 1; next;</code>).  This is needed for\n+        the default allow policy because, while the initiator's direction\n+        may not have any stateful rules, the server's may and then\n+        its return traffic would not be known and marked as invalid.\n+      </li>\n+\n+      <li>\n+        A priority-1 flow that sets the allow bit and sets the hint to commit\n+        IP traffic to the connection tracker (with action <code>reg0[1] = 1;\n+        next;</code>).  This is needed for the default allow policy because,\n+        while the initiator's direction may not have any stateful rules, the\n+        server's may and then its return traffic would not be known and marked\n+        as invalid.\n+      </li>\n+\n+      <li>\n+        A priority-65532 flow that sets the allow bit for any traffic in the\n+        reply direction for a connection that has been committed to the\n+        connection tracker (i.e., established flows), as long as\n+        the committed flow does not have <code>ct_mark.blocked</code> set.\n+        We only handle traffic in the reply direction here because\n+        we want all packets going in the request direction to still\n+        go through the flows that implement the currently defined\n+        policy based on ACLs.  If a connection is no longer allowed by\n+        policy, <code>ct_mark.blocked</code> will get set and packets in the\n+        reply direction will no longer be allowed, either. This flow also\n+        clears the register bits <code>reg0[9]</code> and\n+        <code>reg0[10]</code> and sets register bit <code>reg0[17]</code>.\n+        If ACL logging and logging of related packets is enabled, then a\n+        companion priority-65533 flow will be installed that\n+        accomplishes the same thing but also logs the traffic.\n+      </li>\n+\n+      <li>\n+        The priority-65532 flows that allow response and related traffic, also\n+        set <code>reg8[21] = ct_label.nf</code>, which gets checked in\n+        the <code>Network Function</code> table.\n+      </li>\n+\n+      <li>\n+        A priority-65532 flow that sets the allow bit for any traffic that is\n+        considered related to a committed flow in the connection tracker (e.g.,\n+        an ICMP Port Unreachable from a non-listening UDP port), as long\n+        as the committed flow does not have <code>ct_mark.blocked</code> set.\n+        This flow also applies NAT to the related traffic so that ICMP headers\n+        and the inner packet have correct addresses.\n+        If ACL logging and logging of related packets is enabled, then a\n+        companion priority-65533 flow will be installed that accomplishes the\n+        same thing but also logs the traffic.\n+      </li>\n+\n+      <li>\n+        A priority-65532 flow that sets the drop bit for all traffic marked by\n+        the connection tracker as invalid.\n+      </li>\n+\n+      <li>\n+        A priority-65532 flow that sets the drop bit for all traffic in the\n+        reply direction with <code>ct_mark.blocked</code> set meaning that the\n+        connection should no longer be allowed due to a policy change.  Packets\n+        in the request direction are skipped here to let a newly created\n+        ACL re-allow this connection.\n+      </li>\n+    </ul>\n+\n+    <p>\n+      If the logical datapath has any ACL or a load balancer with VIP\n+      configured, the following flow will also be added:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority 34000 logical flow is added for each logical switch datapath\n+        with the match <code>eth.dst = <var>E</var></code> to allow the service\n+        monitor reply packet destined to <code>ovn-controller</code>\n+        that sets the allow bit, where <var>E</var> is the\n+        service monitor mac defined in the\n+        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 10: <code>from-lport</code> ACL sampling</h3>\n+\n+    <p>\n+      Logical flows in this table sample traffic matched by\n+      <code>from-lport</code> ACLs with sampling enabled.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        If no ACLs have sampling enabled, then a priority 0 flow is installed\n+        that matches everything and advances to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_new configured a priority 1100 flow is\n+        installed that matches on the saved observation_point_id value.\n+        This flow generates a <code>sample()</code> action and then advances\n+        the packet to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_est configured a priority 1200 flow is\n+        installed that matches on the saved observation_point_id value\n+        for established traffic in the original direction.  This flow\n+        generates a <code>sample()</code> action and then advances\n+        the packet to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_est configured a priority 1200 flow is\n+        installed that matches on the saved observation_point_id\n+        value for established traffic in the reply direction.  This flow\n+        generates a <code>sample()</code> action and then advances\n+        the packet to the next table.  Note: this flow is installed in the\n+        opposite pipeline (in the ingress pipeline for ACLs applied in the\n+        egress direction and in the egress pipeline for ACLs applied in the\n+        ingress direction).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 11: <code>from-lport</code> ACL action</h3>\n+\n+    <p>\n+      Logical flows in this table decide how to proceed based on the values of\n+      the allow, drop, and reject bits that may have been set in the previous\n+      table.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        If no ACLs are configured, then a priority 0 flow is installed that\n+        matches everything and advances to the next table.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will advance the packet to the\n+        next table if the allow bit is set.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will run the <code>drop;</code>\n+        action if the drop bit is set.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will run the <code>tcp_reset\n+        { output &lt;-&gt; inport; next(pipeline=egress,table=5);}</code>\n+        action for TCP connections,<code>icmp4/icmp6</code> action\n+        for UDP connections, and <code>sctp_abort {output &lt;-%gt; inport;\n+        next(pipeline=egress,table=5);}</code> action for SCTP associations.\n+      </li>\n+\n+      <li>\n+        If any ACLs have tiers configured on them, then three priority 500\n+        flows are installed. If the current tier counter is 0, 1, or 2, then\n+        the current tier counter is incremented by one and the packet is sent\n+        back to the previous table for re-evaluation.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 12: <code>from-lport</code> QoS</h3>\n+\n+    <p>\n+      Logical flows in this table closely reproduce those in the\n+      <code>QoS</code> table with the <code>action</code> or\n+      <code>bandwidth</code> column set in the\n+      <code>OVN_Northbound</code> database for the\n+      <code>from-lport</code> direction.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For every qos_rules entry in a logical switch with DSCP marking,\n+        packet marking or metering enabled a flow will be added at the priority\n+        mentioned in the QoS table.\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 13: Connection Tracking Field Extraction</h3>\n+\n+    <p>\n+      This table extracts connection tracking fields for new connections\n+      to be used by subsequent load balancing stages.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-100 flow matches <code>ct.new &amp;&amp; ip</code> and\n+        extracts connection tracking protocol and destination port information\n+        into registers <code>reg1[16..23]</code> (protocol) and\n+        <code>reg1[0..15]</code> (destination port) using the actions\n+        <code>reg1[16..23] = ct_proto(); reg1[0..15] = ct_tp_dst(); next;</code>.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow matches all packets and advances to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 14: Load balancing affinity check</h3>\n+\n+    <p>\n+      Load balancing affinity check table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a switch in\n+        <code>OVN_Northbound</code> database where a positive affinity timeout\n+        is specified in <code>options</code> column, that includes a L4 port\n+        <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>,\n+        a priority-100 flow is added. For IPv4 <var>VIPs</var>, the flow\n+        matches <code>ct.new &amp;&amp; ip &amp;&amp; ip4.dst == <var>VIP</var>\n+        &amp;&amp; reg1[16..23] == <var>PROTO_NUM</var> &amp;&amp;\n+        reg1[0..15] == <var>PORT</var></code>. For IPv6\n+        <var>VIPs</var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n+        ip6.dst == <var>VIP</var> &amp;&amp; reg1[16..23] ==\n+        <var>PROTO_NUM</var> &amp;&amp; reg1[0..15] == <var>PORT</var></code>.\n+        The flow's action is <code>reg9[6] = chk_lb_aff(); next;</code>.\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 15: LB</h3>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a switch in\n+        <code>OVN_Northbound</code> database where a positive affinity timeout\n+        is specified in <code>options</code> column, that includes a L4 port\n+        <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>,\n+        a priority-150 flow is added. For IPv4 <var>VIPs</var>, the flow\n+        matches <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp; ip &amp;&amp;\n+        ip4.dst == <var>VIP</var> &amp;&amp; <var>P</var>.dst == <var>PORT\n+        </var></code>. For IPv6 <var>VIPs</var>, the flow matches\n+        <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp; ip &amp;&amp;\n+        ip6.dst == <var> VIP </var>&amp;&amp; <var>P</var> &amp;&amp;\n+        <var>P</var>.dst == <var> PORT</var></code>.\n+        The flow's action is <code>ct_lb_mark(<var>args</var>)</code>, where\n+        <var>args</var> contains comma separated IP addresses (and optional\n+        port numbers) to load balance to.  The address family of the IP\n+        addresses of <var>args</var> is the same as the address family\n+        of <var>VIP</var>.\n+      </li>\n+\n+      <li>\n+        For all the configured load balancing rules for a switch in\n+        <code>OVN_Northbound</code> database that includes a L4 port\n+        <var>PORT</var> of protocol <var>P</var> and IP address\n+        <var>VIP</var>, a priority-120 flow is added.  For IPv4 <var>VIPs\n+        </var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n+        ip4.dst == <var>VIP</var> &amp;&amp; reg1[16..23] ==\n+        <var>PROTO_NUM</var> &amp;&amp; reg1[0..15] == <var>PORT</var></code>.\n+        For IPv6 <var>VIPs</var>,\n+        the flow matches <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>\n+        VIP </var>&amp;&amp; reg1[16..23] == <var>PROTO_NUM</var> &amp;&amp;\n+        reg1[0..15] == <var>PORT</var></code>. The flow's action is\n+        <code>ct_lb_mark(<var>args</var>)\n+        </code>, where <var>args</var> contains comma separated IP addresses\n+        (and optional port numbers) to load balance to.  The address family of\n+        the IP addresses of <var>args</var> is the same as the address family\n+        of <var>VIP</var>. If health check is enabled, then <var>args</var>\n+        will only contain those endpoints whose service monitor status entry\n+        in <code>OVN_Southbound</code> db is either <code>online</code> or\n+        empty.  For IPv4 traffic the flow also loads the original destination\n+        IP and transport port in registers <code>reg1</code> and\n+        <code>reg2</code>.  For IPv6 traffic the flow also loads the original\n+        destination IP and transport port in registers <code>xxreg1</code> and\n+        <code>reg2</code>.\n+        The above flow is created even if the load balancer is attached to a\n+        logical router connected to the current logical switch and\n+        the <code>install_ls_lb_from_router</code> variable in\n+        <ref table=\"NB_Global\" column=\"options\"/> is set to true.\n+      </li>\n+      <li>\n+        For all the configured load balancing rules for a switch in\n+        <code>OVN_Northbound</code> database that includes just an IP address\n+        <var>VIP</var> to match on, OVN adds a priority-110 flow.  For IPv4\n+        <var>VIPs</var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n+        ip4.dst == <var>VIP</var></code>. For IPv6 <var>VIPs</var>,\n+        the flow matches <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>\n+        VIP</var></code>. The action on this flow is <code>\n+        ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains comma\n+        separated IP addresses of the same address family as <var>VIP</var>.\n+        For IPv4 traffic the flow also loads the original destination\n+        IP and transport port in registers <code>reg1</code> and\n+        <code>reg2</code>.  For IPv6 traffic the flow also loads the original\n+        destination IP and transport port in registers <code>xxreg1</code> and\n+        <code>reg2</code>.\n+        The above flow is created even if the load balancer is attached to a\n+        logical router connected to the current logical switch and\n+        the <code>install_ls_lb_from_router</code> variable in\n+        <ref table=\"NB_Global\" column=\"options\"/> is set to true.\n+      </li>\n+\n+      <li>\n+        If the load balancer is created with <code>--reject</code> option and\n+        it has no active backends, a TCP reset segment (for tcp) or an ICMP\n+        port unreachable packet (for all other kind of traffic) will be sent\n+        whenever an incoming packet is received for this load-balancer.\n+        Please note using <code>--reject</code> option will disable\n+        empty_lb SB controller event for this load balancer.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 16: Load balancing affinity learn</h3>\n+\n+    <p>\n+      Load balancing affinity learn table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a switch in\n+        <code>OVN_Northbound</code> database where a positive affinity timeout\n+        <var>T</var> is specified in <code>options</code> column, that includes\n+        a L4 port <var>PORT</var> of protocol <var>P</var> and IP address\n+        <var>VIP</var>, a priority-100 flow is added. For IPv4 <var>VIPs</var>,\n+        the flow matches <code>reg9[6] == 0 &amp;&amp; ct.new &amp;&amp; ip\n+        &amp;&amp; ip4.dst == <var>VIP</var> &amp;&amp; <var>P</var>.dst ==\n+        <var>PORT</var></code>. For IPv6 <var>VIPs</var>, the flow matches\n+        <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>VIP</var>\n+        &amp;&amp; <var>P</var> &amp;&amp; <var>P</var>.dst == <var>PORT</var>\n+        </code>. The flow's action is <code>commit_lb_aff(vip =\n+        <var>VIP</var>:<var>PORT</var>, backend = <var>backend ip</var>:\n+        <var>backend port</var>, proto = <var>P</var>, timeout = <var>T</var>);\n+        </code>.\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 17: Pre-Hairpin</h3>\n+    <ul>\n+      <li>\n+        If the logical switch has load balancer(s) configured, then a\n+        priority-100 flow is added with the match\n+        <code>ip &amp;&amp; ct.trk</code> to check if the\n+        packet needs to be hairpinned (if after load balancing the destination\n+        IP matches the source IP) or not by executing the actions\n+        <code>reg0[6] = chk_lb_hairpin();</code> and\n+        <code>reg0[12] = chk_lb_hairpin_reply();</code> and advances the packet\n+        to the next table.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 18: Nat-Hairpin</h3>\n+    <ul>\n+      <li>\n+         If the logical switch has load balancer(s) configured, then a\n+         priority-100 flow is added with the match\n+         <code>ip &amp;&amp; ct.new &amp;&amp; ct.trk &amp;&amp;\n+         reg0[6] == 1</code> which hairpins the traffic by\n+         NATting source IP to the load balancer VIP by executing the action\n+         <code>ct_snat_to_vip</code> and advances the packet to the next table.\n+      </li>\n+\n+      <li>\n+         If the logical switch has load balancer(s) configured, then a\n+         priority-100 flow is added with the match\n+         <code>ip &amp;&amp; ct.est &amp;&amp; ct.trk &amp;&amp;\n+         reg0[6] == 1</code> which hairpins the traffic by\n+         NATting source IP to the load balancer VIP by executing the action\n+         <code>ct_snat</code> and advances the packet to the next table.\n+      </li>\n+\n+      <li>\n+         If the logical switch has load balancer(s) configured, then a\n+         priority-90 flow is added with the match\n+         <code>ip &amp;&amp; reg0[12] == 1</code> which matches on the replies\n+         of hairpinned traffic (i.e., destination IP is VIP,\n+         source IP is the backend IP and source L4 port is backend port for L4\n+         load balancers) and executes <code>ct_snat</code> and advances the\n+         packet to the next table.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 19: Hairpin</h3>\n+    <ul>\n+      <li>\n+        <p>\n+          If logical switch has attached logical switch port of <var>vtep</var>\n+          type, then for each distributed gateway router port <var>RP</var>\n+          attached to this logical switch and has chassis redirect port\n+          <var>cr-RP</var>, a priority-2000 flow is added with the match\n+          <pre>\n+<code>reg0[14] == 1 &amp;&amp; is_chassis_resident(<var>cr-RP</var>)</code>\n+          </pre>\n+          and action <code>next;</code>.\n+        </p>\n+\n+        <p>\n+          <code>reg0[14]</code> register bit is set in the ingress L2 port\n+          security check table for traffic received from HW VTEP (ramp) ports.\n+        </p>\n+      </li>\n+\n+      <li>\n+        If logical switch has attached logical switch port of <var>vtep</var>\n+        type, then a priority-1000 flow that matches on\n+        <code>reg0[14]</code> register bit for the traffic received from HW\n+        VTEP (ramp) ports.  This traffic is passed to ingress table\n+        ls_in_l2_lkup.\n+      </li>\n+      <li>\n+        A priority-1 flow that hairpins traffic matched by non-default\n+        flows in the Pre-Hairpin table. Hairpinning is done at L2, Ethernet\n+        addresses are swapped and the packets are looped back on the input\n+        port.\n+      </li>\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress table 20: <code>from-lport</code> ACL evaluation after LB</h3>\n+\n+    <p>\n+      Logical flows in this table closely reproduce those in the\n+      <code>ACL eval</code> table in the <code>OVN_Northbound</code> database\n+      for the <code>from-lport</code> direction with the option\n+      <code>apply-after-lb</code> set to <code>true</code>.\n+      The <code>priority</code> values from the <code>ACL</code> table have a\n+      limited range and have 1000 added to them to leave room for OVN default\n+      flows at both higher and lower priorities. The flows in this table\n+      indicate the ACL verdict by setting <code>reg8[16]</code> for\n+      <code>allow-type</code> ACLs, <code>reg8[17]</code> for <code>drop</code>\n+      ACLs, and <code>reg8[17]</code> for <code>reject</code> ACLs, and then\n+      advancing the packet to the next table. These will be reffered to as the\n+      allow bit, drop bit, and reject bit throughout the documentation for this\n+      table and the next one.\n+    </p>\n+\n+    <p>\n+      Like with ACLs that are evaluated before load balancers, if the ACL is\n+      configured with a tier value, then the current tier counter, supplied\n+      in reg8[30..31] is matched against the ACL's configured tier in addition\n+      to the ACL's match.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <code>allow</code> apply-after-lb ACLs translate into logical flows\n+        that set the allow bit.  If there are any stateful ACLs\n+        (including both before-lb and after-lb ACLs)\n+        on this datapath, then <code>allow</code> ACLs also run\n+        <code>ct_commit; next;</code> (which acts as a hint for an upcoming\n+        table to commit the connection to conntrack). In case the\n+        <code>ACL</code> has a label then <code>reg3</code> is loaded with the\n+        label value and <code>reg0[13]</code> bit is set to 1 (which acts as a\n+        hint for the next tables to commit the label to conntrack).\n+      </li>\n+      <li>\n+        <code>allow-related</code> apply-after-lb ACLs translate into logical\n+        flows that set the allow bit and run the\n+        <code>ct_commit {ct_label=0/1; }; next;</code> actions for new\n+        connections and <code>reg0[1] = 1; next;</code> for existing\n+        connections.  In case the <code>ACL</code> has a label then\n+        <code>reg3</code> is loaded with the label value and\n+        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n+        next tables to commit the label to conntrack).\n+      </li>\n+      <li>\n+        <code>allow-stateless</code> apply-after-lb ACLs translate into logical\n+        flows that set the allow bit and advance to the next table.\n+      </li>\n+      <li>\n+        <code>reject</code> apply-after-lb ACLs translate into logical\n+        flows that set the reject bit and advance to the next table.\n+      </li>\n+      <li>\n+        <code>pass</code> apply-after-lb ACLs translate into logical flows that\n+        do not set the allow, drop, or reject bit and advance to the next\n+        table.\n+      </li>\n+      <li>\n+        Other apply-after-lb ACLs set the drop bit for new or untracked\n+        connections and <code>ct_commit { ct_label=1/1; }</code> for known\n+        connections.  Setting <code>ct_label</code> marks a connection\n+        as one that was previously allowed, but should no longer be\n+        allowed due to a policy change.\n+      </li>\n+    </ul>\n+\n+    <ul>\n+      <li>\n+        One priority-65532 flow matching packets with <code>reg0[17]</code>\n+        set (either replies to existing sessions or traffic related to\n+        existing sessions) and allows these by setting the allow bit and\n+        advancing to the next table.\n+      </li>\n+    </ul>\n+\n+    <ul>\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 21: <code>from-lport</code> ACL sampling after LB</h3>\n+\n+    <p>\n+      Logical flows in this table sample traffic matched by\n+      <code>from-lport</code> ACLs (evaluation after LB) with sampling enabled.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        If no ACLs have sampling enabled, then a priority 0 flow is installed\n+        that matches everything and advances to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_new configured a priority 1100 flow is\n+        installed that matches on the saved observation_point_id value.\n+        This flow generates a <code>sample()</code> action and then advances\n+        the packet to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_est configured a priority 1200 flow is\n+        installed that matches on the saved observation_point_id value\n+        for established traffic in the original direction.  This flow\n+        generates a <code>sample()</code> action and then advances\n+        the packet to the next table.\n+      </li>\n+\n+      <li>\n+        For each ACL with sample_est configured a priority 1200 flow is\n+        installed that matches on the saved observation_point_id\n+        value for established traffic in the reply direction.  This flow\n+        generates a <code>sample()</code> action and then advances\n+        the packet to the next table.  Note: this flow is installed in the\n+        opposite pipeline (in the ingress pipeline for ACLs applied in the\n+        egress direction and in the egress pipeline for ACLs applied in the\n+        ingress direction).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 22: <code>from-lport</code> ACL action after LB</h3>\n+\n+    <p>\n+      Logical flows in this table decide how to proceed based on the values of\n+      the allow, drop, and reject bits that may have been set in the previous\n+      table.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        If no ACLs are configured, then a priority 0 flow is installed that\n+        matches everything and advances to the next table.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will advance the packet to the\n+        next table if the allow bit is set.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will run the <code>drop;</code>\n+        action if the drop bit is set.\n+      </li>\n+\n+      <li>\n+        A priority 1000 flow is installed that will run the <code>tcp_reset\n+        { output &lt;-&gt; inport; next(pipeline=egress,table=5);}</code>\n+        action for TCP connections,<code>icmp4/icmp6</code> action\n+        for UDP connections, and <code>sctp_abort {output &lt;-%gt; inport;\n+        next(pipeline=egress,table=5);}</code> action for SCTP associations.\n+      </li>\n+\n+      <li>\n+        If any ACLs have tiers configured on them, then three priority 500\n+        flows are installed. If the current tier counter is 0, 1, or 2, then\n+        the current tier counter is incremented by one and the packet is sent\n+        back to the previous table for re-evaluation.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 23: Pre Network Function</h3>\n+    <p>\n+      This stage selects the active network function from a\n+      <code>Network_Function_Group</code> based on the network function group\n+      ID set by the ACL eval stage earlier. This stage is applicable for\n+      request packets of <code>from-lport</code> ACLs\n+      (<code>reg8[22] == 1</code>). Response packets for\n+      <code>to-lport</code> ACLs bypass this stage and use\n+      <code>ct_label.nf_id</code> directly in the Network Function table.\n+    </p>\n+\n+    <p>\n+      A network function group can contain one or more network functions.\n+      Health monitoring is performed by sending datapath probes as per\n+      parameters defined in <code>Network_Function_Health_Check</code>. This\n+      stage selects one of the healthy network functions. If none are healthy,\n+      the behavior follows the <code>fallback</code> column configured in the\n+      <code>Network_Function_Group</code> table. If health monitoring is not\n+      configured, any one from the group is selected.\n+    </p>\n+\n+    <p>\n+      When a request packet matches a <code>from-lport</code> ACL with\n+      <code>network_function_group</code> set, the ACL eval stage sets\n+      <code>reg8[21] = 1</code> (NF enabled), <code>reg8[22] = 1</code>\n+      (request direction), and <code>reg0[22..29]</code> to the network\n+      function group ID. This table then selects the active network function\n+      from the group and overwrites <code>reg0[22..29]</code> with the\n+      specific <code>id</code> of a <code>Network_Function</code> table entry.\n+      The subsequent Network Function table uses this NF ID to redirect packets\n+      to the appropriate network function port. In the future, this stage will\n+      be extended to support network function load balancing.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For each network_function_group <var>id</var> with an active network\n+        function, a priority-99 flow matches <code>reg8[21] == 1 &amp;&amp;\n+        reg8[22] == 1 &amp;&amp; reg0[22..29] == <var>id</var></code> and\n+        sets <code>reg0[22..29] = <var>nf_id</var>; next;</code> where\n+        <var>nf_id</var> is the ID of the active network function. This\n+        prepares request packets that matched a <code>from-lport</code> ACL\n+        with network_function_group for redirection in the subsequent Network\n+        Function table.\n+      </li>\n+\n+      <li>\n+        For each network function group with <var>id</var> that has\n+        <code>fallback</code> set to <code>fail-open</code>, a priority-10 flow\n+        matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n+        reg0[22..29] == <var>id</var></code> and sets <code>reg8[21] = 0;\n+        reg0[22..29] = 0; next;</code>. This clears both the NF enabled bit and\n+        the NF group ID, allowing packets to continue processing through the\n+        pipeline without network function redirection when no active network\n+        function is available (fail-open behavior).\n+      </li>\n+\n+      <li>\n+        A priority-1 flow matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1\n+        </code> and sets <code>reg0[22..29] = 0; next;</code>. This is a\n+        catch-all flow for network function groups with <code>fallback</code>\n+        set to <code>fail-close</code> (or default) when no active network\n+        function is available. It clears only the NF group ID, leaving the NF\n+        enabled bit set. These packets will be dropped by the priority-1 drop\n+        rule in the subsequent Network Function table (fail-close behavior).\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 24: Stateful</h3>\n+\n+    <ul>\n+      <li>\n+        A priority 100 flow is added which commits the packet to the conntrack\n+        and sets the most significant 32-bits of <code>ct_label</code> with the\n+        <code>reg3</code> value based on the hint provided by previous tables\n+        (with a match for <code>reg0[1] == 1 &amp;&amp; reg0[13] == 1</code>).\n+        This is used by the <code>ACLs</code> with label to commit the label\n+        value to conntrack.\n+      </li>\n+\n+      <li>\n+        For <code>ACLs</code> without label, a second priority-100 flow commits\n+        packets to connection tracker using <code>ct_commit; next;</code>\n+        action based on a hint provided by the previous tables (with a match\n+        for <code>reg0[1] == 1 &amp;&amp; reg0[13] == 0</code>).\n+      </li>\n+\n+      <li>\n+        Corresponding to each of the two priority 100 flows above, a priority\n+        110 flow is added, which has the following extra match and\n+        action, but otherwise identical to the priority 100 flow.\n+        Match: <code>reg8[21] == 1</code> (packet matched an ACL with\n+        <code>network_function_group</code> set)\n+        Action: <code>ct_label.nf = 1;\n+        ct_label.nf_id = reg0[22..29];</code>\n+        This is to commit the network_function information in conntrack so that\n+        the response and related packets can be redirected to it as well.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 25: Network Function</h3>\n+    <p>\n+      This table implements packet redirection to network functions. When a\n+      packet matches an ACL with <code>network_function_group</code> column\n+      set to the <code>id</code> of a <code>Network_Function_Group</code>\n+      table entry, the ACL eval stage sets <code>reg8[21] = 1</code> (NF\n+      enabled), <code>reg8[22] = 1</code> (request direction), and\n+      <code>reg0[22..29]</code> to the network function group ID. The Pre\n+      Network Function stage then selects the active network function from the\n+      group and overwrites <code>reg0[22..29]</code> with the specific\n+      <code>id</code> of a <code>Network_Function</code> table entry. This\n+      table uses that NF ID to redirect packets to the appropriate network\n+      function port.\n+    </p>\n+\n+    <p>\n+      This table handles request packets for <code>from-lport</code> ACLs\n+      and response packets for <code>to-lport</code> ACLs. For\n+      <code>from-lport</code> ACLs, request packets are redirected to the\n+      network function's <code>inport</code>, and corresponding\n+      response/related packets are handled in the egress pipeline. For\n+      <code>to-lport</code> ACLs, request packets are handled in the egress\n+      pipeline, but corresponding response/related packets for those flows\n+      are redirected here using the network function ID stored in\n+      <code>ct_label.nf_id</code> during request processing.\n+    </p>\n+\n+    <p>\n+      If the network function ports are not present on this logical switch,\n+      their child ports (if any) are used. In the statements below, network\n+      function ports refer to either the parent or child ports as applicable to\n+      this logical switch.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For each network_function port <var>P</var>, a priority-100 flow is\n+        added that matches <code>inport == <var>P</var></code> and advances\n+        packets to the next table. Thus packets coming from network function\n+        are not subject to redirection. This flow also sets\n+        <code>reg5[16..31] = ct_label.tun_if_id</code>. This is used for\n+        tunneling packet to originating host in case of cross host traffic\n+        redirection for VLAN subnet. This ct_label field stores the openflow\n+        tunnel interface id of the originating host for this connection and\n+        gets populated in egress <code>Stateful</code> table.\n+      </li>\n+\n+      <li>\n+        For each active network function with <var>id</var> that is referenced\n+        in a network function group, a priority-99 flow matches\n+        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n+        reg0[22..29] == <var>id</var></code> and sets\n+        <code>outport=<var>P</var>; output;</code> where <var>P</var> is the\n+        <code>inport</code> of that network function. This redirects request\n+        packets for flows matching <code>from-lport</code> ACLs with\n+        network_function_group to the specific network function selected by\n+        the Pre Network Function stage.\n+      </li>\n+\n+      <li>\n+        For each active network function with <var>id</var> that is referenced\n+        in a network function group, a priority-99 rule matches\n+        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 0 &amp;&amp;\n+        ct_label.nf_id == <var>id</var></code> and takes identical action as\n+        above. This redirects response and related packets for\n+        <code>to-lport</code> ACLs to the same network function that handled\n+        the request, using the NF ID stored in the connection tracking label.\n+      </li>\n+\n+      <li>\n+        In each of the above cases, when the same packet comes out unchanged\n+        through the other port of the network_function, it would match the\n+        priority 100 flow and be forwarded to the next table.\n+      </li>\n+\n+      <li>\n+        One priority-100 rule to skip redirection of multicast packets that hit\n+        a network_function ACL. Match on <code>reg8[21] == 1 &amp;&amp;\n+        eth.mcast</code> and action is to advance to the next table.\n+      </li>\n+\n+      <li>\n+        One priority-1 rule that checks <code>reg8[21] == 1</code>, and drops\n+        such packets. This is to address the case where a packet hit an ACL\n+        with network function but the network function does not have ports or\n+        child ports on this logical switch.\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 26: ARP/ND responder</h3>\n+\n+    <p>\n+      This table implements ARP/ND responder in a logical switch for known\n+      IPs.  The advantage of the ARP responder flow is to limit ARP\n+      broadcasts by locally responding to ARP requests without the need to\n+      send to other hypervisors.  One common case is when the inport is a\n+      logical port associated with a VIF and the broadcast is responded to\n+      on the local hypervisor rather than broadcast across the whole\n+      network and responded to by the destination VM.  This behavior is\n+      proxy ARP.\n+    </p>\n+\n+    <p>\n+      ARP requests arrive from VMs from a logical switch inport of type\n+      default.  For this case, the logical switch proxy ARP rules can be\n+      for other VMs or logical router ports.  Logical switch proxy ARP\n+      rules may be programmed both for mac binding of IP addresses on\n+      other logical switch VIF ports (which are of the default logical\n+      switch port type, representing connectivity to VMs or containers),\n+      and for mac binding of IP addresses on logical switch router type\n+      ports, representing their logical router port peers.  In order to\n+      support proxy ARP for logical router ports, an IP address must be\n+      configured on the logical switch router type port, with the same\n+      value as the peer logical router port.  The configured MAC addresses\n+      must match as well.  When a VM sends an ARP request for a distributed\n+      logical router port and if the peer router type port of the attached\n+      logical switch does not have an IP address configured, the ARP request\n+      will be broadcast on the logical switch.  One of the copies of the ARP\n+      request will go through the logical switch router type port to the\n+      logical router datapath, where the logical router ARP responder will\n+      generate a reply.  The MAC binding of a distributed logical router,\n+      once learned by an associated VM, is used for all that VM's\n+      communication needing routing.  Hence, the action of a VM re-arping for\n+      the mac binding of the logical router port should be rare.\n+    </p>\n+\n+    <p>\n+      Logical switch ARP responder proxy ARP rules can also be hit when\n+      receiving ARP requests externally on a L2 gateway port.  In this case,\n+      the hypervisor acting as an L2 gateway, responds to the ARP request on\n+      behalf of a destination VM.\n+    </p>\n+\n+    <p>\n+      Note that ARP requests received from <code>localnet</code> logical\n+      inports can either go directly to VMs, in which case the VM responds or\n+      can hit an ARP responder for a logical router port if the packet is used\n+      to resolve a logical router port next hop address.  In either case,\n+      logical switch ARP responder rules will not be hit.  It contains these\n+      logical flows:\n+     </p>\n+\n+    <ul>\n+      <li>\n+        If packet was received from HW VTEP (ramp switch), and this packet is\n+        ARP or Neighbor Solicitation, such packet is passed to next table with\n+        max proirity.  ARP/ND requests from HW VTEP must be handled in logical\n+        router ingress pipeline.\n+      </li>\n+      <li>\n+        If the logical switch has no router ports with options:arp_proxy\n+        configured add a priority-100 flows to skip the ARP responder if inport\n+        is of type <code>localnet</code> advances directly to the next table.\n+        ARP requests sent to <code>localnet</code> ports can be received by\n+        multiple hypervisors.  Now, because the same mac binding rules are\n+        downloaded to all hypervisors, each of the multiple hypervisors will\n+        respond.  This will confuse L2 learning on the source of the ARP\n+        requests.  ARP requests received on an inport of type\n+        <code>router</code> are not expected to hit any logical switch ARP\n+        responder flows.  However, no skip flows are installed for these\n+        packets, as there would be some additional flow cost for this and the\n+        value appears limited.\n+      </li>\n+\n+      <li>\n+        <p>\n+          If inport <code>V</code> is of type <code>virtual</code> adds a\n+          priority-100 logical flows for each <var>P</var> configured in the\n+          <ref table=\"Logical_Switch_Port\" column=\"options:virtual-parents\"/>\n+          column with the match\n+        </p>\n+        <pre>\n+<code>inport == <var>P</var> &amp;&amp; &amp;&amp; ((arp.op == 1 &amp;&amp; arp.spa == <var>VIP</var> &amp;&amp; arp.tpa == <var>VIP</var>) || (arp.op == 2 &amp;&amp; arp.spa == <var>VIP</var>))</code>\n+<code>inport == <var>P</var> &amp;&amp; &amp;&amp; ((nd_ns &amp;&amp; ip6.dst == <var>{VIP, NS_MULTICAST_ADDR}</var> &amp;&amp; nd.target == <var>VIP</var>) || (nd_na &amp;&amp; nd.target == <var>VIP</var>))</code>\n+        </pre>\n+\n+        <p>\n+          and applies the action\n+        </p>\n+        <pre>\n+<code>bind_vport(<var>V</var>, inport);</code>\n+        </pre>\n+\n+        <p>\n+         and advances the packet to the next table.\n+        </p>\n+\n+        <p>\n+          Where <var>VIP</var> is the virtual ip configured in the column\n+          <ref table=\"Logical_Switch_Port\" column=\"options:virtual-ip\"/> and\n+          NS_MULTICAST_ADDR is solicited-node multicast address corresponding\n+          to the VIP.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-50 flows that match only broadcast ARP requests to each\n+          known IPv4 address <var>A</var> of every logical switch port, and\n+          respond with ARP replies directly with corresponding Ethernet\n+          address <var>E</var>:\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+arp.op = 2; /* ARP reply. */\n+arp.tha = arp.sha;\n+arp.sha = <var>E</var>;\n+arp.tpa = arp.spa;\n+arp.spa = <var>A</var>;\n+outport = inport;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          These flows are omitted for logical ports (other than router ports or\n+          <code>localport</code> ports) that are down (unless <code>\n+          ignore_lsp_down</code> is configured as true in <code>options</code>\n+          column of <code>NB_Global</code> table of the <code>Northbound</code>\n+          database), for logical ports of type <code>virtual</code>, for\n+          logical ports with 'unknown' address set, for logical ports with\n+          the <code>options:disable_arp_nd_rsp=true</code> and for logical\n+          ports of a logical switch configured with\n+          <code>other_config:vlan-passthru=true</code>.\n+        </p>\n+\n+      <p>\n+        The above ARP responder flows are added for the list of IPv4 addresses\n+        if defined in <code>options:arp_proxy</code> column of\n+        <code>Logical_Switch_Port</code> table for logical switch ports of\n+        type <code>router</code>.\n+      </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-50 flows that match IPv6 ND neighbor solicitations to\n+          each known IP address <var>A</var> (and <var>A</var>'s\n+          solicited node address) of every logical switch port except of type\n+          router, and respond with neighbor advertisements directly with\n+          corresponding Ethernet address <var>E</var>:\n+        </p>\n+\n+        <pre>\n+nd_na {\n+    eth.src = <var>E</var>;\n+    ip6.src = <var>A</var>;\n+    nd.target = <var>A</var>;\n+    nd.tll = <var>E</var>;\n+    outport = inport;\n+    flags.loopback = 1;\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          Priority-50 flows that match IPv6 ND neighbor solicitations to\n+          each known IP address <var>A</var> (and <var>A</var>'s\n+          solicited node address) of logical switch port of type router, and\n+          respond with neighbor advertisements directly with\n+          corresponding Ethernet address <var>E</var>:\n+        </p>\n+\n+        <pre>\n+nd_na_router {\n+    eth.src = <var>E</var>;\n+    ip6.src = <var>A</var>;\n+    nd.target = <var>A</var>;\n+    nd.tll = <var>E</var>;\n+    outport = inport;\n+    flags.loopback = 1;\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          These flows are omitted for logical ports (other than router ports or\n+          <code>localport</code> ports) that are down (unless <code>\n+          ignore_lsp_down</code> is configured as true in <code>options</code>\n+          column of <code>NB_Global</code> table of the <code>Northbound</code>\n+          database), for logical ports of type <code>virtual</code> and for\n+          logical ports with 'unknown' address set.\n+        </p>\n+\n+        <p>\n+          The above NDP responder flows are added for the list of\n+          IPv6 addresses if defined in <code>options:arp_proxy</code> column of\n+          <code>Logical_Switch_Port</code> table for logical switch ports of\n+          type <code>router</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-100 flows with match criteria like the ARP and ND flows\n+          above, except that they only match packets from the\n+          <code>inport</code> that owns the IP addresses in question, with\n+          action <code>next;</code>.  These flows prevent OVN from replying to,\n+          for example, an ARP request emitted by a VM for its own IP address.\n+          A VM only makes this kind of request to attempt to detect a duplicate\n+          IP address assignment, so sending a reply will prevent the VM from\n+          accepting the IP address that it owns.\n+        </p>\n+\n+        <p>\n+          In place of <code>next;</code>, it would be reasonable to use\n+          <code>drop;</code> for the flows' actions.  If everything is working\n+          as it is configured, then this would produce equivalent results,\n+          since no host should reply to the request.  But ARPing for one's own\n+          IP address is intended to detect situations where the network is not\n+          working as configured, so dropping the request would frustrate that\n+          intent.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each <var>SVC_MON_SRC_IP</var> defined in the value of\n+          the <ref column=\"ip_port_mappings:ENDPOINT_IP\"\n+          table=\"Load_Balancer\" db=\"OVN_Northbound\"/> column of\n+          <ref table=\"Load_Balancer\" db=\"OVN_Northbound\"/> table, priority-110\n+          logical flow is added with the match\n+          <code>arp.tpa == <var>SVC_MON_SRC_IP</var>\n+          &amp;&amp; &amp;&amp; arp.op == 1</code> and applies the action\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+arp.op = 2; /* ARP reply. */\n+arp.tha = arp.sha;\n+arp.sha = <var>E</var>;\n+arp.tpa = arp.spa;\n+arp.spa = <var>A</var>;\n+outport = inport;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          where <var>E</var> is the service monitor source mac defined in\n+          the <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+          db=\"OVN_Northbound\"/> column in the <ref table=\"NB_Global\"\n+          db=\"OVN_Northbound\"/> table. This mac is used as the source mac\n+          in the service monitor packets for the load balancer endpoint IP\n+          health checks.\n+        </p>\n+\n+        <p>\n+          <var>SVC_MON_SRC_IP</var> is used as the source ip in the\n+          service monitor IPv4 packets for the load balancer endpoint IP\n+          health checks.\n+        </p>\n+\n+        <p>\n+          These flows are required if an ARP request is sent for the IP\n+          <var>SVC_MON_SRC_IP</var>.\n+        </p>\n+\n+        <p>\n+          For IPv6 the similar flow is added with the following action\n+        </p>\n+\n+        <pre>\n+nd_na {\n+    eth.dst = eth.src;\n+    eth.src = <var>E</var>;\n+    ip6.src = <var>A</var>;\n+    nd.target = <var>A</var>;\n+    nd.tll = <var>E</var>;\n+    outport = inport;\n+    flags.loopback = 1;\n+    output;\n+};\n+        </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each <var>VIP</var> configured in the table\n+          <ref table=\"Forwarding_Group\" db=\"OVN_Northbound\"/>\n+          a priority-50 logical flow is added with the match\n+          <code>arp.tpa == <var>vip</var> &amp;&amp; &amp;&amp; arp.op == 1\n+          </code> and applies the action\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+arp.op = 2; /* ARP reply. */\n+arp.tha = arp.sha;\n+arp.sha = <var>E</var>;\n+arp.tpa = arp.spa;\n+arp.spa = <var>A</var>;\n+outport = inport;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          where <var>E</var> is the forwarding group's mac defined in\n+          the <ref column=\"vmac\" table=\"Forwarding_Group\"\n+          db=\"OVN_Northbound\"/>.\n+        </p>\n+\n+        <p>\n+          <var>A</var> is used as either the destination ip for load balancing\n+          traffic to child ports or as nexthop to hosts behind the child ports.\n+        </p>\n+\n+        <p>\n+          These flows are required to respond to an ARP request if an ARP\n+          request is sent for the IP <var>vip</var>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets and advances to\n+        the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 27: DHCP option processing</h3>\n+\n+    <p>\n+      This table adds the DHCPv4 options to a DHCPv4 packet from the\n+      logical ports configured with IPv4 address(es) and DHCPv4 options,\n+      and similarly for DHCPv6 options. This table also adds flows for the\n+      logical ports of type <code>external</code>.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-100 logical flow is added for these logical ports\n+          which matches the IPv4 packet with <code>udp.src</code> = 68 and\n+          <code>udp.dst</code> = 67 and applies the action\n+          <code>put_dhcp_opts</code> and advances the packet to the next table.\n+        </p>\n+\n+        <pre>\n+reg0[3] = put_dhcp_opts(offer_ip = <var>ip</var>, <var>options</var>...);\n+next;\n+        </pre>\n+\n+        <p>\n+          For DHCPDISCOVER and DHCPREQUEST, this transforms the packet into a\n+          DHCP reply, adds the DHCP offer IP <var>ip</var> and options to the\n+          packet, and stores 1 into reg0[3].  For other kinds of packets, it\n+          just stores 0 into reg0[3].  Either way, it continues to the next\n+          table.\n+        </p>\n+\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-100 logical flow is added for these logical ports\n+          which matches the IPv6 packet with <code>udp.src</code> = 546 and\n+          <code>udp.dst</code> = 547 and applies the action\n+          <code>put_dhcpv6_opts</code> and advances the packet to the next\n+          table.\n+        </p>\n+\n+        <pre>\n+reg0[3] = put_dhcpv6_opts(ia_addr = <var>ip</var>, <var>options</var>...);\n+next;\n+        </pre>\n+\n+        <p>\n+          For DHCPv6 Solicit/Request/Confirm packets, this transforms the\n+          packet into a DHCPv6 Advertise/Reply, adds the DHCPv6 offer IP\n+          <var>ip</var> and options to the packet, and stores 1 into reg0[3].\n+          For other kinds of packets, it just stores 0 into reg0[3]. Either\n+          way, it continues to the next table.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advances to table 16.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 28: DHCP responses</h3>\n+\n+    <p>\n+      This table implements DHCP responder for the DHCP replies generated by\n+      the previous table.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority 100 logical flow is added for the logical ports configured\n+          with DHCPv4 options which matches IPv4 packets with <code>udp.src == 68\n+          &amp;&amp; udp.dst == 67 &amp;&amp; reg0[3] == 1</code> and\n+          responds back to the <code>inport</code> after applying these\n+          actions.  If <code>reg0[3]</code> is set to 1, it means that the\n+          action <code>put_dhcp_opts</code> was successful.\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+ip4.src = <var>S</var>;\n+udp.src = 67;\n+udp.dst = 68;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          where <var>E</var> is the server MAC address and <var>S</var> is the\n+          server IPv4 address defined in the DHCPv4 options. Note that\n+          <code>ip4.dst</code> field is handled by <code>put_dhcp_opts</code>.\n+        </p>\n+\n+        <p>\n+          (This terminates ingress packet processing; the packet does not go\n+           to the next ingress table.)\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority 100 logical flow is added for the logical ports configured\n+          with DHCPv6 options which matches IPv6 packets with <code>udp.src == 546\n+          &amp;&amp; udp.dst == 547 &amp;&amp; reg0[3] == 1</code> and\n+          responds back to the <code>inport</code> after applying these\n+          actions.  If <code>reg0[3]</code> is set to 1, it means that the\n+          action <code>put_dhcpv6_opts</code> was successful.\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+ip6.dst = <var>A</var>;\n+ip6.src = <var>S</var>;\n+udp.src = 547;\n+udp.dst = 546;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          where <var>E</var> is the server MAC address and <var>S</var> is the\n+          server IPv6 LLA address  generated from the <code>server_id</code>\n+          defined in the DHCPv6 options and <var>A</var> is\n+          the IPv6 address defined in the logical port's addresses column.\n+        </p>\n+\n+        <p>\n+          (This terminates packet processing; the packet does not go on the\n+          next ingress table.)\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advances to table 17.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 29 DNS Lookup</h3>\n+\n+    <p>\n+      This table looks up and resolves the DNS names to the corresponding\n+      configured IP address(es).\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-100 logical flow for each logical switch datapath\n+          if it is configured with DNS records, which matches the IPv4 and IPv6\n+          packets with <code>udp.dst</code> = 53 and applies the action\n+          <code>dns_lookup</code> and advances the packet to the next table.\n+        </p>\n+\n+        <pre>\n+reg0[4] = dns_lookup(); next;\n+        </pre>\n+\n+        <p>\n+          For valid DNS packets, this transforms the packet into a DNS\n+          reply if the DNS name can be resolved, and stores 1 into reg0[4].\n+          For failed DNS resolution or other kinds of packets, it just stores\n+          0 into reg0[4]. Either way, it continues to the next table.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 30 DNS Responses</h3>\n+\n+    <p>\n+      This table implements DNS responder for the DNS replies generated by\n+      the previous table.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-100 logical flow for each logical switch datapath\n+          if it is configured with DNS records, which matches the IPv4 and IPv6\n+          packets with <code>udp.dst = 53 &amp;&amp; reg0[4] == 1</code>\n+          and responds back to the <code>inport</code> after applying these\n+          actions.  If <code>reg0[4]</code> is set to 1, it means that the\n+          action <code>dns_lookup</code> was successful.\n+        </p>\n+\n+        <pre>\n+eth.dst &lt;-&gt; eth.src;\n+ip4.src &lt;-&gt; ip4.dst;\n+udp.dst = udp.src;\n+udp.src = 53;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          (This terminates ingress packet processing; the packet does not go\n+           to the next ingress table.)\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress table 31 External ports</h3>\n+\n+    <p>\n+      Traffic from the <code>external</code> logical ports enter the ingress\n+      datapath pipeline via the <code>localnet</code> port. This table adds the\n+      below logical flows to handle the traffic from these ports.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-100 flow is added for each <code>external</code> logical\n+          port which doesn't reside on a chassis to drop the ARP/IPv6 NS\n+          request to the router IP(s) (of the logical switch) which matches\n+          on the <code>inport</code> of the <code>external</code> logical port\n+          and the valid <code>eth.src</code> address(es) of the\n+          <code>external</code> logical port.\n+        </p>\n+\n+        <p>\n+          This flow guarantees that the ARP/NS request to the router IP\n+          address from the external ports is responded by only the chassis\n+          which has claimed these external ports. All the other chassis,\n+          drops these packets.\n+        </p>\n+\n+        <p>\n+          A priority-100 flow is added for each <code>external</code> logical\n+          port which doesn't reside on a chassis to drop any packet destined\n+          to the router mac - with the match\n+          <code>inport == <var>external</var> &amp;&amp;\n+          eth.src == <var>E</var> &amp;&amp; eth.dst == <var>R</var>\n+          &amp;&amp; !is_chassis_resident(\"<var>external</var>\")</code>\n+          where <var>E</var> is the external port mac and <var>R</var> is the\n+          router port mac.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advances to table 20.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 32 Destination Lookup</h3>\n+\n+    <p>\n+      This table implements switching behavior.  It contains these logical\n+      flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-110 flow with the match\n+        <code>eth.src == <var>E</var></code> for all logical switch\n+        datapaths and applies the action <code>handle_svc_check(inport)</code>.\n+        Where <var>E</var> is the service monitor mac defined in the\n+        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> table.\n+      </li>\n+\n+      <li>\n+        A priority-100 flow that punts all IGMP/MLD packets to\n+        <code>ovn-controller</code> if multicast snooping is enabled on the\n+        logical switch.\n+      </li>\n+\n+      <li>\n+        A priority-100 flow that forwards all DHCP broadcast packets coming\n+        from VIFs to the logical router port's MAC when DHCP relay is enabled\n+        on the logical switch.\n+      </li>\n+\n+      <li>\n+        A priority-100 flow that matches <code>reg8[23] == 1</code> and does\n+        <code>output</code> action. This ensures that packets that got injected\n+        back into this table from egress table <code>Network Function</code>\n+        (after it set the <code>outport</code> for packet redirection) get\n+        forwarded without any further processing.\n+      </li>\n+\n+      <li>\n+        <p>\n+          For any logical port that's defined as a target of routing protocol\n+          redirecting (via <code>routing-protocol-redirect</code> option set on\n+          Logical Router Port), we redirect the traffic related to protocols\n+          specified in <code>routing-protocols</code> option. It's acoomplished\n+          with following priority-100 flows:\n+        </p>\n+        <ul>\n+          <li>\n+            Flows that match Logical Router Port's IPs and destination port of\n+            the routing daemon are redirected to this port to allow external\n+            peers' connection to the daemon listening on this port.\n+          </li>\n+          <li>\n+            Flows that match Logical Router Port's IPs and source port of\n+            the routing daemon are redirected to this port to allow replies\n+            from the peers.\n+          </li>\n+        </ul>\n+        <p>\n+          In addition to this, we add priority-100 rules that\n+          <code>clone</code> ARP replies and IPv6 Neighbor Advertisements to\n+          this port as well. These allow to build proper ARP/IPv6 neighbor\n+          list on this port.\n+        </p>\n+      </li>\n+\n+      <li>\n+        Priority-90 flows for transit switches that forward registered\n+        IP multicast traffic to their corresponding multicast group , which\n+        <code>ovn-northd</code> creates based on learnt\n+        <ref table=\"IGMP_Group\" db=\"OVN_Southbound\"/> entries.\n+      </li>\n+\n+      <li>\n+        Priority-90 flows that forward registered IP multicast traffic to\n+        their corresponding multicast group, which <code>ovn-northd</code>\n+        creates based on learnt <ref table=\"IGMP_Group\" db=\"OVN_Southbound\"/>\n+        entries.  The flows also forward packets to the\n+        <code>MC_MROUTER_FLOOD</code> multicast group, which\n+        <code>ovn-nortdh</code> populates with all the logical ports that\n+        are connected to logical routers with\n+        <ref column=\"options\" table=\"Logical_Router\"/>:mcast_relay='true'.\n+      </li>\n+\n+      <li>\n+        A priority-85 flow that forwards all IP multicast traffic destined to\n+        224.0.0.X to the <code>MC_FLOOD_L2</code> multicast group, which\n+        <code>ovn-northd</code> populates with all non-router logical ports.\n+      </li>\n+\n+      <li>\n+        A priority-85 flow that forwards all IP multicast traffic destined to\n+        reserved multicast IPv6 addresses (RFC 4291, 2.7.1, e.g.,\n+        Solicited-Node multicast) to the <code>MC_FLOOD</code> multicast\n+        group, which <code>ovn-northd</code> populates with all enabled\n+        logical ports.\n+      </li>\n+\n+      <li>\n+        A priority-80 flow that forwards all unregistered IP multicast traffic\n+        to the <code>MC_STATIC</code> multicast group, which\n+        <code>ovn-northd</code> populates with all the logical ports that\n+        have <ref column=\"options\" table=\"Logical_Switch_Port\"/>\n+        <code>:mcast_flood='true'</code>. The flow also forwards\n+        unregistered IP multicast traffic to the <code>MC_MROUTER_FLOOD</code>\n+        multicast group, which <code>ovn-northd</code> populates with all the\n+        logical ports connected to logical routers that have\n+        <ref column=\"options\" table=\"Logical_Router\"/>\n+        <code>:mcast_relay='true'</code>.\n+      </li>\n+\n+      <li>\n+        A priority-80 flow that drops all unregistered IP multicast traffic\n+        if <ref column=\"other_config\" table=\"Logical_Switch\"/>\n+        <code>:mcast_snoop='true'</code> and\n+        <ref column=\"other_config\" table=\"Logical_Switch\"/>\n+        <code>:mcast_flood_unregistered='false'</code> and the switch is\n+        not connected to a logical router that has\n+        <ref column=\"options\" table=\"Logical_Router\"/>\n+        <code>:mcast_relay='true'</code> and the switch doesn't have any\n+        logical port with <ref column=\"options\" table=\"Logical_Switch_Port\"/>\n+        <code>:mcast_flood='true'</code>.\n+      </li>\n+\n+      <li>\n+        Priority-80 flows for each IP address/VIP/NAT address owned by a\n+        router port connected to the switch. These flows match ARP requests\n+        and ND packets for the specific IP addresses.  Matched packets are\n+        forwarded only to the router that owns the IP address and to the\n+        <code>MC_FLOOD_L2</code> multicast group which contains all non-router\n+        logical ports.\n+      </li>\n+\n+      <li>\n+        Priority-75 flows for each port connected to a logical router\n+        matching self originated ARP request/RARP request/ND packets.  These\n+        packets are flooded to the <code>MC_FLOOD_L2</code> which contains all\n+        non-router logical ports.\n+      </li>\n+\n+      <li>\n+        A priority-72 flow that outputs all ND NA (Neighbor Advertisement),\n+        ND RS (Router Solicitation) and ND RA (Router Advertisement) packets\n+        with an Ethernet broadcast or multicast <code>eth.dst</code> to the\n+        <code>MC_FLOOD</code> multicast group, which includes all ports.\n+        ND NA must reach routers for neighbor learning; ND RS must reach\n+        routers so they can respond with Router Advertisements; ND RA must\n+        reach routers for proper IPv6 network operation.\n+      </li>\n+\n+      <li>\n+        A priority-72 flow that outputs all ARP requests and ND NS (Neighbor\n+        Solicitation) packets with an Ethernet broadcast or multicast\n+        <code>eth.dst</code> to the <code>MC_FLOOD_L2</code> multicast group\n+        if <code>other_config:broadcast-arps-to-all-routers=false</code>.\n+      </li>\n+\n+      <li>\n+        A priority-71 flow that outputs all ARP packets with an Ethernet\n+        broadcast or multicast <code>eth.dst</code> to the\n+        <code>MC_FLOOD</code> multicast group.\n+      </li>\n+\n+      <li>\n+        A priority-71 flow that outputs all IP packets with an Ethernet\n+        broadcast or multicast <code>eth.dst</code> to the\n+        <code>MC_FLOOD_L2</code> multicast group, which contains only\n+        non-router logical ports.  If any connected router has\n+        <code>options:mcast_relay=true</code>, the packet is also cloned to\n+        the <code>MC_MROUTER_FLOOD</code> multicast group (which contains\n+        only the router ports with relay enabled).  If any port has\n+        <code>options:mcast_flood=true</code>, it is also cloned to the\n+        <code>MC_STATIC</code> multicast group.  This prevents IP multicast\n+        from being unnecessarily forwarded to routers that would drop it.\n+      </li>\n+\n+      <li>\n+        A priority-70 flow that outputs all packets with an Ethernet broadcast\n+        or multicast <code>eth.dst</code> to the <code>MC_FLOOD_L2</code>\n+        multicast group.\n+      </li>\n+\n+      <li>\n+        <p>\n+          One priority-50 flow that matches each known Ethernet address against\n+          <code>eth.dst</code>.  Action of this flow outputs the packet to the\n+          single associated output port if it is enabled. <code>drop;</code>\n+          action is applied if LSP is disabled.  If the logical switch port\n+          of type VIF has the option <code>options:pkt_clone_type</code>\n+          is set to the value <code>mc_unknown</code>, then the packet is\n+          also forwarded to the  <code>MC_UNKNOWN</code> multicast group.\n+        </p>\n+\n+        <p>\n+          The above flow is not added if the logical switch port is of type\n+          VIF, has <code>unknown</code> as one of its address and has the\n+          option <code>options:force_fdb_lookup</code> set to true.\n+        </p>\n+\n+        <p>\n+          For the Ethernet address on a logical switch port of type\n+          <code>router</code>, when that logical switch port's\n+          <ref column=\"addresses\" table=\"Logical_Switch_Port\"\n+          db=\"OVN_Northbound\"/> column is set to <code>router</code> and\n+          the connected logical router port has a gateway chassis:\n+        </p>\n+\n+        <ul>\n+          <li>\n+            The flow for the connected logical router port's Ethernet\n+            address is only programmed on the gateway chassis.\n+          </li>\n+\n+          <li>\n+            If the logical router has rules specified in\n+            <ref column=\"nat\" table=\"Logical_Router\" db=\"OVN_Northbound\"/> with\n+            <ref column=\"external_mac\" table=\"NAT\" db=\"OVN_Northbound\"/>, then\n+            those addresses are also used to populate the switch's destination\n+            lookup on the chassis where\n+            <ref column=\"logical_port\" table=\"NAT\" db=\"OVN_Northbound\"/> is\n+            resident.\n+          </li>\n+        </ul>\n+\n+        <p>\n+          For the Ethernet address on a logical switch port of type\n+          <code>router</code>, when that logical switch port's\n+          <ref column=\"addresses\" table=\"Logical_Switch_Port\"\n+          db=\"OVN_Northbound\"/> column is set to <code>router</code> and\n+          the connected logical router port specifies a\n+          <code>reside-on-redirect-chassis</code> and the logical router\n+          to which the connected logical router port belongs to has a\n+          distributed gateway LRP:\n+        </p>\n+\n+        <ul>\n+          <li>\n+            The flow for the connected logical router port's Ethernet\n+            address is only programmed on the gateway chassis.\n+          </li>\n+        </ul>\n+\n+        <p>\n+          For each forwarding group configured on the logical switch datapath,\n+          a priority-50 flow that matches on <code>eth.dst == <var>VIP</var>\n+          </code> with an action of <code>fwd_group(childports=<var>args\n+          </var>)</code>, where <var>args</var> contains comma separated\n+          logical switch child ports to load balance to.\n+          If <code>liveness</code> is enabled, then action also includes\n+          <code> liveness=true</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that matches all packets with the\n+        action <code>outport = get_fdb(eth.dst); next;</code>. The action\n+        <code>get_fdb</code> gets the port for the <code>eth.dst</code>\n+        in the MAC learning table of the logical switch datapath. If there\n+        is no entry for <code>eth.dst</code> in the MAC learning table,\n+        then it stores <code>none</code> in the <code>outport</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 33 Destination unknown</h3>\n+\n+    <p>\n+      This table handles the packets whose destination was not found or\n+      and looked up in the MAC learning table of the logical switch\n+      datapath. It contains the following flows.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          Priority 50 flow with the match <code>outport == <var>P</var></code>\n+          is added for each disabled Logical Switch Port <code>P</code>.  This\n+          flow has action <code>drop;</code>.\n+        </p>\n+      </li>\n+      <li>\n+        <p>\n+          If the logical switch has logical ports with 'unknown' addresses set,\n+          then the below logical flow is added\n+        </p>\n+\n+        <ul>\n+          <li>\n+            Priority 50 flow with the match <code>outport == \"none\"</code> then\n+            outputs them to the <code>MC_UNKNOWN</code> multicast group, which\n+            <code>ovn-northd</code> populates with all enabled logical ports\n+            that accept unknown destination packets.  As a small optimization,\n+            if no logical ports accept unknown destination packets,\n+            <code>ovn-northd</code> omits this multicast group and logical\n+            flow.\n+          </li>\n+        </ul>\n+\n+        <p>\n+          If the logical switch has no logical ports with 'unknown' address\n+          set, then the below logical flow is added\n+        </p>\n+\n+        <ul>\n+          <li>\n+            Priority 50 flow with the match <code>outport == none</code>\n+            and drops the packets.\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+        One priority-0 fallback flow that outputs the packet to the egress\n+        stage with the outport learnt from <code>get_fdb</code> action.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 0: Lookup MAC address learning table</h3>\n+    <p>\n+      This is similar to ingress table <code>Lookup MAC address learning table\n+      </code> with the difference that MAC address learning lookup is only\n+      happening for ports with type <code>remote</code> whose port security is\n+      disabled and 'unknown' address set.  This stage facilitates MAC learning\n+      on a transit switch connecting multiple availability zones.\n+    </p>\n+\n+    <h3>Egress Table 1: Learn MAC of 'unknown' ports.</h3>\n+    <p>\n+      This is similar to ingress table <code>Learn MAC of 'unknown' ports\n+      </code> with the difference that MAC address learning is only happening\n+      for ports with type <code>remote</code> whose port security is disabled\n+      and 'unknown' address set.  This stage facilitates MAC learning on a\n+      transit switch connecting multiple availability zones.\n+    </p>\n+\n+    <h3>Egress Table 2: <code>to-lport</code> Pre-ACLs</h3>\n+\n+    <p>\n+      This is similar to ingress table <code>Pre-ACLs</code> except for\n+     <code>to-lport</code> traffic.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>eth.src == <var>E</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>E</var>\n+      is the service monitor mac defined in the\n+      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> table.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>outport == <var>I</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>I</var>\n+      is the peer of a logical router port. This flow is added to\n+      skip the connection tracking of packets which will be entering\n+      logical router datapath from logical switch datapath for routing.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow for each network_function\n+      <code>inport</code> <var>P</var> that matches <code>inport ==\n+      <var>P</var></code>. The action is to skip all the egress tables up to\n+      the <code>Network Function</code> table and advance the packet directly\n+      to the table after that. This is for the case where packet redirection\n+      happens in egress <code>Network Function</code> table. The same packet\n+      when it comes out of the other port of network function, they should not\n+      be processed again by the same egress stages, specially they should\n+      skip the conntrack processing.\n+    </p>\n+\n+    <h3>Egress Table 3: Pre-LB</h3>\n+\n+    <p>\n+      This table is similar to ingress table <code>Pre-LB</code>.  It\n+      contains a priority-0 flow that simply moves traffic to the next table.\n+      Moreover it contains two priority-110 flows to move multicast, IPv6\n+      Neighbor Discovery and MLD traffic to the next table. If any load\n+      balancing rules exist for the datapath, a priority-100 flow is added with\n+      a match of <code>ip</code> and action of <code>reg0[2] = 1; next;</code>\n+      to act as a hint for table <code>Pre-stateful</code> to send IP packets\n+      to the connection tracker for packet de-fragmentation and possibly DNAT\n+      the destination VIP to one of the selected backend for already committed\n+      load balanced traffic.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>eth.src == <var>E</var></code> for all logical switch\n+      datapaths to move traffic to the next table. Where <var>E</var>\n+      is the service monitor mac defined in the\n+      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+      db=\"OVN_Northbound\"/> table.\n+    </p>\n+\n+    <p>\n+      This table also has a priority-110 flow with the match\n+      <code>outport == <var>I</var></code> for all logical switch\n+      datapaths to move traffic to the next table, and, if there are no\n+      stateful_acl, clear the ct_state. Where <var>I</var>\n+      is the peer of a logical router port. This flow is added to\n+      skip the connection tracking of packets which will be entering\n+      logical router datapath from logical switch datapath for routing.\n+    </p>\n+\n+    <p>\n+      When <code>enable-stateless-acl-with-lb</code> is enabled,\n+      additional priority-115 flow is added to match traffic with\n+      <code>REGBIT_ACL_STATELESS</code> set and pass connection tracking.\n+    </p>\n+\n+    <h3>Egress Table 4: Pre-stateful</h3>\n+\n+    <p>\n+      This is similar to ingress table <code>Pre-stateful</code>.  This table\n+      adds the below 3 logical flows.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A Priority-120 flow that send the packets to connection tracker using\n+        <code>ct_lb_mark;</code> as the action so that the already established\n+        traffic gets unDNATted from the backend IP to the load balancer VIP\n+        based on a hint provided by the previous tables with a match\n+        for <code>reg0[2] == 1</code>.  If the packet was not DNATted earlier,\n+        then <code>ct_lb_mark</code> functions like <code>ct_next</code>.\n+      </li>\n+\n+      <li>\n+        A priority-100 flow sends the packets to connection tracker based\n+        on a hint provided by the previous tables\n+        (with a match for <code>reg0[0] == 1</code>) by using the\n+        <code>ct_next;</code> action.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advance to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 5: <code>from-lport</code> ACL hints</h3>\n+    <p>\n+      This is similar to ingress table <code>ACL hints</code>.\n+    </p>\n+\n+    <h3>Egress Table 6: <code>to-lport</code> ACL evaluation</h3>\n+\n+    <p>\n+      This is similar to ingress table <code>ACL eval</code> except for\n+      <code>to-lport</code> ACLs. As a reminder, these flows use the\n+      following register bits to indicate their verdicts.\n+      <code>Allow-type</code> ACLs set <code>reg8[16]</code>, <code>drop</code>\n+      ACLs set <code>reg8[17]</code>, and <code>reject</code> ACLs set\n+      <code>reg8[18]</code>.\n+    </p>\n+\n+    <p>\n+      Also like with ingress ACLs, egress ACLs can have network_function_group\n+      <var>id</var> and in that case the flow will set <code>reg8[21] = 1;\n+      reg8[22] = 1; reg0[22..29] = <var>id</var></code>. These registers are used\n+      in the <code>Network Function</code> table.\n+    </p>\n+\n+    <p>\n+      Also like with ingress ACLs, egress ACLs can have a configured\n+      <code>tier</code>. If a tier is configured, then the current tier\n+      counter is evaluated against the ACL's configured tier in addition\n+      to the ACL's match. The current tier counter is stored in\n+      <code>reg8[30..31]</code>.\n+    </p>\n+\n+    <p>\n+      Similar to ingress table, a priority-65532 flow is added to allow IPv6\n+      Neighbor solicitation, Neighbor discover, Router solicitation, Router\n+      advertisement and MLD packets regardless of other ACLs defined.\n+    </p>\n+\n+    <p>\n+      In addition, the following flows are added.\n+    </p>\n+    <ul>\n+      <li>\n+        A priority 34000 logical flow is added for each logical port which\n+        has DHCPv4 options defined to allow the DHCPv4 reply packet and which has\n+        DHCPv6 options defined to allow the DHCPv6 reply packet from the\n+        <code>Ingress Table 26: DHCP responses</code>. This is indicated by\n+        setting the allow bit.\n+      </li>\n+\n+      <li>\n+        A priority 34000 logical flow is added for each logical switch datapath\n+        configured with DNS records with the match <code>udp.dst = 53</code>\n+        to allow the DNS reply packet from the\n+        <code>Ingress Table 28: DNS responses</code>. This is indicated by\n+        setting the allow bit.\n+      </li>\n+\n+      <li>\n+        A priority 34000 logical flow is added for each logical switch datapath\n+        with the match <code>eth.src = <var>E</var></code> to allow the service\n+        monitor request packet generated by <code>ovn-controller</code>\n+        with the action <code>next</code>, where <var>E</var> is the\n+        service monitor mac defined in the\n+        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n+        db=\"OVN_Northbound\"/> table. This is indicated by setting the allow\n+        bit.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 7: <code>to-lport</code> ACL sampling</h3>\n+    <p>\n+      This is similar to ingress table <code>ACL sampling</code>.\n+    </p>\n+\n+    <h3>Egress Table 8: <code>to-lport</code> ACL action</h3>\n+    <p>\n+      This is similar to ingress table <code>ACL action</code>.\n+    </p>\n+\n+    <h3>Egress Table 9: Mirror </h3>\n+\n+    <p>\n+      Overlay remote mirror table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For each logical switch port with an attached mirror, a logical flow\n+        with a priority of 100 is added. This flow matches all outcoming\n+        packets to the attached port, clones them, and forwards the cloned\n+        packets to the mirror target port.\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+\n+      <li>\n+        A logical flow added for each Mirror Rule in Mirror table attached\n+        to logical switch ports, matches all outcoming packets that match\n+        rules and clones the packet and sends cloned packet to mirror\n+        target port.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 10: <code>to-lport</code> QoS</h3>\n+\n+    <p>\n+      This is similar to ingress table <code>QoS</code> except\n+      they apply to <code>to-lport</code> QoS rules.\n+    </p>\n+\n+    <h3>Egress Table 11: Pre Network Function</h3>\n+\n+    <p>\n+      This stage selects the active network function from a\n+      <code>Network_Function_Group</code> based on the network function group\n+      ID set by the ACL eval stage earlier. This stage is applicable for\n+      request packets of <code>to-lport</code> ACLs\n+      (<code>reg8[22] == 1</code>). Response packets for\n+      <code>from-lport</code> ACLs bypass this stage and use\n+      <code>ct_label.nf_id</code> directly in the Network Function table.\n+    </p>\n+\n+    <p>\n+      A network function group can contain one or more network functions.\n+      Health monitoring is performed by sending datapath probes as per\n+      parameters defined in <code>Network_Function_Health_Check</code>. This\n+      stage selects one of the healthy network functions. If none are healthy,\n+      the behavior follows the <code>fallback</code> column configured in the\n+      <code>Network_Function_Group</code> table. If health monitoring is not\n+      configured, any one from the group is selected.\n+    </p>\n+\n+    <p>\n+      When a request packet matches a <code>to-lport</code> ACL with\n+      <code>network_function_group</code> set, the ACL eval stage sets\n+      <code>reg8[21] = 1</code> (NF enabled), <code>reg8[22] = 1</code>\n+      (request direction), and <code>reg0[22..29]</code> to the network\n+      function group ID. This table then selects the active network function\n+      from the group and overwrites <code>reg0[22..29]</code> with the\n+      specific <code>id</code> of a <code>Network_Function</code> table entry.\n+      The subsequent Network Function table uses this NF ID to redirect packets\n+      to the appropriate network function port. In the future, this stage will\n+      be extended to support network function load balancing.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For each network function group with <var>id</var> that has an active\n+        network function, a priority-99 flow matches <code>reg8[21] == 1\n+        &amp;&amp; reg8[22] == 1 &amp;&amp; reg0[22..29] == <var>id</var></code>\n+        and sets <code>reg0[22..29] = <var>nf_id</var>; next;</code> where\n+        <var>nf_id</var> is the <code>id</code> of the active\n+        <code>Network_Function</code> selected from the group. This prepares\n+        request packets that matched a <code>to-lport</code> ACL with\n+        network_function_group for redirection in the subsequent Network\n+        Function table.\n+      </li>\n+\n+      <li>\n+        For each network function group with <var>id</var> that has\n+        <code>fallback</code> set to <code>fail-open</code>, a priority-10 flow\n+        matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n+        reg0[22..29] == <var>id</var></code> and sets <code>reg8[21] = 0;\n+        reg0[22..29] = 0; next;</code>. This clears both the NF enabled bit and\n+        the NF group ID, allowing packets to continue processing through the\n+        pipeline without network function redirection when no active network\n+        function is available (fail-open behavior).\n+      </li>\n+\n+      <li>\n+        A priority-1 flow matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1\n+        </code> and sets <code>reg0[22..29] = 0; next;</code>. This is a\n+        catch-all flow for network function groups with <code>fallback</code>\n+        set to <code>fail-close</code> (or default) when no active network\n+        function is available. It clears only the NF group ID, leaving the NF\n+        enabled bit set. These packets will be dropped by the priority-1 drop\n+        rule in the subsequent Network Function table (fail-close behavior).\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that simply moves traffic to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 12: Stateful</h3>\n+\n+    <p>\n+      This is similar to ingress table <code>Stateful</code> except that\n+      there are no rules added for load balancing new connections.\n+      When <code>enable-stateless-acl-with-lb</code> is enabled, new\n+      stateless connections bypass connection tracking.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority 120 flow is added for each network function port\n+        <var>P</var> that is identical to the priority 100 flow except for\n+        additional match <code>outport == <var>P</var></code> and additional\n+        action  <code>ct_label.tun_if_id = reg5[16..31]</code>. In case packets\n+        redirected by network function logic gets tunneled from host1 to host2\n+        where the network function port resides, host2's physical table 0\n+        populates reg5[16..31] with the openflow tunnel interface id on which\n+        the packet was received. This priority 120 flow commits the tunnel id\n+        to the ct_label. That way, when the same packet comes out of the other\n+        port of the network function it can retrieve this information from the\n+        peer port's CT entry and tunnel the packet back to host1. This is\n+        required to make cross host traffic redirection work for VLAN subnet.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 13: Network Function</h3>\n+\n+    <p>\n+      This table handles request packets for <code>to-lport</code> ACLs\n+      and response packets for <code>from-lport</code> ACLs. For\n+      <code>to-lport</code> ACLs, request packets are redirected to the\n+      network function's <code>outport</code>, and corresponding\n+      response/related packets are handled in the ingress pipeline. For\n+      <code>from-lport</code> ACLs, request packets are handled in the\n+      ingress pipeline, but corresponding response/related packets for those\n+      flows are redirected here using the network function ID stored in\n+      <code>ct_label.nf_id</code> during request processing.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        Similar to ingress <code>Network Function</code> a priority-100 flow is\n+        added for each network_function port, that matches the inport with the\n+        network function port and advances the packet to the next table.\n+      </li>\n+\n+      <li>\n+        For each active network function with <var>id</var> that is\n+        referenced in a network function group, a priority-99 flow matches\n+        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n+        reg0[22..29] == <var>id</var></code> and sets\n+        <code>outport=<var>P</var>; reg8[23] = 1; next(pipeline=ingress,\n+        table=<var>T</var>)</code> where <var>P</var> is the\n+        <code>outport</code> of that network function and <var>T</var> is\n+        the ingress table <code>Destination Lookup</code>. This redirects\n+        request packets matching <code>to-lport</code> ACLs with\n+        network_function_group to the specific network function selected by\n+        the Pre Network Function stage. The packets are injected back to the\n+        ingress pipeline from where they get sent out, skipping any further\n+        lookup because of <code>reg8[23]</code>.\n+      </li>\n+\n+      <li>\n+        For each active network function with <var>id</var> that is referenced\n+        in a network function group, a priority-99 rule matches\n+        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 0 &amp;&amp;\n+        ct_label.nf_id == <var>id</var></code> and takes identical action as\n+        above. This redirects response and related packets for\n+        <code>from-lport</code> ACLs to the same network function that handled\n+        the request, using the NF ID stored in the connection tracking label.\n+      </li>\n+\n+      <li>\n+        In each of the above cases, when the same packet comes out unchanged\n+        through the other port of the network_function, it would match the\n+        priority 100 flow and be forwarded to the next table.\n+      </li>\n+\n+      <li>\n+        One priority-100 multicast match flow same as\n+        ingress <code>Network Function</code>.\n+      </li>\n+\n+      <li>\n+        One priority-1 flow same as ingress <code>Network Function</code>.\n+      </li>\n+\n+      <li>\n+        One priority-0 flow same as ingress <code>Network Function</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 14: Egress Port Security - check</h3>\n+\n+    <p>\n+      This is similar to the port security logic in table\n+      <code>Ingress Port Security check</code> except that action\n+      <code>check_out_port_sec</code> is used to check the port security\n+      rules.  This table adds the below logical flows.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority 100 flow which matches on the multicast traffic and applies\n+        the action <code>REGBIT_PORT_SEC_DROP\" = 0; next;\"</code> to skip\n+        the out port security checks.\n+      </li>\n+\n+      <li>\n+        A priority 0 logical flow is added which matches on all the packets\n+        and applies the action\n+        <code>REGBIT_PORT_SEC_DROP\" = check_out_port_sec(); next;\"</code>.\n+        The action <code>check_out_port_sec</code> applies the port security\n+        rules based on the addresses defined in the\n+        <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> table before delivering the packet to the\n+        <code>outport</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 15: Egress Port Security - Apply</h3>\n+\n+    <p>\n+      This is similar to the ingress port security logic in ingress table\n+      <code>A Ingress Port Security - Apply</code>.  This table drops the\n+      packets if the port security check failed in the previous stage i.e\n+      the register bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n+    </p>\n+\n+    <p>\n+      The following flows are added.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+        For each port configured with egress qos in the\n+        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/>, running a localnet port on the same logical\n+        switch, a priority 110 flow is added which matches on the localnet\n+        <code>outport</code> and on the port <code>inport</code> and\n+        applies the action <code>set_queue(id); output;\"</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+        For each localnet port configured with egress qos in the\n+        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+        db=\"OVN_Northbound\"/>, a priority 100 flow is added which\n+        matches on the localnet <code>outport</code> and applies the action\n+        <code>set_queue(id); output;\"</code>.\n+        </p>\n+\n+        <p>\n+          Please remember to mark the corresponding physical interface with\n+          <code>ovn-egress-iface</code> set to true in\n+          <ref column=\"external_ids\" table=\"Interface\" db=\"Open_vSwitch\"/>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-50 flow that drops the packet if the register\n+        bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that outputs the packet to the <code>outport</code>.\n+      </li>\n+    </ul>\n+\n+    <h2>Logical Router Datapaths</h2>\n+\n+    <p>\n+      Logical router datapaths will only exist for <ref table=\"Logical_Router\"\n+      db=\"OVN_Northbound\"/> rows in the <ref db=\"OVN_Northbound\"/> database\n+      that do not have <ref column=\"enabled\" table=\"Logical_Router\"\n+      db=\"OVN_Northbound\"/> set to <code>false</code>\n+    </p>\n+\n+    <h3>Ingress Table 0: L2 Admission Control</h3>\n+\n+    <p>\n+      This table drops packets that the router shouldn't see at all based on\n+      their Ethernet headers.  It contains the following flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        Priority-100 flows to drop packets with VLAN tags or multicast Ethernet\n+        source addresses.\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each enabled router port <var>P</var> with Ethernet address\n+          <var>E</var>, a priority-50 flow that matches <code>inport ==\n+          <var>P</var> &amp;&amp; (eth.mcast || eth.dst ==\n+          <var>E</var></code>), stores the router port ethernet address\n+          and advances to next table, with action\n+          <code>xreg0[0..47]=E; next;</code>.\n+        </p>\n+\n+        <p>\n+          For the gateway port on a distributed logical router (where\n+          one of the logical router ports specifies a\n+          gateway chassis), the above flow matching\n+          <code>eth.dst == <var>E</var></code> is only programmed on\n+          the gateway port instance on the gateway chassis.\n+          If LRP's logical switch has attached LSP of <code>vtep</code> type,\n+          the <code>is_chassis_resident()</code> part is not added to lflow to\n+          allow traffic originated from logical switch to reach LR services\n+          (LBs, NAT).\n+        </p>\n+\n+        <p>\n+          For each gateway port <var>GW</var> on a distributed logical router\n+          a priority-120 flow that matches 'recirculated' icmp{4,6} error\n+          'packet too big' and <code>eth.dst == <var>D</var> &amp;&amp;\n+          !is_chassis_resident(<var> cr-GW</var>)</code> where <var>D</var>\n+          is the gateway port mac address and <var>cr-GW</var> is the chassis\n+          resident port of <var>GW</var>, swap inport and outport and stores\n+          <var>GW</var> as inport.\n+        </p>\n+\n+        <p>\n+          This table adds a priority-105 flow that matches 'recirculated'\n+          icmp{4,6} error 'packet too big' to drop the packet.\n+        </p>\n+\n+        <p>\n+          For unicast L2 traffic on a distributed logical router or for\n+          gateway router where the port is configured with\n+          <code>options:gateway_mtu</code> the action of the above flow\n+          is modified adding <code>check_pkt_larger</code> in order to mark\n+          the packet setting <code>REGBIT_PKT_LARGER</code> if the size is\n+          greater than the MTU.\n+\n+          If the port is also configured with\n+          <code>options:gateway_mtu_bypass</code> then another flow is\n+          added, with priority-55, to bypass the <code>check_pkt_larger</code>\n+          flow.  This is useful for traffic that normally doesn't need to be\n+          fragmented and for which check_pkt_larger, which might not be\n+          offloadable, is not really needed.  One such example is TCP traffic.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each <code>dnat_and_snat</code> NAT rule on a distributed\n+          router that specifies an external Ethernet address <var>E</var>,\n+          a priority-50 flow that matches <code>inport == <var>GW</var>\n+          &amp;&amp; eth.dst == <var>E</var></code>, where <var>GW</var>\n+          is the logical router distributed gateway port corresponding to the\n+          NAT rule (specified or inferred), with action\n+          <code>xreg0[0..47]=E; next;</code>.\n+        </p>\n+\n+        <p>\n+          This flow is only programmed on the gateway port instance on\n+          the chassis where the <code>logical_port</code> specified in\n+          the NAT rule resides.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow that matches all packets not already handled\n+        (match <code>1</code>) and drops them (action <code>drop;</code>).\n+      </li>\n+    </ul>\n+\n+    <p>\n+      Other packets are implicitly dropped.\n+    </p>\n+\n+    <h3>Ingress Table 1: Neighbor lookup</h3>\n+\n+    <p>\n+      For ARP and IPv6 Neighbor Discovery packets, this table looks into the\n+      <ref db=\"OVN_Southbound\" table=\"MAC_Binding\"/> records to determine\n+      if OVN needs to learn the mac bindings. Following flows are added:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each router port <var>P</var> that owns IP address <var>A</var>,\n+          which belongs to subnet <var>S</var> with prefix length <var>L</var>,\n+          if the option <code>always_learn_from_arp_request</code> is\n+          <code>true</code> for this router, a priority-100 flow is added which\n+          matches <code>inport == <var>P</var> &amp;&amp; arp.spa ==\n+          <var>S</var>/<var>L</var> &amp;&amp; arp.op == 1</code> (ARP request)\n+          with the following actions:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+next;\n+        </pre>\n+\n+        <p>\n+          If the option <code>always_learn_from_arp_request</code> is\n+          <code>false</code>, the following two flows are added.\n+        </p>\n+\n+        <p>\n+          A priority-110 flow is added which matches <code>inport ==\n+          <var>P</var> &amp;&amp; arp.spa == <var>S</var>/<var>L</var>\n+          &amp;&amp; arp.tpa == <var>A</var> &amp;&amp; arp.op == 1</code>\n+          (ARP request) with the following actions:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+reg9[3] = 1;\n+next;\n+        </pre>\n+\n+        <p>\n+          A priority-100 flow is added which matches <code>inport ==\n+          <var>P</var> &amp;&amp; arp.spa == <var>S</var>/<var>L</var>\n+          &amp;&amp; arp.op == 1</code> (ARP request) with the following\n+          actions:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+reg9[3] = lookup_arp_ip(inport, arp.spa);\n+next;\n+        </pre>\n+\n+        <p>\n+          If the logical router port <var>P</var> is a distributed gateway\n+          router port, additional match\n+          <code>is_chassis_resident(cr-<var>P</var>)</code> is added for all\n+          these flows.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-100 flow which matches on ARP reply packets and applies\n+          the actions if the option <code>always_learn_from_arp_request</code>\n+          is <code>true</code>:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+next;\n+        </pre>\n+\n+        <p>\n+          If the option <code>always_learn_from_arp_request</code>\n+          is <code>false</code>, the above actions will be:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+reg9[3] = 1;\n+next;\n+        </pre>\n+\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-100 flow which matches on IPv6 Neighbor Discovery\n+          advertisement packet and applies the actions if the option\n+          <code>always_learn_from_arp_request</code> is <code>true</code>:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n+next;\n+        </pre>\n+\n+        <p>\n+          If the option <code>always_learn_from_arp_request</code>\n+          is <code>false</code>, the above actions will be:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n+reg9[3] = 1;\n+next;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-100 flow which matches on IPv6 Neighbor Discovery\n+          solicitation packet and applies the actions if the option\n+          <code>always_learn_from_arp_request</code> is <code>true</code>:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n+next;\n+        </pre>\n+\n+        <p>\n+          If the option <code>always_learn_from_arp_request</code>\n+          is <code>false</code>, the above actions will be:\n+        </p>\n+\n+        <pre>\n+reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n+reg9[3] = lookup_nd_ip(inport, ip6.src);\n+next;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        A priority-0 fallback flow that matches all packets and applies\n+        the action <code>reg9[2] = 1; next;</code>\n+        advancing the packet to the next table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 2: Neighbor learning</h3>\n+\n+    <p>\n+      This table adds flows to learn the mac bindings from the ARP and\n+      IPv6 Neighbor Solicitation/Advertisement packets if it is needed\n+      according to the lookup results from the previous stage.\n+    </p>\n+\n+    <p>\n+      reg9[2] will be <code>1</code> if the <code>lookup_arp/lookup_nd</code>\n+      in the previous table was successful or skipped, meaning no need\n+      to learn mac binding from the packet.\n+    </p>\n+\n+    <p>\n+      reg9[3] will be <code>1</code> if the\n+      <code>lookup_arp_ip/lookup_nd_ip</code> in the previous table was\n+      successful or skipped, meaning it is ok to learn mac binding from\n+      the packet (if reg9[2] is 0).\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-100 flow with the match <code>reg9[2] == 1 || reg9[3] ==\n+        0</code> and advances the packet to the next table as there is no need\n+        to learn the neighbor.\n+      </li>\n+\n+      <li>\n+        A priority-95 flow with the match <code>nd_ns &amp;&amp;\n+          (ip6.src == 0 || nd.sll == 0)</code> and applies the action\n+        <code>next;</code>\n+      </li>\n+\n+      <li>\n+        A priority-90 flow with the match <code>arp</code> and\n+        applies the action\n+        <code>put_arp(inport, arp.spa, arp.sha); next;</code>\n+      </li>\n+\n+      <li>\n+        A priority-95 flow with the match <code>nd_na  &amp;&amp;\n+        nd.tll == 0</code> and applies the action\n+        <code>put_nd(inport, nd.target, eth.src); next;</code>\n+      </li>\n+\n+      <li>\n+        A priority-90 flow with the match <code>nd_na</code> and\n+        applies the action\n+        <code>put_nd(inport, nd.target, nd.tll); next;</code>\n+      </li>\n+\n+      <li>\n+        A priority-90 flow with the match <code>nd_ns</code> and\n+        applies the action\n+        <code>put_nd(inport, ip6.src, nd.sll); next;</code>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow that matches all packets not already handled\n+        (match <code>1</code>) and drops them (action <code>drop;</code>).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 3: IP Input</h3>\n+\n+    <p>\n+      This table is the core of the logical router datapath functionality.  It\n+      contains the following flows to implement very basic IP host\n+      functionality.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each <code>dnat_and_snat</code> NAT rule on a distributed\n+          logical routers or gateway routers with gateway port\n+          configured with <code>options:gateway_mtu</code> to a valid integer\n+          value <var>M</var>, a priority-160 flow with the match\n+          <code>inport == <var>LRP</var> &amp;&amp; REGBIT_PKT_LARGER\n+          &amp;&amp; REGBIT_EGRESS_LOOPBACK == 0</code>, where <var>LRP</var>\n+          is the logical router port and applies the following action for ipv4\n+          and ipv6 respectively:\n+        </p>\n+\n+    <pre>\n+icmp4_error {\n+    icmp4.type = 3; /* Destination Unreachable. */\n+    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n+    icmp4.frag_mtu = <var>M</var>;\n+    eth.dst = eth.src;\n+    eth.src = <var>E</var>;\n+    ip4.dst = ip4.src;\n+    ip4.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER 0;\n+    outport = <var>LRP</var>;\n+    flags.loopback = 1;\n+    output;\n+};\n+\n+icmp6_error {\n+    icmp6.type = 2;\n+    icmp6.code = 0;\n+    icmp6.frag_mtu = <var>M</var>;\n+    eth.dst = eth.src;\n+    eth.src = <var>E</var>;\n+    ip6.dst = ip6.src;\n+    ip6.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER 0;\n+    outport = <var>LRP</var>;\n+    flags.loopback = 1;\n+    output;\n+};\n+    </pre>\n+        <p>\n+          where <var>E</var> and <var>I</var> are the NAT rule external mac\n+          and IP respectively.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For distributed logical routers or gateway routers with gateway port\n+          configured with <code>options:gateway_mtu</code> to a valid integer\n+          value, a priority-150 flow with the match <code>inport ==\n+          <var>LRP</var> &amp;&amp; REGBIT_PKT_LARGER &amp;&amp;\n+          REGBIT_EGRESS_LOOPBACK == 0</code>, where <var>LRP</var> is the\n+          logical router port and applies the following action for ipv4\n+          and ipv6 respectively:\n+        </p>\n+\n+    <pre>\n+icmp4_error {\n+    icmp4.type = 3; /* Destination Unreachable. */\n+    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n+    icmp4.frag_mtu = <var>M</var>;\n+    eth.dst = <var>E</var>;\n+    ip4.dst = ip4.src;\n+    ip4.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER 0;\n+    next(pipeline=ingress, table=0);\n+};\n+\n+icmp6_error {\n+    icmp6.type = 2;\n+    icmp6.code = 0;\n+    icmp6.frag_mtu = <var>M</var>;\n+    eth.dst = <var>E</var>;\n+    ip6.dst = ip6.src;\n+    ip6.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER 0;\n+    next(pipeline=ingress, table=0);\n+};\n+    </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each NAT entry of a distributed logical router  (with\n+          distributed gateway router port(s)) of type <code>snat</code>,\n+          a priority-120 flow with the match <code>inport == <var>P</var>\n+          &amp;&amp; ip4.src == <var>A</var></code> advances the packet to\n+          the next pipeline, where <var>P</var> is the distributed logical\n+          router port corresponding to the NAT entry (specified or inferred)\n+          and <var>A</var> is the <code>external_ip</code> set\n+          in the NAT entry. If <var>A</var> is an IPv6 address, then\n+          <code>ip6.src</code> is used for the match.\n+        </p>\n+\n+        <p>\n+          The above flow is required to handle the routing of the East/west NAT\n+          traffic.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+            For each BFD port the two following priority-110 flows are added\n+            to manage BFD traffic:\n+\n+            <ul>\n+              <li>\n+               if <code>ip4.src</code> or <code>ip6.src</code> is any IP\n+               address owned by the router port and <code>udp.dst == 3784\n+               </code>, the packet is advanced to the next pipeline stage.\n+              </li>\n+\n+              <li>\n+               if <code>ip4.dst</code> or <code>ip6.dst</code> is any IP\n+               address owned by the router port and <code>udp.dst == 3784\n+               </code>, the <code>handle_bfd_msg</code> action is executed.\n+              </li>\n+            </ul>\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+            For each logical router port configured with DHCP relay the\n+            following priority-110 flows are added to manage the DHCP relay\n+            traffic:\n+\n+            <ul>\n+              <li>\n+                <p>\n+                  if <code>inport</code> is lrp and <code>ip4.src == 0.0.0.0\n+                  </code> and <code>ip4.dst == 255.255.255.255</code> and\n+                  <code>ip4.frag == 0 </code> and <code>udp.src == 68</code>\n+                  and <code>udp.dst == 67</code>, the <code>dhcp_relay_req_chk\n+                  </code> action is executed.\n+                </p>\n+\n+              <pre>\n+                reg9[7] = dhcp_relay_req_chk(<var>lrp_ip</var>,\n+                                            <var>dhcp_server_ip</var>);next\n+              </pre>\n+\n+              <p>\n+                if action is successful then, GIADDR in the dhcp header is\n+                updated with lrp ip and stores 1 into reg9[7] else stores 0\n+                into reg9[7].\n+              </p>\n+              </li>\n+\n+              <li>\n+               if <code>ip4.src</code> is DHCP server ip and <code>ip4.dst\n+               </code> is lrp IP and <code>udp.src == 67</code> and\n+               <code>udp.dst == 67</code>, the packet is advanced to the next\n+               pipeline stage.\n+              </li>\n+            </ul>\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          L3 admission control: Priority-120 flows allows IGMP and MLD packets\n+          if the router has logical ports that have\n+          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n+          <code>:mcast_flood='true'</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          L3 admission control: A priority-100 flow drops packets that match\n+          any of the following:\n+        </p>\n+\n+        <ul>\n+          <li>\n+            <code>ip4.src[28..31] == 0xe</code> (multicast source)\n+          </li>\n+          <li>\n+            <code>ip4.src == 255.255.255.255</code> (broadcast source)\n+          </li>\n+          <li>\n+            <code>ip4.src == 127.0.0.0/8 || ip4.dst == 127.0.0.0/8</code>\n+            (localhost source or destination)\n+          </li>\n+          <li>\n+            <code>ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8</code> (zero\n+            network source or destination)\n+          </li>\n+          <li>\n+            <code>ip4.src</code> or <code>ip6.src</code> is any IP\n+            address owned by the router, unless the packet was recirculated\n+            due to egress loopback as indicated by\n+            <code>REGBIT_EGRESS_LOOPBACK</code>.\n+          </li>\n+          <li>\n+            <code>ip4.src</code> is the broadcast address of any IP network\n+            known to the router.\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+          A priority-100 flow parses DHCPv6 replies from IPv6 prefix\n+          delegation routers (<code>udp.src == 547 &amp;&amp;\n+          udp.dst == 546</code>). The <code>handle_dhcpv6_reply</code>\n+          is used to send IPv6 prefix delegation messages to the delegation\n+          router.\n+      </li>\n+\n+      <li>\n+          For each load balancer applied to this logical router configured\n+          with <code>VIP</code> template, a priority-100 flow matching\n+          <code>ip4.dst</code> or <code>ip6.dst</code> with the configured\n+          load balancer <code>VIP</code> and action <code>next;</code>.\n+          These flows avoid dropping the packet if the <code>VIP</code> is\n+          set to one of the router IPs.\n+      </li>\n+\n+      <li>\n+        <p>\n+          ICMP echo reply.  These flows reply to ICMP echo requests received\n+          for the router's IP address.  Let <var>A</var> be an IP address\n+          owned by a router port.  Then, for each <var>A</var> that is\n+          an IPv4 address, a priority-90 flow matches on\n+          <code>ip4.dst == <var>A</var></code> and\n+          <code>icmp4.type == 8 &amp;&amp; icmp4.code == 0</code>\n+          (ICMP echo request).  For each <var>A</var> that is an IPv6\n+          address, a priority-90 flow matches on\n+          <code>ip6.dst == <var>A</var></code> and\n+          <code>icmp6.type == 128 &amp;&amp; icmp6.code == 0</code>\n+          (ICMPv6 echo request).  The port of the router that receives the\n+          echo request does not matter. Also, the <code>ip.ttl</code> of\n+          the echo request packet is not checked, so it complies with\n+          RFC 1812, section 4.2.2.9. Flows for ICMPv4 echo requests use the\n+          following actions:\n+        </p>\n+\n+        <pre>\n+ip4.dst &lt;-&gt; ip4.src;\n+ip.ttl = 255;\n+icmp4.type = 0;\n+flags.loopback = 1;\n+next;\n+        </pre>\n+\n+        <p>\n+          Flows for ICMPv6 echo requests use the following actions:\n+        </p>\n+\n+        <pre>\n+ip6.dst &lt;-&gt; ip6.src;\n+ip.ttl = 255;\n+icmp6.type = 129;\n+flags.loopback = 1;\n+next;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Reply to ARP requests.\n+        </p>\n+\n+        <p>\n+          These flows reply to ARP requests for the router's own IP address.\n+          The ARP requests are handled only if the requestor's IP belongs\n+          to the same subnets of the logical router port.\n+          For each router port <var>P</var> that owns IP address <var>A</var>,\n+          which belongs to subnet <var>S</var> with prefix length <var>L</var>,\n+          and Ethernet address <var>E</var>, a priority-90 flow matches\n+          <code>inport == <var>P</var> &amp;&amp;\n+          arp.spa == <var>S</var>/<var>L</var> &amp;&amp; arp.op == 1\n+          &amp;&amp; arp.tpa == <var>A</var></code> (ARP request) with the\n+          following actions:\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = xreg0[0..47];\n+arp.op = 2; /* ARP reply. */\n+arp.tha = arp.sha;\n+arp.sha = xreg0[0..47];\n+arp.tpa = arp.spa;\n+arp.spa = <var>A</var>;\n+outport = inport;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          For the gateway port on a distributed logical router (where\n+          one of the logical router ports specifies a\n+          gateway chassis), the above flows are only\n+          programmed on the gateway port instance on the\n+          gateway chassis.  This behavior avoids generation\n+          of multiple ARP responses from different chassis, and allows\n+          upstream MAC learning to point to the gateway chassis.\n+        </p>\n+\n+        <p>\n+          For the logical router port with the option\n+          <code>reside-on-redirect-chassis</code> set (which is centralized),\n+          the above flows are only programmed on the gateway port instance on\n+          the gateway chassis (if the logical router has a\n+          distributed gateway port). This behavior avoids generation\n+          of multiple ARP responses from different chassis, and allows\n+          upstream MAC learning to point to the gateway chassis.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Reply to IPv6 Neighbor Solicitations.  These flows reply to\n+          Neighbor Solicitation requests for the router's own IPv6\n+          address and populate the logical router's mac binding table.\n+        </p>\n+\n+        <p>\n+          For each router port <var>P</var> that\n+          owns IPv6 address <var>A</var>, solicited node address <var>S</var>,\n+          and Ethernet address <var>E</var>, a priority-90 flow matches\n+          <code>inport == <var>P</var> &amp;&amp;\n+          nd_ns &amp;&amp; ip6.dst == {<var>A</var>, <var>E</var>} &amp;&amp;\n+          nd.target == <var>A</var></code> with the following actions:\n+        </p>\n+\n+        <pre>\n+nd_na_router {\n+    eth.src = xreg0[0..47];\n+    ip6.src = <var>A</var>;\n+    nd.target = <var>A</var>;\n+    nd.tll = xreg0[0..47];\n+    outport = inport;\n+    flags.loopback = 1;\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          For the gateway port on a distributed logical router (where\n+          one of the logical router ports specifies a\n+          gateway chassis), the above flows replying to\n+          IPv6 Neighbor Solicitations are only programmed on the\n+          gateway port instance on the gateway chassis.\n+          This behavior avoids generation of multiple replies from\n+          different chassis, and allows upstream MAC learning to point\n+          to the gateway chassis.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          These flows reply to ARP requests or IPv6 neighbor solicitation\n+          for the virtual IP addresses configured in the router for NAT\n+          (both DNAT and SNAT) or load balancing.\n+        </p>\n+\n+        <p>\n+          IPv4: For a configured NAT (both DNAT and SNAT) IP address or a\n+          load balancer IPv4 VIP <var>A</var>, for each router port\n+          <var>P</var> with Ethernet address <var>E</var>, a priority-90 flow\n+          matches <code>arp.op == 1 &amp;&amp; arp.tpa == <var>A</var></code>\n+          (ARP request) with the following actions:\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = xreg0[0..47];\n+arp.op = 2; /* ARP reply. */\n+arp.tha = arp.sha;\n+arp.sha = xreg0[0..47];\n+arp.tpa &lt;-&gt; arp.spa;\n+outport = inport;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          IPv4: For a configured load balancer IPv4 VIP, a similar flow is\n+          added with the additional match <code>inport == <var>P</var></code>\n+          if the VIP is reachable from any logical router port of the logical\n+          router.\n+        </p>\n+\n+        <p>\n+          If the router port <var>P</var> is a distributed gateway router\n+          port, then the <code>is_chassis_resident(<var>P</var>)</code> is\n+          also added in the match condition for the load balancer IPv4\n+          VIP <var>A</var>.\n+        </p>\n+\n+        <p>\n+          IPv6: For a configured NAT (both DNAT and SNAT) IP address or a\n+          load balancer IPv6 VIP <var>A</var> (if the VIP is reachable from any\n+          logical router port of the logical router), solicited node address\n+          <var>S</var>, for each router port <var>P</var> with\n+          Ethernet address <var>E</var>, a priority-90 flow matches\n+          <code>inport == <var>P</var> &amp;&amp; nd_ns &amp;&amp;\n+          ip6.dst == {<var>A</var>, <var>S</var>} &amp;&amp;\n+          nd.target == <var>A</var></code>\n+          with the following actions:\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+nd_na {\n+    eth.src = xreg0[0..47];\n+    nd.tll = xreg0[0..47];\n+    ip6.src = <var>A</var>;\n+    nd.target = <var>A</var>;\n+    outport = inport;\n+    flags.loopback = 1;\n+    output;\n+}\n+        </pre>\n+\n+        <p>\n+          If the router port <var>P</var> is a distributed gateway router\n+          port, then the <code>is_chassis_resident(<var>P</var>)</code>\n+          is also added in the match condition for the load balancer IPv6\n+          VIP <var>A</var>.\n+        </p>\n+\n+        <p>\n+          For the gateway port on a distributed logical router with NAT\n+          (where one of the logical router ports specifies a\n+          gateway chassis):\n+        </p>\n+\n+        <ul>\n+          <li>\n+            If the corresponding NAT rule cannot be handled in a\n+            distributed manner, then a priority-92 flow is programmed on\n+            the gateway port instance on the\n+            gateway chassis.  A priority-91 drop flow is\n+            programmed on the other chassis when ARP requests/NS packets\n+            are received on the gateway port. This behavior avoids\n+            generation of multiple ARP responses from different chassis,\n+            and allows upstream MAC learning to point to the\n+            gateway chassis.\n+          </li>\n+\n+          <li>\n+            <p>\n+              If the corresponding NAT rule can be handled in a distributed\n+              manner, then this flow is only programmed on the gateway port\n+              instance where the <code>logical_port</code> specified in the\n+              NAT rule resides.\n+            </p>\n+\n+            <p>\n+              Some of the actions are different for this case, using the\n+              <code>external_mac</code> specified in the NAT rule rather\n+              than the gateway port's Ethernet address <var>E</var>:\n+            </p>\n+\n+            <pre>\n+eth.src = <var>external_mac</var>;\n+arp.sha = <var>external_mac</var>;\n+            </pre>\n+\n+            <p>\n+              or in the case of IPv6 neighbor solicition:\n+            </p>\n+\n+            <pre>\n+eth.src = <var>external_mac</var>;\n+nd.tll = <var>external_mac</var>;\n+            </pre>\n+\n+            <p>\n+              This behavior avoids generation of multiple ARP responses\n+              from different chassis, and allows upstream MAC learning to\n+              point to the correct chassis.\n+            </p>\n+          </li>\n+        </ul>\n+      </li>\n+\n+      <li>\n+        Priority-85 flows which drops the ARP and IPv6 Neighbor Discovery\n+        packets.\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-84 flow explicitly allows IPv6 multicast traffic that is\n+          supposed to reach the router pipeline (i.e., router solicitation\n+          and router advertisement packets).\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-83 flow explicitly drops IPv6 multicast traffic that is\n+          destined to reserved multicast groups.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-82 flow allows IP multicast traffic if\n+          <ref column=\"options\" table=\"Logical_Router\"/>:mcast_relay='true',\n+          otherwise drops it.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          UDP port unreachable.  Priority-80 flows generate ICMP port\n+          unreachable messages in reply to UDP datagrams directed to the\n+          router's IP address, except in the special case of gateways,\n+          which accept traffic directed to a router IP for load balancing\n+          and NAT purposes.\n+        </p>\n+\n+        <p>\n+          These flows should not match IP fragments with nonzero offset.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          TCP reset.  Priority-80 flows generate TCP reset messages in reply\n+          to TCP datagrams directed to the router's IP address, except in\n+          the special case of gateways, which accept traffic directed to a\n+          router IP for load balancing and NAT purposes.\n+        </p>\n+\n+        <p>\n+          These flows should not match IP fragments with nonzero offset.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Protocol or address unreachable. Priority-70 flows generate ICMP\n+          protocol or address unreachable messages for IPv4 and IPv6\n+          respectively in reply to packets directed to the router's IP\n+          address on IP protocols other than UDP, TCP, and ICMP, except in the\n+          special case of gateways, which accept traffic directed to a router\n+          IP for load balancing purposes.\n+        </p>\n+\n+        <p>\n+          These flows should not match IP fragments with nonzero offset.\n+        </p>\n+      </li>\n+\n+      <li>\n+        Drop other IP traffic to this router.  These flows drop any other\n+        traffic destined to an IP address of this router that is not already\n+        handled by one of the flows above, which amounts to ICMP (other than\n+        echo requests) and fragments with nonzero offsets.  For each IP address\n+        <var>A</var> owned by the router, a priority-60 flow matches\n+        <code>ip4.dst == <var>A</var></code> or\n+        <code>ip6.dst == <var>A</var></code>\n+        and drops the traffic.  An exception is made and the above flow\n+        is not added if the router port's own IP address is used to SNAT\n+        packets passing through that router or if it is used as a\n+        load balancer VIP.\n+      </li>\n+    </ul>\n+\n+    <p>\n+      The flows above handle all of the traffic that might be directed to the\n+      router itself.  The following flows (with lower priorities) handle the\n+      remaining traffic, potentially for forwarding:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        Drop Ethernet local broadcast.  A priority-50 flow with match\n+        <code>eth.bcast</code> drops traffic destined to the local Ethernet\n+        broadcast address.  By definition this traffic should not be forwarded.\n+      </li>\n+\n+      <li>\n+        Avoid ICMP time exceeded for multicast.  A priority-32 flow with match\n+        <code>ip.ttl == {0, 1} &amp;&amp; !ip.later_frag &amp;&amp;\n+        (ip4.mcast || ip6.mcast)</code> and actions <code>drop;</code> drops\n+        multicast packets whose TTL has expired without sending ICMP time\n+        exceeded.\n+      </li>\n+\n+      <li>\n+        <p>\n+          ICMP time exceeded.  For each router port <var>P</var>, whose IP\n+          address is <var>A</var>, a priority-31 flow with match <code>inport\n+          == <var>P</var> &amp;&amp; ip.ttl == {0, 1} &amp;&amp;\n+          !ip.later_frag</code> matches packets whose TTL has expired, with the\n+          following actions to send an ICMP time exceeded reply for IPv4 and\n+          IPv6 respectively:\n+        </p>\n+\n+        <pre>\n+icmp4 {\n+    icmp4.type = 11; /* Time exceeded. */\n+    icmp4.code = 0;  /* TTL exceeded in transit. */\n+    ip4.dst = ip4.src;\n+    ip4.src = <var>A</var>;\n+    ip.ttl = 254;\n+    next;\n+};\n+\n+icmp6 {\n+    icmp6.type = 3; /* Time exceeded. */\n+    icmp6.code = 0;  /* TTL exceeded in transit. */\n+    ip6.dst = ip6.src;\n+    ip6.src = <var>A</var>;\n+    ip.ttl = 254;\n+    next;\n+};\n+        </pre>\n+      </li>\n+\n+      <li>\n+        TTL discard.  A priority-30 flow with match <code>ip.ttl == {0,\n+        1}</code> and actions <code>drop;</code> drops other packets whose TTL\n+        has expired, that should not receive a ICMP error reply (i.e. fragments\n+        with nonzero offset).\n+      </li>\n+\n+      <li>\n+        Next table.  A priority-0 flows match all packets that aren't already\n+        handled and uses actions <code>next;</code> to feed them to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+\n+    <h3>Ingress Table 4: DHCP Relay Request</h3>\n+    <p>\n+      This stage process the DHCP request packets on which\n+      <code>dhcp_relay_req_chk</code> action is applied in the IP input stage.\n+    </p>\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-100 logical flow is added for each logical router port\n+          configured with DHCP relay that matches <code>inport</code> is lrp\n+          and <code>ip4.src == 0.0.0.0</code> and\n+          <code>ip4.dst == 255.255.255.255</code> and <code>udp.src == 68\n+          </code> and <code>udp.dst == 67</code> and <code>reg9[7] == 1</code>\n+          and applies following actions. If <code>reg9[7]</code> is set to 1\n+          then, <code>dhcp_relay_req_chk</code> action was successful.\n+        </p>\n+\n+        <pre>\n+ip4.src=<var>lrp ip</var>;\n+ip4.dst=<var>dhcp server ip</var>;\n+udp.src = 67;\n+next;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-1 logical flow is added for each logical router port\n+          configured with DHCP relay that matches <code>inport</code> is lrp\n+          and <code>ip4.src == 0.0.0.0</code> and\n+          <code>ip4.dst == 255.255.255.255</code> and <code>udp.src == 68\n+          </code> and <code>udp.dst == 67</code> and <code>reg9[7] == 0</code>\n+          and drops the packet. If <code>reg9[7]</code> is set to 0 then,\n+          <code>dhcp_relay_req_chk</code> action was unsuccessful.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advance to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 5: UNSNAT</h3>\n+\n+    <p>\n+      This is for already established connections' reverse traffic.\n+      i.e., SNAT has already been done in egress pipeline and now the\n+      packet has entered the ingress pipeline as part of a reply.  It is\n+      unSNATted here.\n+    </p>\n+\n+    <p>Ingress Table 5: UNSNAT on Gateway and Distributed Routers</p>\n+    <ul>\n+      <li>\n+        <p>\n+          If the Router (Gateway or Distributed) is configured with\n+          load balancers, then below lflows are added:\n+        </p>\n+\n+        <p>\n+          For each IPv4 address <var>A</var> defined as load balancer\n+          VIP with the protocol <var>P</var> (and the protocol port\n+          <var>T</var> if defined) is also present as an\n+          <code>external_ip</code> in the NAT table,\n+          a priority-120 logical flow is added with the match\n+          <code>ip4 &amp;&amp; ip4.dst == <var>A</var> &amp;&amp;\n+          <var>P</var></code> with the action <code>next;</code> to\n+          advance the packet to the next table. If the load balancer\n+          has protocol port <code>B</code> defined, then the match also has\n+          <code><var>P</var>.dst == <var>B</var></code>.\n+        </p>\n+\n+        <p>\n+          The above flows are also added for IPv6 load balancers.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <p>Ingress Table 5: UNSNAT on Gateway Routers</p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          If the Gateway router has been configured to force SNAT any\n+          previously DNATted packets to <var>B</var>, a priority-110 flow\n+          matches <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n+          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n+          with an action <code>ct_snat; </code>.\n+        </p>\n+\n+        <p>\n+          If the Gateway router is configured with\n+          <code>lb_force_snat_ip=router_ip</code> then for every logical router\n+          port <var>P</var> attached to the Gateway router with the router ip\n+          <var>B</var>, a priority-110 flow is added with the match\n+          <code>inport == <var>P</var> &amp;&amp;\n+          ip4.dst == <var>B</var></code> or <code>inport == <var>P</var>\n+          &amp;&amp; ip6.dst == <var>B</var></code> with an action\n+          <code>ct_snat; </code>.\n+        </p>\n+\n+        <p>\n+          If the Gateway router has been configured to force SNAT any\n+          previously load-balanced packets to <var>B</var>, a priority-100 flow\n+          matches <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n+          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n+          with an action <code>ct_snat; </code>.\n+        </p>\n+\n+        <p>\n+          For each NAT configuration in the OVN Northbound database, that asks\n+          to change the source IP address of a packet from <var>A</var> to\n+          <var>B</var>, a priority-90 flow matches\n+          <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n+          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n+          with an action <code>ct_snat; </code>. If the NAT rule is of type\n+          dnat_and_snat and has <code>stateless=true</code> in the\n+          options, then the action would be <code>next;</code>.\n+        </p>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+          <code>next;</code>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <p>Ingress Table 5: UNSNAT on Distributed Routers</p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the source IP address of a packet from <var>A</var> to\n+          <var>B</var>, two priority-100 flows are added.\n+        </p>\n+\n+        <p>\n+          If the NAT rule cannot be handled in a distributed manner, then\n+          the below priority-100 flows are only programmed on the\n+          gateway chassis.\n+        </p>\n+\n+        <ul>\n+          <li>\n+            <p>\n+              The first flow matches <code>ip &amp;&amp;\n+              ip4.dst == <var>B</var> &amp;&amp; inport == <var>GW</var>\n+              </code> or <code>ip &amp;&amp; ip6.dst == <var>B</var> &amp;&amp;\n+              inport == <var>GW</var></code>\n+              where <var>GW</var> is the distributed gateway port\n+              corresponding to the NAT rule (specified or inferred), with an\n+              action <code>ct_snat;</code> to unSNAT in the common\n+              zone.  If the NAT rule is of type dnat_and_snat and has\n+              <code>stateless=true</code> in the options, then the action\n+              would be <code>next;</code>.\n+            </p>\n+\n+            <p>\n+              If the NAT entry is of type <code>snat</code>, then there is an\n+              additional match <code>is_chassis_resident(<var>cr-GW</var>)\n+              </code> where <var>cr-GW</var> is the chassis resident port of\n+              <var>GW</var>.\n+            </p>\n+          </li>\n+        </ul>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+          <code>next;</code>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 6: POST USNAT</h3>\n+\n+    <p>\n+      This is to check whether the packet is already tracked in SNAT zone.\n+      It contains a priority-0 flow that simply moves traffic to the next\n+      table.\n+    </p>\n+\n+    <p>\n+      If the <code>options:ct-commit-all</code> is set to <code>true</code> the\n+      following two flows are configured matching on <code>ip &amp;&amp;\n+      ct.new</code> with an action <code>flags.unsnat_new = 1; next; </code>\n+      and <code>ip &amp;&amp; !ct.trk</code> with an action\n+      <code>flags.unsnat_not_tracked = 1; next;</code> Which sets one of the\n+      flags that is used in later stages. There is extra match on both when\n+      there is configured DGP\n+      <code>inport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n+    </p>\n+\n+    <h3>Ingress Table 7: DEFRAG</h3>\n+\n+    <p>\n+      This is to send packets to connection tracker for tracking and\n+      defragmentation.  It contains a priority-0 flow that simply moves traffic\n+      to the next table.\n+    </p>\n+\n+    <p>\n+      For all load balancing rules that are configured in\n+      <code>OVN_Northbound</code> database for a Gateway router,\n+      a priority-100 flow is added for each configured virtual IP address\n+      <var>VIP</var>. For IPv4 <var>VIPs</var> the flow matches\n+      <code>ip &amp;&amp; ip4.dst == <var>VIP</var></code>.  For IPv6\n+      <var>VIPs</var>, the flow matches <code>ip &amp;&amp; ip6.dst ==\n+      <var>VIP</var></code>. The flow applies the action <code> ct_dnat;</code>\n+      to send IP packets to the connection tracker for packet de-fragmentation\n+      and to dnat the destination IP for the committed connection before\n+      sending it to the next table.\n+    </p>\n+\n+    <p>\n+      If ECMP routes with symmetric reply are configured in the\n+      <code>OVN_Northbound</code> database for a gateway router, a priority-100\n+      flow is added for each router port on which symmetric replies are\n+      configured. The matching logic for these ports essentially reverses the\n+      configured logic of the ECMP route. So for instance, a route with a\n+      destination routing policy will instead match if the source IP address\n+      matches the static route's prefix. The flow uses the actions\n+      <code>chk_ecmp_nh_mac(); ct_next</code> or\n+      <code>chk_ecmp_nh(); ct_next</code> to send IP packets to table\n+      <code>76</code> or to table <code>77</code> in order to check if source\n+      info are already stored by OVN and then to the connection tracker for\n+      packet de-fragmentation and tracking before sending it to the next table.\n+    </p>\n+\n+    <p>\n+      If load balancing rules are configured in <code>OVN_Northbound</code>\n+      database for a Gateway router, a priority 50 flow that matches\n+      <code>icmp || icmp6</code> with an action of <code>ct_dnat;</code>,\n+      this allows potentially related ICMP traffic to pass through CT.\n+    </p>\n+\n+    <p>\n+      If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+      the following flow is configured matching on <code>ip &amp;&amp;\n+      (!ct.trk || !ct.rpl)</code> with an action <code>ct_next(dnat);</code>.\n+      There is extra match when the LR is configured as DGP\n+      <code>inport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n+    </p>\n+\n+   <h3>Ingress Table 8: Connection tracking field extraction</h3>\n+\n+    <p>\n+      This table extracts connection tracking fields for new connections\n+      and stores them in registers for use by subsequent load balancing\n+      stages.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For all new connections (<code>ct.new</code>), a priority-100 flow\n+          extracts the connection tracking protocol and destination port\n+          information into registers:\n+        </p>\n+\n+        <pre>\n+reg1[16..23] = ct_proto();\n+reg1[0..15] = ct_tp_dst();\n+next;\n+        </pre>\n+\n+        <p>\n+          This stores the connection tracking destination port in\n+          <code>REG_CT_TP_DST</code> (reg1[0..15]) and the protocol\n+          in <code>REG_CT_PROTO</code> (reg1[16..23]).\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets and advances to the\n+        next table with action <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 9: Load balancing affinity check</h3>\n+\n+    <p>\n+      Load balancing affinity check table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a logical router where\n+        a positive affinity timeout is specified in <code>options</code>\n+        column, that includes a L4 port <var>PORT</var> of protocol\n+        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-100\n+        flow that matches on <code>ct.new &amp;&amp; ip &amp;&amp;\n+        ip.dst == <var>VIP</var> &amp;&amp; REG_CT_PROTO == <var>P_NUM</var>\n+        &amp;&amp; REG_CT_TP_DST == <var>PORT</var></code> (<code>xxreg0 ==\n+        <var>VIP</var></code> in the IPv6 case) with an action of\n+        <code>reg0 = ip.dst; reg9[16..31] = P.dst; reg9[6] = chk_lb_aff();\n+        next;</code> (<code>xxreg0 == <var>ip6.dst</var> </code> in the IPv6\n+        case), where <var>P_NUM</var> is the protocol number (6 for TCP, 17\n+        for UDP, 132 for SCTP).\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 10: DNAT</h3>\n+\n+    <p>\n+      Packets enter the pipeline with destination IP address that needs to\n+      be DNATted from a virtual IP address to a real IP address.  Packets\n+      in the reverse direction needs to be unDNATed.\n+    </p>\n+\n+    <p>Ingress Table 8: Load balancing DNAT rules</p>\n+\n+    <p>\n+      Following load balancing DNAT flows are added for Gateway router or\n+      Router with gateway port. These flows are programmed only on the\n+      gateway chassis.  These flows do not get programmed for\n+      load balancers with IPv6 <var>VIPs</var>.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a logical router where\n+        a positive affinity timeout is specified in <code>options</code>\n+        column, that includes a L4 port <var>PORT</var> of protocol\n+        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-150\n+        flow that matches on <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp;\n+        ip &amp;&amp; ip.dst == <var>VIP</var> &amp;&amp; REG_CT_PROTO ==\n+        <var>P_NUM</var> &amp;&amp;\n+        REG_CT_TP_DST == <var>PORT</var></code> with an action of\n+        <code>ct_lb_mark(<var>args</var>) </code>, where <var>args</var>\n+        contains comma separated IP addresses (and optional port numbers)\n+        to load balance to, and <var>P_NUM</var> is the protocol number\n+        (6 for TCP, 17 for UDP, 132 for SCTP). The address family of the IP\n+        addresses of <var>args</var> is the same as the address family of\n+        <var>VIP</var>.\n+      </li>\n+\n+      <li>\n+        If controller_event has been enabled for all the configured load\n+        balancing rules for a Gateway router or Router with gateway port\n+        in <code>OVN_Northbound</code> database that does not have configured\n+        backends, a priority-130 flow is added to trigger ovn-controller events\n+        whenever the chassis receives a packet for that particular VIP.\n+        If <code>event-elb</code> meter has been previously created, it will be\n+        associated to the empty_lb logical flow\n+      </li>\n+\n+      <li>\n+        <p>\n+          For all the configured load balancing rules for a Gateway router or\n+          Router with gateway port in <code>OVN_Northbound</code> database that\n+          includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4\n+          or IPv6 address <var>VIP</var>, a priority-120 flow that matches on\n+          <code>ct.new &amp;&amp; !ct.rel &amp;&amp; ip &amp;&amp; ip.dst ==\n+          <var>VIP</var> &amp;&amp; REG_CT_PROTO == <var>P_NUM</var> &amp;&amp;\n+          REG_CT_TP_DST == <var>PORT</var></code> with an action of\n+          <code>ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains\n+          comma separated IPv4 or IPv6 addresses (and optional port numbers) to\n+          load balance to, and <var>P_NUM</var> is the protocol number\n+          (6 for TCP, 17 for UDP, 132 for SCTP). If the router is configured\n+          to force SNAT any\n+          load-balanced packets, the above action will be replaced by\n+          <code>flags.force_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n+          force_snat);</code>.\n+          If the load balancing rule is configured with <code>skip_snat</code>\n+          set to true, the above action will be replaced by\n+          <code>flags.skip_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n+          skip_snat);</code>.\n+          If health check is enabled, then\n+          <var>args</var> will only contain those endpoints whose service\n+          monitor status entry in <code>OVN_Southbound</code> db is\n+          either <code>online</code> or empty.\n+        </p>\n+\n+      </li>\n+\n+      <li>\n+        <p>\n+          For all the configured load balancing rules for a router in\n+          <code>OVN_Northbound</code> database that includes just an IP address\n+          <var>VIP</var> to match on, a priority-110 flow that matches on\n+          <code>ct.new &amp;&amp; !ct.rel &amp;&amp; ip4 &amp;&amp; ip.dst ==\n+          <var>VIP</var></code> with an action of\n+          <code>ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains\n+          comma separated IPv4 or IPv6 addresses.  If the router is configured\n+          to force SNAT any load-balanced packets, the above action will be\n+          replaced by <code>flags.force_snat_for_lb = 1;\n+          ct_lb_mark(<var>args</var>; force_snat);</code>.\n+          If the load balancing rule is configured with <code>skip_snat</code>\n+          set to true, the above action will be replaced by\n+          <code>flags.skip_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n+          skip_snat);</code>.\n+        </p>\n+\n+        <p>\n+          The previous table <code>lr_in_defrag</code> sets the register\n+          <code>reg0</code> (or <code>xxreg0</code> for IPv6) and does\n+          <code>ct_dnat</code>.  Hence for established traffic, this\n+          table just advances the packet to the next stage.\n+        </p>\n+      </li>\n+\n+      <li>\n+        If the load balancer is created with <code>--reject</code> option and\n+        it has no active backends, a TCP reset segment (for tcp) or an ICMP\n+        port unreachable packet (for all other kind of traffic) will be sent\n+        whenever an incoming packet is received for this load-balancer.\n+        Please note using <code>--reject</code> option will disable\n+        empty_lb SB controller event for this load balancer.\n+      </li>\n+\n+      <li>\n+        <p>\n+            For the related traffic, a priority 50 flow that matches\n+            <code>ct.rel &amp;&amp; !ct.est &amp;&amp; !ct.new </code>\n+            with an action of <code>ct_commit_nat;</code>, if the router\n+            has load balancer assigned to it. Along with two priority 70 flows\n+            that match <code>skip_snat</code> and <code>force_snat</code>\n+            flags, setting the <code>flags.force_snat_for_lb = 1</code> or\n+            <code>flags.skip_snat_for_lb = 1</code> accordingly.\n+        </p>\n+      </li>\n+      <li>\n+        <p>\n+          For the established traffic, a priority 50 flow that matches\n+          <code>ct.est &amp;&amp; !ct.rel &amp;&amp; !ct.new &amp;&amp;\n+          ct_mark.natted</code> with an action of <code>next;</code>,\n+          if the router has load balancer assigned to it. Along with two\n+          priority 70 flows that match <code>skip_snat</code> and\n+          <code>force_snat</code> flags, setting the\n+          <code>flags.force_snat_for_lb = 1</code> or\n+          <code>flags.skip_snat_for_lb = 1</code> accordingly.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <p>Ingress Table 9: DNAT on Gateway Routers</p>\n+\n+    <ul>\n+      <li>\n+        For each configuration in the OVN Northbound database, that asks\n+        to change the destination IP address of a packet from <var>A</var> to\n+        <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;\n+        ip4.dst == <var>A</var></code> or <code>ip &amp;&amp;\n+        ip6.dst == <var>A</var></code> with an action\n+        <code>flags.loopback = 1; ct_dnat(<var>B</var>);</code>.  If the\n+        Gateway router is configured to force SNAT any DNATed packet,\n+        the above action will be replaced by\n+        <code>flags.force_snat_for_dnat = 1; flags.loopback = 1;\n+        ct_dnat(<var>B</var>);</code>. If the NAT rule is of type\n+        dnat_and_snat and has <code>stateless=true</code> in the\n+        options, then the action would be <code>ip4/6.dst=\n+        (<var>B</var>)</code>.\n+\n+        <p>\n+          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n+          there is an additional match <code>ip4.src == <var>allowed_ext_ips\n+          </var></code>. Similarly, for IPV6, match would be <code>ip6.src ==\n+          <var>allowed_ext_ips</var></code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule has <code>exempted_ext_ips</code> set, then\n+          there is an additional flow configured at priority 101.\n+          The flow matches if source ip is an <code>exempted_ext_ip</code>\n+          and the action is <code>next; </code>. This flow is used to\n+          bypass the ct_dnat action for a packet originating from\n+          <code>exempted_ext_ips</code>.\n+        </p>\n+\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the destination IP address of a packet from <var>A</var>\n+          to <var>B</var>, match <var>M</var> and priority <var>P</var>,\n+          a logical flow that matches <code>ip &amp;&amp; ip4.dst ==\n+          <var>A</var></code> or <code>ip &amp;&amp; ip6.dst == <var>A</var>\n+          &amp;&amp; (<var>M</var>)</code> with an action\n+          <code>flags.loopback = 1; ct_dnat(<var>B</var>);</code>.\n+          The priority of the flow is calculated based as\n+          <code>300 + <var>P</var></code>.  If the Gateway router is\n+          configured to force SNAT any DNATed packet, the above action will\n+          be replaced by <code>flags.force_snat_for_dnat = 1;\n+          flags.loopback = 1; ct_dnat(<var>B</var>);</code>. If the NAT rule\n+          is of type dnat_and_snat and has <code>stateless=true</code> in the\n+          options, then the action would be <code>ip4/6.dst=\n+          (<var>B</var>)</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+          the following flow is configured matching on <code>ip &amp;&amp;\n+          ct.new</code> with an action <code>ct_commit_to_zone(dnat);</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <p>Ingress Table 9: DNAT on Distributed Routers</p>\n+\n+    <p>\n+      On distributed routers, the DNAT table only handles packets\n+      with destination IP address that needs to be DNATted from a\n+      virtual IP address to a real IP address.  The unDNAT processing\n+      in the reverse direction is handled in a separate table in the\n+      egress pipeline.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the destination IP address of a packet from <var>A</var> to\n+          <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;\n+          ip4.dst == <var>B</var> &amp;&amp; inport == <var>GW</var></code>,\n+          where <var>GW</var> is the logical router gateway port corresponding\n+          to the NAT rule (specified or inferred), with an action\n+          <code>ct_dnat(<var>B</var>);</code>.  The match will include\n+          <code>ip6.dst == <var>B</var></code> in the IPv6 case.\n+          If the NAT rule is of type dnat_and_snat and has\n+          <code>stateless=true</code> in the options, then the action\n+          would be <code>ip4/6.dst=(<var>B</var>)</code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule cannot be handled in a distributed manner, then\n+          the priority-100 flow above is only programmed on the\n+          gateway chassis.\n+        </p>\n+\n+        <p>\n+          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n+          there is an additional match <code>ip4.src == <var>allowed_ext_ips\n+          </var></code>. Similarly, for IPV6, match would be <code>ip6.src ==\n+          <var>allowed_ext_ips</var></code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule has <code>exempted_ext_ips</code> set, then\n+          there is an additional flow configured at priority 101.\n+          The flow matches if source ip is an <code>exempted_ext_ip</code>\n+          and the action is <code>next; </code>. This flow is used to\n+          bypass the ct_dnat action for a packet originating from\n+          <code>exempted_ext_ips</code>.\n+        </p>\n+\n+        <p>\n+          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+          the following flow is configured matching on <code>ip &amp;&amp;\n+          ct.new &amp;&amp; inport == DGP &amp;&amp;\n+          is_chassis_resident(CHASSIS)</code> with an action\n+          <code>ct_commit_to_zone(dnat);</code>.\n+        </p>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+          <code>next;</code>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 11: Load balancing affinity learn</h3>\n+\n+    <p>\n+      Load balancing affinity learn table contains the following\n+      logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules for a logical router where\n+        a positive affinity timeout <var>T</var> is specified in <code>options\n+        </code> column, that includes a L4 port <var>PORT</var> of protocol\n+        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-100\n+        flow that matches on <code>reg9[6] == 0 &amp;&amp; ct.new &amp;&amp;\n+        ip &amp;&amp; reg0 == <var>VIP</var> &amp;&amp; <var>P</var> &amp;&amp;\n+        reg9[16..31] == </code> <code><var>PORT</var></code> (<code>xxreg0 ==\n+        <var>VIP</var> </code> in the IPv6 case) with an action of\n+        <code>commit_lb_aff(vip = <var>VIP</var>:<var>PORT</var>, backend =\n+        <var>backend ip</var>: <var>backend port</var>, proto = <var>P</var>,\n+        timeout = <var>T</var>);</code>.\n+      </li>\n+\n+      <li>\n+        A priority 0 flow is added which matches on all packets and applies\n+        the action <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 12: ECMP symmetric reply processing</h3>\n+    <ul>\n+      <li>\n+        If ECMP routes with symmetric reply are configured in the\n+        <code>OVN_Northbound</code> database for a gateway router, a\n+        priority-100 flow is added for each router port on which symmetric\n+        replies are configured. The matching logic for these ports essentially\n+        reverses the configured logic of the ECMP route. So for instance, a\n+        route with a destination routing policy will instead match if the\n+        source IP address matches the static route's prefix. The flow uses\n+        the action <code>ct_commit { ct_label.ecmp_reply_eth = eth.src;\"\n+        \" ct_mark.ecmp_reply_port = <var>K</var>;}; commit_ecmp_nh(); next;\n+        </code> to commit the connection and storing <code>eth.src</code> and\n+        the ECMP reply port binding tunnel key <var>K</var> in the\n+        <code>ct_label</code> and the traffic pattern to table\n+        <code>76</code> or <code>77</code>.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 13: IPv6 ND RA option processing</h3>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-50 logical flow is added for each logical router port\n+          configured with IPv6 ND RA options which matches IPv6 ND Router\n+          Solicitation packet and applies the action\n+          <code>put_nd_ra_opts</code> and advances the packet to the next\n+          table.\n+        </p>\n+\n+        <pre>\n+reg0[5] = put_nd_ra_opts(<var>options</var>);next;\n+        </pre>\n+\n+        <p>\n+          For a valid IPv6 ND RS packet, this transforms the packet into an\n+          IPv6 ND RA reply and sets the RA options to the packet and stores 1\n+          into reg0[5]. For other kinds of packets, it just stores 0 into\n+          reg0[5]. Either way, it continues to the next table.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 14: IPv6 ND RA responder</h3>\n+\n+    <p>\n+      This table implements IPv6 ND RA responder for the IPv6 ND RA replies\n+      generated by the previous table.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-50 logical flow is added for each logical router port\n+          configured with IPv6 ND RA options which matches IPv6 ND RA\n+          packets and <code>reg0[5] == 1</code> and responds back to the\n+          <code>inport</code> after applying these actions.\n+          If <code>reg0[5]</code> is set to 1, it means that the action\n+          <code>put_nd_ra_opts</code> was successful.\n+        </p>\n+\n+        <pre>\n+eth.dst = eth.src;\n+eth.src = <var>E</var>;\n+ip6.dst = ip6.src;\n+ip6.src = <var>I</var>;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+output;\n+        </pre>\n+\n+        <p>\n+          where <var>E</var> is the MAC address and <var>I</var> is the IPv6\n+          link local address of the logical router port.\n+        </p>\n+\n+        <p>\n+          (This terminates packet processing in ingress pipeline; the packet\n+          does not go to the next ingress table.)\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 15: IP Routing Pre</h3>\n+\n+    <p>\n+      If a packet arrived at this table from Logical Router Port <var>P</var>\n+      which has <code>options:route_table</code> value set, a logical flow with\n+      match <code>inport == \"<var>P</var>\"</code> with priority 100 and action\n+      setting unique-generated per-datapath 32-bit value (non-zero) in OVS\n+      register 7.  This register's value is checked in next table.  If packet\n+      didn't match any configured inport (<var>&lt;main&gt;</var> route table),\n+      register 7 value is set to 0.\n+    </p>\n+\n+    <p>\n+      This table contains the following logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          Priority-100 flow with match <code>inport == \"LRP_NAME\"</code> value\n+          and action, which set route table identifier in reg7.\n+        </p>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+          <code>reg7 = 0; next;</code>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 16: IP Routing</h3>\n+\n+    <p>\n+      A packet that arrives at this table is an IP packet that should be\n+      routed to the address in <code>ip4.dst</code> or\n+      <code>ip6.dst</code>.  This table implements IP routing, setting\n+      <code>reg0</code> (or <code>xxreg0</code> for IPv6) to the next-hop IP\n+      address (leaving <code>ip4.dst</code> or <code>ip6.dst</code>, the\n+      packet's final destination, unchanged) and advances to the next\n+      table for ARP resolution.  It also sets <code>reg1</code> (or\n+      <code>xxreg1</code>) to the IP address owned by the selected router\n+      port (ingress table <code>ARP Request</code> will generate an ARP\n+      request, if needed, with <code>reg0</code> as the target protocol\n+      address and <code>reg1</code> as the source protocol address).\n+    </p>\n+\n+    <p>\n+      For ECMP routes, i.e. multiple static routes with same policy and\n+      prefix but different nexthops, the above actions are deferred to next\n+      table.  This table, instead, is responsible for determine the ECMP\n+      group id and select a member id within the group based on 5-tuple\n+      hashing.  It stores group id in <code>reg8[0..15]</code> and member id in\n+      <code>reg8[16..31]</code>. This step is skipped with a priority-10300\n+      rule if the traffic going out the ECMP route is reply traffic, and the\n+      ECMP route was configured to use symmetric replies. Instead, the stored\n+      values in conntrack is used to choose the destination. The\n+      <code>ct_label.ecmp_reply_eth</code> tells the destination MAC address to\n+      which the packet should be sent. The <code>ct_mark.ecmp_reply_port</code>\n+      tells the logical router port on which the packet should be sent. These\n+      values saved to the conntrack fields when the initial ingress traffic is\n+      received over the ECMP route and committed to conntrack.\n+      If <code>REGBIT_KNOWN_ECMP_NH</code> is set, the priority-10300\n+      flows in this stage set the <code>outport</code>, while the\n+      <code>eth.dst</code> is set by flows at the ARP/ND Resolution stage.\n+    </p>\n+\n+    <p>\n+      This table contains the following logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          Priority-10550 flow that drops IPv6 Router Solicitation/Advertisement\n+          packets that were not processed in previous tables.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-10550 flows that drop IGMP and MLD packets with source MAC\n+          address owned by the router.  These are used to prevent looping\n+          statically forwarded IGMP and MLD packets for which TTL is not\n+          decremented (it is always 1).\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-10500 flows that match IP multicast traffic destined to\n+          groups registered on any of the attached switches and sets\n+          <code>outport</code> to the associated multicast group that will\n+          eventually flood the traffic to all interested attached logical\n+          switches. The flows also decrement TTL.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-10460 flows that match IGMP and MLD control packets,\n+          set <code>outport</code> to the <code>MC_STATIC</code>\n+          multicast group, which <code>ovn-northd</code>\n+          populates with the logical ports that have\n+          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n+          <code>:mcast_flood='true'</code>. If no router ports are configured\n+          to flood multicast traffic the packets are dropped.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-10450 flow that matches unregistered IP multicast traffic\n+          decrements TTL and sets <code>outport</code> to the\n+          <code>MC_STATIC</code> multicast group, which <code>ovn-northd</code>\n+          populates with the logical ports that have\n+          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n+          <code>:mcast_flood='true'</code>. If no router ports are configured\n+          to flood multicast traffic the packets are dropped.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          IPv4 routing table.  For each route to IPv4 network <var>N</var> with\n+          netmask <var>M</var>, on router port <var>P</var> with IP address\n+          <var>A</var> and Ethernet\n+          address <var>E</var>, a logical flow with match <code>ip4.dst ==\n+          <var>N</var>/<var>M</var></code>, whose priority is the number of\n+          1-bits in <var>M</var>, has the following actions:\n+        </p>\n+\n+        <pre>\n+ip.ttl--;\n+reg8[0..15] = 0;\n+reg0 = <var>G</var>;\n+reg1 = <var>A</var>;\n+eth.src = <var>E</var>;\n+outport = <var>P</var>;\n+flags.loopback = 1;\n+next;\n+        </pre>\n+\n+        <p>\n+          (Ingress table 1 already verified that <code>ip.ttl--;</code> will\n+          not yield a TTL exceeded error.)\n+        </p>\n+\n+        <p>\n+          If the route has a gateway, <var>G</var> is the gateway IP address.\n+          Instead, if the route is from a configured static route, <var>G</var>\n+          is the next hop IP address.  Else it is <code>ip4.dst</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          IPv6 routing table.  For each route to IPv6 network\n+          <var>N</var> with netmask <var>M</var>, on router port\n+          <var>P</var> with IP address <var>A</var> and Ethernet address\n+          <var>E</var>, a logical flow with match in CIDR notation\n+          <code>ip6.dst == <var>N</var>/<var>M</var></code>,\n+          whose priority is the integer value of <var>M</var>, has the\n+          following actions:\n+        </p>\n+\n+        <pre>\n+ip.ttl--;\n+reg8[0..15] = 0;\n+xxreg0 = <var>G</var>;\n+xxreg1 = <var>A</var>;\n+eth.src = <var>E</var>;\n+outport = inport;\n+flags.loopback = 1;\n+next;\n+        </pre>\n+\n+        <p>\n+          (Ingress table 1 already verified that <code>ip.ttl--;</code> will\n+          not yield a TTL exceeded error.)\n+        </p>\n+\n+        <p>\n+          If the route has a gateway, <var>G</var> is the gateway IP address.\n+          Instead, if the route is from a configured static route, <var>G</var>\n+          is the next hop IP address.  Else it is <code>ip6.dst</code>.\n+        </p>\n+\n+        <p>\n+          If the address <var>A</var> is in the link-local scope, the\n+          route will be limited to sending on the ingress port.\n+        </p>\n+\n+        <p>\n+          For each static route the <code>reg7 == id &amp;&amp;</code> is\n+          prefixed in logical flow match portion.  For routes with\n+          <code>route_table</code> value set a unique non-zero id is used.\n+          For routes within <code>&lt;main&gt;</code> route table (no route\n+          table set), this id value is 0.\n+        </p>\n+        <p>\n+          For each <var>connected</var> route (route to the LRP's subnet CIDR)\n+          the logical flow match portion has no\n+          <code>reg7 == id &amp;&amp;</code> prefix to have route to LRP's\n+          subnets in all routing tables.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For ECMP routes, they are grouped by policy and prefix.  An unique id\n+          (non-zero) is assigned to each group, and each member is also\n+          assigned an unique id (non-zero) within each group.\n+        </p>\n+\n+        <p>\n+          For each IPv4/IPv6 ECMP group with group id <var>GID</var> and member\n+          ids <var>MID1</var>, <var>MID2</var>, ..., a logical flow with match\n+          in CIDR notation <code>ip4.dst == <var>N</var>/<var>M</var></code>,\n+          or <code>ip6.dst == <var>N</var>/<var>M</var></code>, whose priority\n+          is the integer value of <var>M</var>, has the following actions:\n+        </p>\n+\n+        <pre>\n+ip.ttl--;\n+flags.loopback = 1;\n+reg8[0..15] = <var>GID</var>;\n+reg8[16..31] = select(<var>MID1</var>, <var>MID2</var>, ...);\n+        </pre>\n+        <p>\n+          However, when there is only one route in an ECMP group, group actions\n+          will be:\n+        </p>\n+\n+        <pre>\n+ip.ttl--;\n+flags.loopback = 1;\n+reg8[0..15] = <var>GID</var>;\n+reg8[16..31] = <var>MID1</var>);\n+        </pre>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow that matches all packets not already handled\n+        (match <code>1</code>) and drops them (action <code>drop;</code>).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 17: IP_ROUTING_ECMP</h3>\n+\n+    <p>\n+      This table implements the second part of IP routing for ECMP routes\n+      following the previous table.  If a packet matched a ECMP group in the\n+      previous table, this table matches the group id and member id stored\n+      from the previous table, setting <code>reg0</code>\n+      (or <code>xxreg0</code> for IPv6) to the next-hop IP address\n+      (leaving <code>ip4.dst</code> or <code>ip6.dst</code>, the\n+      packet's final destination, unchanged) and advances to the next\n+      table for ARP resolution.  It also sets <code>reg1</code> (or\n+      <code>xxreg1</code>) to the IP address owned by the selected router\n+      port (ingress table <code>ARP Request</code> will generate an ARP\n+      request, if needed, with <code>reg0</code> as the target protocol\n+      address and <code>reg1</code> as the source protocol address).\n+    </p>\n+\n+    <p>\n+      This processing is skipped for reply traffic being sent out of an ECMP\n+      route if the route was configured to use symmetric replies.\n+    </p>\n+\n+    <p>\n+      This table contains the following logical flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-150 flow that matches <code>reg8[0..15] == 0</code>\n+          with action <code>next;</code> directly bypasses packets of non-ECMP\n+          routes.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each member with ID <var>MID</var> in each ECMP group with ID\n+          <var>GID</var>, a priority-100 flow with match\n+          <code>reg8[0..15] == <var>GID</var> &amp;&amp; reg8[16..31] == <var>MID</var></code>\n+          has following actions:\n+        </p>\n+\n+        <pre>\n+[xx]reg0 = <var>G</var>;\n+[xx]reg1 = <var>A</var>;\n+eth.src = <var>E</var>;\n+outport = <var>P</var>;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow that matches all packets not already handled\n+        (match <code>1</code>) and drops them (action <code>drop;</code>).\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 18: Router policies</h3>\n+    <p>\n+      This table adds flows for the logical router policies configured\n+      on the logical router. Please see the\n+      <code>OVN_Northbound</code> database <code>Logical_Router_Policy</code>\n+      table documentation in <code>ovn-nb</code> for supported actions.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each router policy configured on the logical router, a\n+          logical flow is added with specified priority, match and\n+          actions.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the policy action is <code>reroute</code> with 2 or more nexthops\n+          defined, then the logical flow is added with the following actions:\n+        </p>\n+\n+         <pre>\n+reg8[0..15] = <var>GID</var>;\n+reg8[16..31] = select(1,..n);\n+        </pre>\n+\n+        <p>\n+          where <var>GID</var> is the ECMP group id generated by\n+          <code>ovn-northd</code> for this policy and <var>n</var>\n+          is the number of nexthops. <code>select</code> action\n+          selects one of the nexthop member id, stores it in the register\n+          <code>reg8[16..31]</code> and advances the packet to the\n+          next stage.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the policy action is <code>reroute</code> with just one nexhop,\n+          then the logical flow is added with the following actions:\n+        </p>\n+\n+         <pre>\n+[xx]reg0 = <var>H</var>;\n+eth.src = <var>E</var>;\n+outport = <var>P</var>;\n+reg8[0..15] = 0;\n+flags.loopback = 1;\n+next;\n+        </pre>\n+\n+        <p>\n+          where <var>H</var> is the <code>nexthop </code> defined in the\n+          router policy, <var>E</var> is the ethernet address of the\n+          logical router port from which the <code>nexthop</code> is\n+          reachable and <var>P</var> is the logical router port from\n+          which the <code>nexthop</code> is reachable.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If a router policy has the option <code>pkt_mark=<var>m</var></code>\n+          set and if the action is <code>not</code> drop, then the action also\n+          includes <code>pkt.mark = <var>m</var></code> to mark the packet\n+          with the marker <var>m</var>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 19: ECMP handling for router policies</h3>\n+    <p>\n+      This table handles the ECMP for the router policies configured\n+      with multiple nexthops.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-150 flow is added to advance the packet to the next stage\n+          if the ECMP group id register <code>reg8[0..15]</code> is 0.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each ECMP reroute router policy with multiple nexthops,\n+          a priority-100 flow is added for each nexthop <var>H</var>\n+          with the match <code>reg8[0..15] == <var>GID</var> &amp;&amp;\n+          reg8[16..31] == <var>M</var></code> where <var>GID</var>\n+          is the router policy group id generated by <code>ovn-northd</code>\n+          and <var>M</var> is the member id of the nexthop <var>H</var>\n+          generated by <code>ovn-northd</code>. The following actions are added\n+          to the flow:\n+        </p>\n+\n+        <pre>\n+[xx]reg0 = <var>H</var>;\n+eth.src = <var>E</var>;\n+outport = <var>P</var>\n+\"flags.loopback = 1; \"\n+\"next;\"\n+        </pre>\n+\n+        <p>\n+          where <var>H</var> is the <code>nexthop </code> defined in the\n+          router policy, <var>E</var> is the ethernet address of the\n+          logical router port from which the <code>nexthop</code> is\n+          reachable and <var>P</var> is the logical router port from\n+          which the <code>nexthop</code> is reachable.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow that matches all packets not already handled\n+        (match <code>1</code>) and drops them (action <code>drop;</code>).\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 20: DHCP Relay Response Check</h3>\n+    <p>\n+      This stage process the DHCP response packets coming from the DHCP server.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+         A priority 100 logical flow is added for each logical router port\n+         configured with DHCP relay that matches <code>ip4.src</code> is\n+         DHCP server ip and <code>ip4.dst</code> is lrp IP and\n+         <code>ip4.frag == 0</code> and <code>udp.src == 67</code> and\n+         <code>udp.dst == 67</code> and applies <code>dhcp_relay_resp_chk\n+         </code> action. Original destination ip is stored in reg2.\n+        </p>\n+\n+      <pre>\n+        reg9[8] = dhcp_relay_resp_chk(<var>lrp_ip</var>,\n+                                      <var>dhcp_server_ip</var>);next\n+      </pre>\n+\n+      <p>\n+        if action is successful then, dest mac and dest IP addresses are\n+        updated in the packet and stores 1 into reg9[8] else stores 0 into\n+        reg9[8].\n+      </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advance to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 21: DHCP Relay Response</h3>\n+    <p>\n+      This stage process the DHCP response packets on which\n+      <code>dhcp_relay_resp_chk</code> action is applied in the previous stage.\n+    </p>\n+    <ul>\n+      <li>\n+        <p>\n+          A priority 100 logical flow is added for each logical router port\n+          configured with DHCP relay that matches <code>ip4.src</code> is\n+          DHCP server ip and <code>reg2</code> is lrp IP and\n+          <code>udp.src == 67</code> and <code>udp.dst == 67</code>\n+          and <code>reg9[8] == 1</code> and applies following actions. If\n+          <code>reg9[8]</code> is set to 1 then,\n+          <code>dhcp_relay_resp_chk</code> was successful.\n+        </p>\n+\n+        <pre>\n+ip4.src = <var>lrp ip</var>;\n+udp.dst = 68;\n+outport = <var>lrp port</var>;\n+output;\n+        </pre>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority 1 logical flow is added for the logical router port\n+          on which DHCP relay is enabled that matches <code>ip4.src</code>\n+          is DHCP server ip and <code>reg2</code> is lrp IP and\n+          <code>udp.src == 67</code> and <code>udp.dst == 67</code>\n+          and <code>reg9[8] == 0</code> and drops the packet. If\n+          <code>reg9[8]</code> is set to 0 then,\n+          <code>dhcp_relay_resp_chk</code> was unsuccessful.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 flow that matches all packets to advance to the next\n+        table.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 22: ARP/ND Resolution</h3>\n+\n+    <p>\n+      Any packet that reaches this table is an IP packet whose next-hop\n+      IPv4 address is in <code>reg0</code> or IPv6 address is in\n+      <code>xxreg0</code>.  (<code>ip4.dst</code> or\n+      <code>ip6.dst</code> contains the final destination.)  This table\n+      resolves the IP address in <code>reg0</code> (or\n+      <code>xxreg0</code>) into an output port in <code>outport</code>\n+      and an Ethernet address in <code>eth.dst</code>, using the\n+      following flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-500 flow that matches IP multicast traffic that was\n+          allowed in the routing pipeline. For this kind of traffic the\n+          <code>outport</code> was already set so the flow just advances to\n+          the next table.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Priority-200 flows that match ECMP reply traffic for the routes\n+          configured to use symmetric replies, with actions\n+          <code>push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[32..79]; pop(xxreg1); next;</code>.\n+          <code>xxreg1</code> is used here to avoid masked access to ct_label,\n+          to make the flow HW-offloading friendly.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Static MAC bindings.  MAC bindings can be known statically based on\n+          data in the <code>OVN_Northbound</code> database.  For router ports\n+          connected to logical switches, MAC bindings can be known statically\n+          from the <code>addresses</code> column in the\n+          <code>Logical_Switch_Port</code> table. (Note: the flow is not\n+          installed for IPs of logical switch ports of type\n+          <code>virtual</code>, and dynamic MAC binding is used for those IPs\n+          instead, so that virtual parent failover does not depend on <code>\n+          ovn-northd</code>, to achieve better failover performance.) For\n+          router ports connected to other logical routers, MAC bindings can be\n+          known statically from the <code>mac</code> and <code>networks</code>\n+          column in the <code>Logical_Router_Port</code> table.  (Note: the\n+          flow is NOT installed for the IP addresses that belong to a neighbor\n+          logical router port if the current router has the\n+          <code>options:dynamic_neigh_routers</code> set to <code>true</code>)\n+        </p>\n+\n+        <p>\n+          For each IPv4 address <var>A</var> whose host is known to have\n+          Ethernet address <var>E</var> on router port <var>P</var>, a\n+          priority-100 flow with match <code>outport === <var>P</var>\n+          &amp;&amp; reg0 == <var>A</var></code> has actions\n+          <code>eth.dst = <var>E</var>; next;</code>.\n+        </p>\n+\n+        <p>\n+          For each IPv6 address <var>A</var> whose host is known to have\n+          Ethernet address <var>E</var> on router port <var>P</var>, a\n+          priority-100 flow with match <code>outport === <var>P</var>\n+          &amp;&amp; xxreg0 == <var>A</var></code> has actions\n+          <code>eth.dst = <var>E</var>; next;</code>.\n+        </p>\n+\n+        <p>\n+          For each logical router port with an IPv4 address <var>A</var> and\n+          a mac address of <var>E</var> that is reachable via a different\n+          logical router port <var>P</var>, a priority-100 flow with\n+          match <code>outport === <var>P</var> &amp;&amp; reg0 ==\n+          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;\n+          next;</code>.\n+        </p>\n+\n+        <p>\n+          For each logical router port with an IPv6 address <var>A</var> and\n+          a mac address of <var>E</var> that is reachable via a different\n+          logical router port <var>P</var>, a priority-100 flow with\n+          match <code>outport === <var>P</var> &amp;&amp; xxreg0 ==\n+          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;\n+          next;</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Static MAC bindings from NAT entries.  MAC bindings can also be known\n+          for the entries in the <code>NAT</code> table. Below flows are\n+          programmed for distributed logical routers i.e with a distributed\n+          router port.\n+        </p>\n+\n+        <p>\n+          For each row in the <code>NAT</code> table with IPv4 address\n+          <var>A</var> in the <ref column=\"external_ip\"\n+          table=\"NAT\" db=\"OVN_Northbound\"/> column of\n+          <ref table=\"NAT\" db=\"OVN_Northbound\"/> table, below two flows are\n+          programmed:\n+        </p>\n+\n+        <p>\n+          A priority-100 flow with the match <code>outport == <var>P</var>\n+          &amp;&amp; reg0 == <var>A</var></code> has actions <code>eth.dst =\n+          <var>E</var>; next;</code>, where <code>P</code> is the distributed\n+          logical router port, <var>E</var> is the Ethernet address if set in\n+          the <ref column=\"external_mac\" table=\"NAT\" db=\"OVN_Northbound\"/>\n+          column of <ref table=\"NAT\" db=\"OVN_Northbound\"/> table for of type\n+          <code>dnat_and_snat</code>, otherwise the Ethernet address of the\n+          distributed logical router port. Note that if the\n+          <ref column=\"external_ip\" table=\"NAT\" db=\"OVN_Northbound\"/> is not\n+          within a subnet on the owning logical router, then OVN will only\n+          create ARP resolution flows if the <ref column=\"options:add_route\"/>\n+          is set to <code>true</code>. Otherwise, no ARP resolution flows\n+          will be added.\n+        </p>\n+\n+        <p>\n+          Corresponding to the above flow, a priority-150 flow with the match\n+          <code>inport == <var>P</var> &amp;&amp; outport == <var>P</var>\n+          &amp;&amp; ip4.dst == <var>A</var></code> has actions\n+          <code>drop;</code> to exclude packets that have gone through\n+          DNAT/unSNAT stage but failed to convert the destination, to avoid\n+          loop.\n+        </p>\n+\n+        <p>\n+          For IPv6 NAT entries, same flows are added, but using the register\n+          <code>xxreg0</code> and field <code>ip6</code> for the match.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the router datapath runs a port with <code>redirect-type</code>\n+          set to <code>bridged</code>, for each distributed NAT rule with IP\n+          <var>A</var> in the\n+          <ref column=\"logical_ip\" table=\"NAT\" db=\"OVN_Northbound\"/> column\n+          and logical port <var>P</var> in the\n+          <ref column=\"logical_port\" table=\"NAT\" db=\"OVN_Northbound\"/> column\n+          of <ref table=\"NAT\" db=\"OVN_Northbound\"/> table, a priority-90 flow\n+          with the match <code>outport == <var>Q</var> &amp;&amp; ip.src ===\n+          <var>A</var> &amp;&amp; is_chassis_resident(<var>P</var>)</code>,\n+          where <code>Q</code> is the distributed logical router port and\n+          action <code>get_arp(outport, reg0); next;</code> for IPv4 and\n+          <code>get_nd(outport, xxreg0); next;</code> for IPv6.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Traffic with IP destination an address owned by the router should be\n+          dropped. Such traffic is normally dropped in ingress table\n+          <code>IP Input</code> except for IPs that are also shared with SNAT\n+          rules. However, if there was no unSNAT operation that happened\n+          successfully until this point in the pipeline and the destination IP\n+          of the packet is still a router owned IP, the packets can be safely\n+          dropped.\n+        </p>\n+\n+        <p>\n+          A priority-2 logical flow with match <code>ip4.dst = {..}</code>\n+          matches on traffic destined to router owned IPv4 addresses which are\n+          also SNAT IPs. This flow has action <code>drop;</code>.\n+        </p>\n+\n+        <p>\n+          A priority-2 logical flow with match <code>ip6.dst = {..}</code>\n+          matches on traffic destined to router owned IPv6 addresses which are\n+          also SNAT IPs. This flow has action <code>drop;</code>.\n+        </p>\n+\n+        <p>\n+          A priority-0 logical that flow matches all packets not already\n+          handled (match <code>1</code>) and drops them\n+          (action <code>drop;</code>).\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          Dynamic MAC bindings.  These flows resolve MAC-to-IP bindings\n+          that have become known dynamically through ARP or neighbor\n+          discovery.  (The ingress table <code>ARP Request</code> will\n+          issue an ARP or neighbor solicitation request for cases where\n+          the binding is not yet known.)\n+        </p>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>ip4</code> has actions\n+          <code>get_arp(outport, reg0); next;</code>.\n+        </p>\n+\n+        <p>\n+          A priority-0 logical flow with match <code>ip6</code> has actions\n+          <code>get_nd(outport, xxreg0); next;</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For a distributed gateway LRP with <code>redirect-type</code>\n+          set to <code>bridged</code>, a priority-50 flow will match\n+          <code>outport == \"ROUTER_PORT\" and !is_chassis_resident\n+          (\"cr-ROUTER_PORT\")</code> has actions <code>eth.dst = <var>E</var>;\n+          next;</code>, where <var>E</var> is the ethernet address of the\n+          logical router port.\n+        </p>\n+      </li>\n+\n+    </ul>\n+\n+       <h3>Ingress Table 23: Check packet length</h3>\n+\n+    <p>\n+      For distributed logical routers or gateway routers with gateway\n+      port configured with <code>options:gateway_mtu</code> to a valid\n+      integer value, this table adds a priority-50 logical flow with\n+      the match <code>outport == <var>GW_PORT</var></code> where\n+      <var>GW_PORT</var> is the gateway router port and applies the\n+      actions <code>check_pkt_larger</code> and <code>ct_state_save</code>\n+      and then advances the packet to the next table.\n+    </p>\n+\n+    <pre>\n+REGBIT_PKT_LARGER = check_pkt_larger(<var>L</var>);\n+REG_CT_STATE = ct_state_save();\n+next;\n+    </pre>\n+\n+    <p>\n+      where <var>L</var> is the packet length to check for. If the packet\n+      is larger than <var>L</var>, it stores 1 in the register bit\n+      <code>REGBIT_PKT_LARGER</code>. The value of\n+      <var>L</var> is taken from <ref column=\"options:gateway_mtu\"\n+      table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> column of\n+      <ref table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> row.\n+    </p>\n+\n+    <p>\n+      If the port is also configured with\n+      <code>options:gateway_mtu_bypass</code> then another flow is\n+      added, with priority-55, to bypass the <code>check_pkt_larger</code>\n+      flow.\n+    </p>\n+\n+    <p>\n+      This table adds one priority-0 fallback flow that matches all packets\n+      and advances to the next table.\n+    </p>\n+\n+       <h3>Ingress Table 24: Handle larger packets</h3>\n+\n+    <p>\n+      For distributed logical routers or gateway routers with gateway port\n+      configured with <code>options:gateway_mtu</code> to a valid integer\n+      value, this table adds the following priority-150 logical flow for each\n+      logical router port with the match <code>inport == <var>LRP</var>\n+      &amp;&amp; outport == <var>GW_PORT</var> &amp;&amp; REGBIT_PKT_LARGER\n+      &amp;&amp; !REGBIT_EGRESS_LOOPBACK</code>, where <var>LRP</var> is the\n+      logical router port and <var>GW_PORT</var> is the gateway port and\n+      applies the following action for ipv4 and ipv6 respectively:\n+    </p>\n+\n+    <pre>\n+icmp4 {\n+    icmp4.type = 3; /* Destination Unreachable. */\n+    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n+    icmp4.frag_mtu = <var>M</var>;\n+    eth.dst = <var>E</var>;\n+    ip4.dst = ip4.src;\n+    ip4.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER = 0;\n+    next(pipeline=ingress, table=0);\n+};\n+\n+icmp6 {\n+    icmp6.type = 2;\n+    icmp6.code = 0;\n+    icmp6.frag_mtu = <var>M</var>;\n+    eth.dst = <var>E</var>;\n+    ip6.dst = ip6.src;\n+    ip6.src = <var>I</var>;\n+    ip.ttl = 255;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    REGBIT_PKT_LARGER = 0;\n+    next(pipeline=ingress, table=0);\n+};\n+    </pre>\n+\n+    <ul>\n+      <li>\n+        Where <var>M</var> is the (fragment MTU - 58) whose value is taken from\n+        <ref column=\"options:gateway_mtu\" table=\"Logical_Router_Port\"\n+        db=\"OVN_Northbound\"/> column of\n+        <ref table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> row.\n+      </li>\n+\n+      <li>\n+        <var>E</var> is the Ethernet address of the logical router port.\n+      </li>\n+\n+      <li>\n+        <var>I</var> is the IPv4/IPv6 address of the logical router port.\n+      </li>\n+    </ul>\n+\n+    <p>\n+      This table adds one priority-0 fallback flow that matches all packets\n+      and advances to the next table.\n+    </p>\n+\n+       <h3>Ingress Table 25: Gateway Redirect</h3>\n+\n+    <p>\n+      For distributed logical routers where one or more of the logical router\n+      ports specifies a gateway chassis, this table redirects\n+      certain packets to the distributed gateway port instances on the\n+      gateway chassises.  This table has the following flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        For all the configured load balancing rules that include an IPv4\n+        address <var>VIP</var>, and a list of IPv4 backend addresses\n+        <var>B0</var>, <var>B1</var> .. <var>Bn</var> defined for the\n+        <var>VIP</var> a priority-200 flow is added that matches <code>\n+        ip4 &amp;&amp; (ip4.src == <var>B0</var> || ip4.src == <var>B1</var>\n+        || ... || ip4.src == <var>Bn</var>)</code> with an action <code>\n+        outport = <var>CR</var>; next;</code> where <var>CR</var> is the\n+        <code>chassisredirect</code> port representing the instance of the\n+        logical router distributed gateway port on the gateway chassis.\n+        If the backend IPv4 address <var>Bx</var> is also configured with\n+        L4 port <var>PORT</var> of protocol <var>P</var>, then the match\n+        also includes <code>P.src</code> == <var>PORT</var>.\n+        Similar flows are added for IPv6.\n+      </li>\n+\n+      <li>\n+        For each NAT rule in the OVN Northbound database that can\n+        be handled in a distributed manner, a priority-100 logical\n+        flow with match <code>ip4.src == <var>B</var> &amp;&amp;\n+        outport == <var>GW</var></code> &amp;&amp;\n+        is_chassis_resident(<var>P</var>), where <var>GW</var> is\n+        the distributed gateway port specified in the\n+        NAT rule and <var>P</var> is the NAT logical port. IP traffic\n+        matching the above rule will be managed locally setting\n+        <code>reg1</code> to <var>C</var> and\n+        <code>eth.src</code> to <var>D</var>, where <var>C</var> is NAT\n+        external ip and <var>D</var> is NAT external mac.\n+      </li>\n+\n+      <li>\n+        For each <code>dnat_and_snat</code> NAT rule with\n+        <code>stateless=true</code> and <code>allowed_ext_ips</code>\n+        configured, a priority-75 flow is programmed with match\n+        <code>ip4.dst == <var>B</var></code> and action\n+        <code>outport = <var>CR</var>; next;</code> where <var>B</var>\n+        is the NAT rule external IP and <var>CR</var> is the\n+        <code>chassisredirect</code> port representing the instance\n+        of the logical router distributed gateway port on the\n+        gateway chassis. Moreover a priority-70 flow is programmed\n+        with same match and action <code>drop;</code>.\n+        For each <code>dnat_and_snat</code> NAT rule with\n+        <code>stateless=true</code> and <code>exempted_ext_ips</code>\n+        configured, a priority-75 flow is programmed with match\n+        <code>ip4.dst == <var>B</var></code> and action\n+        <code>drop;</code> where <var>B</var> is the NAT rule\n+        external IP.\n+        A similar flow is added for IPv6 traffic.\n+      </li>\n+\n+      <li>\n+        For each NAT rule in the OVN Northbound database that can\n+        be handled in a distributed manner, a priority-80 logical flow\n+        with drop action if the NAT logical port is a virtual port not\n+        claimed by any chassis yet.\n+      </li>\n+\n+      <li>\n+        A priority-50 logical flow with match\n+        <code>outport == <var>GW</var></code> has actions\n+        <code>outport = <var>CR</var>; next;</code>, where\n+        <var>GW</var> is the logical router distributed gateway\n+        port and <var>CR</var> is the <code>chassisredirect</code>\n+        port representing the instance of the logical router\n+        distributed gateway port on the\n+        gateway chassis.\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 26: Network ID</h3>\n+\n+    <p>\n+      This table contains flows that set <code>flags.network_id</code> for\n+      IP packets:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          A priority-110 flow with match:\n+          <ul>\n+            <li>\n+              for IPv4: <code>outport == <var>P</var> &amp;&amp;\n+              REG_NEXT_HOP_IPV4 == <var>I</var>/<var>C</var> &amp;&amp;\n+              ip4</code>\n+            </li>\n+            <li>\n+              for IPv6: <code>outport == <var>P</var> &amp;&amp;\n+              REG_NEXT_HOP_IPV6 == <var>I</var>/<var>C</var> &amp;&amp;\n+              ip6</code>\n+            </li>\n+          </ul>\n+        </p>\n+\n+        <p>\n+          and actions <code>flags.network_id = <var>N</var>; next;</code>.\n+          Where <var>P</var> is the outport, <var>I</var>/<var>C</var> is a\n+          network CIDR of the port <var>P</var>, and <var>N</var> is the\n+          network id (index). There is one flow like this per router port's\n+          network.\n+        </p>\n+\n+        <p>\n+        <code>flags.network_id</code> is 4 bits, and thus only 16 networks can\n+        be indexed. If the number of networks is greater than 16, networks 17\n+        and up will have the actions <code>flags.network_id = 0; next;</code>\n+        and only the lexicographically first IP will be considered for SNAT for\n+        those networks.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A lower priority-105 flow with match <code>1</code> and actions\n+        <code>flags.network_id = 0; next;</code>. This is for the case that the\n+        next-hop doesn't belong to any of the port networks, so\n+        <code>flags.network_id</code> should be set to zero.\n+      </li>\n+\n+      <li>\n+        Catch-all: A priority-0 flow with match <code>1</code> has\n+        actions <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+       <h3>Ingress Table 27: ARP Request</h3>\n+\n+    <p>\n+      In the common case where the Ethernet destination has been resolved, this\n+      table advances the packet to the next table.  Otherwise, it composes and\n+      sends an ARP or IPv6 Neighbor Solicitation request.  It holds the\n+      following flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          Unknown MAC address.  A priority-100 flow for IPv4 packets with match\n+          <code>eth.dst == 00:00:00:00:00:00</code> has the following actions:\n+        </p>\n+\n+        <pre>\n+arp {\n+    eth.dst = ff:ff:ff:ff:ff:ff;\n+    arp.spa = reg1;\n+    arp.tpa = reg0;\n+    arp.op = 1;  /* ARP request. */\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          Unknown MAC address.  For each IPv6 static route associated with the\n+          router with the nexthop IP: <var>G</var>, a priority-200 flow\n+          for IPv6 packets with match\n+          <code>eth.dst == 00:00:00:00:00:00 &amp;&amp;\n+          xxreg0 == <var>G</var></code>\n+          with the following actions is added:\n+        </p>\n+\n+        <pre>\n+nd_ns {\n+    eth.dst = <var>E</var>;\n+    ip6.dst = <var>I</var>\n+    nd.target = <var>G</var>;\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          Where <var>E</var> is the multicast mac derived from the Gateway IP,\n+          <var>I</var> is the solicited-node multicast address corresponding\n+          to the target address <var>G</var>.\n+        </p>\n+\n+        <p>\n+          Unknown MAC address.  A priority-100 flow for IPv6 packets with match\n+          <code>eth.dst == 00:00:00:00:00:00</code> has the following actions:\n+        </p>\n+\n+        <pre>\n+nd_ns {\n+    nd.target = xxreg0;\n+    output;\n+};\n+        </pre>\n+\n+        <p>\n+          (Ingress table <code>IP Routing</code> initialized <code>reg1</code>\n+          with the IP address owned by <code>outport</code> and\n+          <code>(xx)reg0</code> with the next-hop IP address)\n+        </p>\n+\n+        <p>\n+          The IP packet that triggers the ARP/IPv6 NS request is dropped.\n+        </p>\n+      </li>\n+\n+      <li>\n+        Known MAC address.  A priority-0 flow with match <code>1</code> has\n+        actions <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Ingress Table 28: ECMP symmetric reply processing for egress</h3>\n+    <p>\n+      This table contains logical flows that commit IP traffic forwarded by\n+      ECMP symmetric reply static routes in the \"route direction\", that is,\n+      for sessions initiated from behind such routes.  These flows can be hit\n+      only on gateway routers, the only type of routers that supports ECMP\n+      symmetric reply routes.  As the egress port of the traffic needs to be\n+      stored in conntrack for these sessions, one logical flow is added for\n+      each logical router port.\n+    </p>\n+\n+    <h3>Egress Table 0: Check DNAT local </h3>\n+\n+    <p>\n+      This table checks if the packet needs to be DNATed in the router ingress\n+      table <code>lr_in_dnat</code> after it is SNATed  and looped back\n+      to the ingress pipeline.  This check is done only for routers configured\n+      with distributed gateway ports and NAT entries.  This check is done\n+      so that SNAT and DNAT is done in different zones instead of a common\n+      zone.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 1: UNDNAT</h3>\n+\n+    <p>\n+      This is for already established connections' reverse traffic.\n+      i.e., DNAT has already been done in ingress pipeline and now the\n+      packet has entered the egress pipeline as part of a reply.  This traffic\n+      is unDNATed here.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 1: UNDNAT on Gateway Routers</h3>\n+\n+    <ul>\n+      <li>\n+        For IPv6 Neighbor Discovery or Router Solicitation/Advertisement\n+        traffic, a priority-100 flow with action <code>next;</code>.\n+      </li>\n+\n+      <li>\n+        For all IP packets, a priority-50 flow with an action\n+        <code>flags.loopback = 1; ct_dnat;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 1: UNDNAT on Distributed Routers</h3>\n+    <ul>\n+      <li>\n+        <p>\n+          For all the configured load balancing rules for a router with gateway\n+          port in <code>OVN_Northbound</code> database that includes an IPv4\n+          address <code>VIP</code>, for every backend IPv4 address <var>B</var>\n+          defined for the <code>VIP</code> a priority-120 flow is programmed on\n+          gateway chassis that matches\n+          <code>ip &amp;&amp; ip4.src == <var>B</var> &amp;&amp;\n+          outport == <var>GW</var></code>, where <var>GW</var> is the logical\n+          router gateway port with an action <code>ct_dnat;</code>.\n+          If the backend IPv4 address <var>B</var> is also configured with\n+          L4 port <var>PORT</var> of protocol <var>P</var>, then the\n+          match also includes <code>P.src</code> == <var>PORT</var>.  These\n+          flows are not added for load balancers with IPv6 <var>VIPs</var>.\n+        </p>\n+\n+        <p>\n+          If the router is configured to force SNAT  any load-balanced packets,\n+          above action will be replaced by\n+          <code>flags.force_snat_for_lb = 1; ct_dnat;</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each configuration in the OVN Northbound database that asks\n+          to change the destination IP address of a packet from an IP\n+          address of <var>A</var> to <var>B</var>, a priority-100 flow\n+          matches <code>ip &amp;&amp; ip4.src == <var>B</var>\n+          &amp;&amp; outport == <var>GW</var></code>, where <var>GW</var>\n+          is the logical router gateway port, with an action\n+          <code>ct_dnat;</code>. If the NAT rule is of type\n+          dnat_and_snat and has <code>stateless=true</code> in the\n+          options, then the action would be <code>next;</code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule cannot be handled in a distributed manner, then\n+          the priority-100 flow above is only programmed on the\n+          gateway chassis with the action <code>ct_dnat</code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule can be handled in a distributed manner, then\n+          there is an additional action\n+          <code>eth.src = <var>EA</var>;</code>, where <var>EA</var>\n+          is the ethernet address associated with the IP address\n+          <var>A</var> in the NAT rule.  This allows upstream MAC\n+          learning to point to the correct chassis.\n+        </p>\n+      </li>\n+\n+    </ul>\n+\n+    <h3>Egress Table 2: Post UNDNAT</h3>\n+\n+    <p>\n+      <ul>\n+        <li>\n+          A priority-70 logical flow is added that initiates CT state for\n+          traffic that is configured to be SNATed on Distributed routers.\n+          This allows the next table, <code>lr_out_snat</code>, to\n+          effectively match on various CT states.\n+        </li>\n+\n+        <li>\n+          A priority-50 logical flow is added that commits any untracked flows\n+          from the previous table <code>lr_out_undnat</code> for Gateway\n+          routers.  This flow matches on <code>ct.new &amp;&amp; ip</code>\n+          with action <code>ct_commit { } ; next; </code>.\n+        </li>\n+\n+        <li>\n+          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+          the following flows are configured matching on <code>ip &amp;&amp;\n+          (!ct.trk || !ct.rpl) &amp;&amp; flags.unsnat_not_tracked == 1</code>\n+          with  an action <code>ct_next(snat);</code> and <code>ip &amp;&amp;\n+          flags.unsnat_new == 1</code> with an action <code>next;</code>. There\n+          is extra match when there is configured DGP\n+          <code>outport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n+        </li>\n+\n+        <li>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+        </li>\n+\n+      </ul>\n+    </p>\n+\n+    <h3>Egress Table 3: SNAT</h3>\n+\n+    <p>\n+      Packets that are configured to be SNATed get their source IP address\n+      changed based on the configuration in the OVN Northbound database.\n+    </p>\n+\n+    <ul>\n+      <li>\n+        A priority-120 flow to advance the IPv6 Neighbor solicitation packet\n+        to next table to skip SNAT. In the case where ovn-controller injects\n+        an IPv6 Neighbor Solicitation packet (for <code>nd_ns</code> action)\n+        we don't want the packet to go through conntrack.\n+      </li>\n+    </ul>\n+\n+    <p>Egress Table 3: SNAT on Gateway Routers</p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          If the Gateway router in the OVN Northbound database has been\n+          configured to force SNAT a packet (that has been previously DNATted)\n+          to <var>B</var>, a priority-100 flow matches\n+          <code>flags.force_snat_for_dnat == 1 &amp;&amp; ip</code> with an\n+          action <code>ct_snat(<var>B</var>);</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If a load balancer configured to skip snat has been applied to\n+          the Gateway router pipeline, a priority-120 flow matches\n+          <code>flags.skip_snat_for_lb == 1 &amp;&amp; ip</code> with an\n+          action <code>next;</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the Gateway router in the OVN Northbound database has been\n+          configured to force SNAT a packet (that has been previously\n+          load-balanced) using router IP (i.e <ref column=\"options\"\n+          table=\"Logical_Router\"/>:lb_force_snat_ip=router_ip), then for\n+          each logical router port <var>P</var> attached to the Gateway\n+          router, and for each network configured for this port, a priority-110\n+          flow matches <code>flags.force_snat_for_lb == 1</code> &amp;&amp;\n+          <code>ip4</code> &amp;&amp;\n+          <code>flags.network_id == <var>N</var></code> &amp;&amp;\n+          <code>outport == <var>P</var></code>, where <var>N</var> is the\n+          network index, with an action <code>ct_snat(<var>R</var>);</code>\n+          where <var>R</var> is the IP configured on the router port. A similar\n+          flow is created for IPv6, with <code>ip6</code> instead of\n+          <code>ip4</code>. <var>N</var>, the network index, will be 0 for\n+          networks 17 and up.\n+        </p>\n+\n+        <p>\n+          If the logical router port <var>P</var> is configured with multiple\n+          IPv4 and multiple IPv6 addresses, the IPv4 and IPv6 address within\n+          the same network as the next-hop will be chosen as <var>R</var> for\n+          SNAT. However, if there are more than 16 networks configured, the\n+          lexicographically first IP will be considered for SNAT for networks\n+          17 and up.\n+        </p>\n+      </li>\n+      <li>\n+        <p>\n+          A priority-105 flow matches the old behavior for if northd is\n+          upgraded before controller and <code>flags.network_id</code> is not\n+          recognized. It is only added if there's at least one network\n+          configured (excluding LLA for IPv6). It matches on:\n+          <code>flags.force_snat_for_lb == 1</code> &amp;&amp; <code>ip4</code>\n+          &amp;&amp; <code>outport == <var>P</var></code>, with action:\n+          <code>ct_snat(<var>R</var>)</code>.\n+          <var>R</var> is the lexicographically first IP address configured.\n+          There is a similar flow for IPv6 with <code>ip6</code> instead of\n+          <code>ip4</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the Gateway router in the OVN Northbound database has been\n+          configured to force SNAT a packet (that has been previously\n+          load-balanced) to <var>B</var>, a priority-100 flow matches\n+          <code>flags.force_snat_for_lb == 1 &amp;&amp; ip</code> with an\n+          action <code>ct_snat(<var>B</var>);</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the source IP address of a packet from an IP address of\n+          <var>A</var> or to change the source IP address of a packet that\n+          belongs to network <var>A</var> to <var>B</var>, a flow matches\n+          <code>ip &amp;&amp; ip4.src == <var>A</var> &amp;&amp;\n+          (!ct.trk || !ct.rpl)</code> with an action\n+          <code>ct_snat(<var>B</var>);</code>.  The priority of the flow\n+          is calculated based on the mask of <var>A</var>, with matches\n+          having larger masks getting higher priorities. If the NAT rule is\n+          of type dnat_and_snat and has <code>stateless=true</code> in the\n+          options, then the action would be <code>ip4/6.src=\n+          (<var>B</var>)</code>.\n+        </p>\n+\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the source IP address of a packet from an IP address of\n+          <var>A</var> or to change the source IP address of a packet that\n+          belongs to network <var>A</var> to <var>B</var>, match <var>M</var>\n+          and priority <var>P</var>, a flow matches <code>ip &amp;&amp;\n+          ip4.src == <var>A</var> &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp;\n+          (<var>M</var>)</code> with an action <code>ct_snat(<var>B</var>);\n+          </code>.  The priority of the flow is calculated based as\n+          <code>300 + <var>P</var></code>.  If the NAT rule is of type\n+          dnat_and_snat and has <code>stateless=true</code> in the options,\n+          then the action would be <code>ip4/6.src=(<var>B</var>)</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n+          there is an additional match <code>ip4.dst == <var>allowed_ext_ips\n+          </var></code>. Similarly, for IPV6, match would be <code>ip6.dst ==\n+          <var>allowed_ext_ips</var></code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the NAT rule has <code>exempted_ext_ips</code> set, then\n+          there is an additional flow configured at the priority + 1 of\n+          corresponding NAT rule. The flow matches if destination ip\n+          is an <code>exempted_ext_ip</code> and the action is <code>next;\n+          </code>. This flow is used to bypass the ct_snat action for a packet\n+          which is destinted to <code>exempted_ext_ips</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+          the following two flows are configured matching on <code> ip\n+          &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp;\n+          flags.unsnat_new == 1</code> and\n+          <code>ip &amp;&amp; ct.new &amp;&amp; flags.unsnat_not_tracked == 1\n+          </code> both with an action <code>ct_commit_to_zone(snat);</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        <p>\n+          A priority-0 logical flow with match <code>1</code> has actions\n+          <code>next;</code>.\n+        </p>\n+      </li>\n+    </ul>\n+\n+    <p>Egress Table 3: SNAT on Distributed Routers</p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each configuration in the OVN Northbound database, that asks\n+          to change the source IP address of a packet from an IP address of\n+          <var>A</var> or to change the source IP address of a packet that\n+          belongs to network <var>A</var> to <var>B</var>, two flows are\n+          added.  The priority <var>P</var> of these flows are calculated\n+          based on the mask of <var>A</var>, with matches having larger\n+          masks getting higher priorities.\n+        </p>\n+\n+        <p>\n+          If the NAT rule cannot be handled in a distributed manner, then\n+          the below flows are only programmed on the gateway chassis increasing\n+          flow priority by 128 in order to be run first.\n+        </p>\n+\n+        <ul>\n+          <li>\n+            The first flow is added with the calculated priority <var>P</var>\n+            and match <code>ip &amp;&amp; ip4.src == <var>A</var> &amp;&amp;\n+            outport == <var>GW</var></code>, where <var>GW</var> is the\n+            logical router gateway port, with an action\n+            <code>ct_snat(<var>B</var>);</code> to SNATed in the\n+            common zone.  If the NAT rule is of type dnat_and_snat and has\n+            <code>stateless=true</code> in the options, then the action\n+            would be <code>ip4/6.src=(<var>B</var>)</code>.\n+          </li>\n+        </ul>\n+\n+        <p>\n+          If the NAT rule can be handled in a distributed manner, then\n+          there is an additional action (for both the flows)\n+          <code>eth.src = <var>EA</var>;</code>, where <var>EA</var>\n+          is the ethernet address associated with the IP address\n+          <var>A</var> in the NAT rule.  This allows upstream MAC\n+          learning to point to the correct chassis.\n+        </p>\n+\n+        <p>\n+          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n+          there is an additional match <code>ip4.dst == <var>allowed_ext_ips\n+          </var></code>. Similarly, for IPV6, match would be <code>ip6.dst ==\n+          <var>allowed_ext_ips</var></code>.\n+        </p>\n+\n+        <p>\n+          If the NAT rule has <code>exempted_ext_ips</code> set, then\n+          there is an additional flow configured at the priority\n+          <code><var>P</var> + 2 </code> of\n+          corresponding NAT rule. The flow matches if destination ip\n+          is an <code>exempted_ext_ip</code> and the action is <code>next;\n+          </code>. This flow is used to bypass the ct_snat action for a flow\n+          which is destinted to <code>exempted_ext_ips</code>.\n+        </p>\n+\n+      </li>\n+\n+      <li>\n+        An additional flow is added for traffic that goes in opposite\n+        direction (i.e. it enters a network with configured SNAT). Where the\n+        flow above matched on <code>ip4.src == <var>A</var> &amp;&amp; outport\n+        == <var>GW</var></code>, this flow matches on <code> ip4.dst ==\n+        <var>A</var> &amp;&amp; inport == <var>GW</var></code>. A CT state is\n+        initiated for this traffic so that the following table, <code>\n+        lr_out_post_snat</code>, can identify whether the traffic flow was\n+        initiated from the internal or external network.\n+      </li>\n+\n+      <li>\n+        <p>\n+          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n+          the following two flows are configured matching on <code>ip\n+          &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp; flags.unsnat_new == 1\n+          &amp;&amp; outport == DGP &amp;&amp; is_chassis_resident(CHASSIS)\n+          </code> and <code>ip &amp;&amp; ct.new &amp;&amp;\n+          flags.unsnat_not_tracked == 1 &amp;&amp; outport == DGP &amp;&amp;\n+          is_chassis_resident(CHASSIS)</code>both  with an action\n+          <code>ct_commit_to_zone(snat);</code>.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 4: Post SNAT</h3>\n+\n+    <p>\n+      Packets reaching this table are processed according to the flows below:\n+      <ul>\n+        <li>\n+          Traffic that goes directly into a network configured with SNAT on\n+          Distributed routers, and was initiated from an external network (i.e.\n+          it matches <code>ct.new</code>), is committed to the SNAT CT zone.\n+          This ensures that replies returning from the SNATed network do not\n+          have their source address translated. For details about match rules\n+          and priority see section \"Egress Table 3: SNAT on Distributed\n+          Routers\".\n+        </li>\n+\n+        <li>\n+          A priority-0 logical flow that matches all packets not already\n+          handled (match <code>1</code>) and action <code>next;</code>.\n+        </li>\n+      </ul>\n+    </p>\n+\n+    <h3>Egress Table 5: Egress Loopback</h3>\n+\n+    <p>\n+      For distributed logical routers where one of the logical router\n+      ports specifies a gateway chassis.\n+    </p>\n+\n+    <p>\n+      While UNDNAT and SNAT processing have already occurred by this\n+      point, this traffic needs to be forced through egress loopback on\n+      this distributed gateway port instance, in order for UNSNAT and\n+      DNAT processing to be applied, and also for IP routing and ARP\n+      resolution after all of the NAT processing, so that the packet can\n+      be forwarded to the destination.\n+    </p>\n+\n+    <p>\n+      This table has the following flows:\n+    </p>\n+\n+    <ul>\n+      <li>\n+        <p>\n+          For each NAT rule in the OVN Northbound database on a\n+          distributed router, a priority-100 logical flow with match\n+          <code>ip4.dst == <var>E</var> &amp;&amp;\n+          outport == <var>GW</var> &amp;&amp;\n+          is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the\n+          external IP address specified in the NAT rule, <var>GW</var>\n+          is the distributed gateway port corresponding to the NAT rule\n+          (specified or inferred).\n+          For dnat_and_snat NAT rule, <var>P</var> is the logical port\n+          specified in the NAT rule.\n+          If <ref column=\"logical_port\"\n+          table=\"NAT\" db=\"OVN_Northbound\"/> column of\n+          <ref table=\"NAT\" db=\"OVN_Northbound\"/> table is NOT set, then\n+          <var>P</var> is the <code>chassisredirect port</code> of\n+          <var>GW</var> with the following actions:\n+        </p>\n+\n+        <pre>\n+clone {\n+    ct_clear;\n+    inport = outport;\n+    outport = \"\";\n+    flags = 0;\n+    flags.loopback = 1;\n+    reg0 = 0;\n+    reg1 = 0;\n+    ...\n+    reg9 = 0;\n+    REGBIT_EGRESS_LOOPBACK = 1;\n+    next(pipeline=ingress, table=0);\n+};\n+        </pre>\n+\n+        <p>\n+          <code>flags.loopback</code> is set since in_port is unchanged\n+          and the packet may return back to that port after NAT processing.\n+          <code>REGBIT_EGRESS_LOOPBACK</code> is set to indicate that\n+          egress loopback has occurred, in order to skip the source IP\n+          address check against the router address.\n+        </p>\n+      </li>\n+\n+      <li>\n+        A priority-0 logical flow with match <code>1</code> has actions\n+        <code>next;</code>.\n+      </li>\n+    </ul>\n+\n+    <h3>Egress Table 6: Delivery</h3>\n+\n+    <p>\n+      Packets that reach this table are ready for delivery.  It contains:\n+      <ul>\n+        <li>\n+          Priority-110 logical flows that match IP multicast packets on each\n+          enabled logical router port and modify the Ethernet source address\n+          of the packets to the Ethernet address of the port and then execute\n+          action <code>output;</code>.\n+        </li>\n+        <li>\n+          Priority-100 logical flows that match packets on each enabled\n+          logical router port, with action <code>output;</code>.\n+        </li>\n+        <li>\n+          A priority-0 logical flow that matches all packets not already\n+          handled (match <code>1</code>) and drops them\n+          (action <code>drop;</code>).\n+        </li>\n+      </ul>\n+    </p>\n+\n+    <h1>Drop sampling</h1>\n+\n+    <p>\n+      As described in the previous section, there are several places where\n+      ovn-northd might decided to drop a packet by explicitly creating a\n+      <code>Logical_Flow</code> with the <code>drop;</code> action.\n+    </p>\n+\n+    <p>\n+      When debug drop-sampling has been cofigured in the OVN Northbound\n+      database, the ovn-northd will replace all the <code>drop;</code>\n+      actions with a <code>sample(priority=65535, collector_set=<var>id</var>,\n+      obs_domain=<var>obs_id</var>, obs_point=@cookie)</code> action, where:\n+      <ul>\n+        <li>\n+        <var>id</var> is the value the <code>debug_drop_collector_set</code>\n+        option configured in the OVN Northbound.\n+        </li>\n+        <li>\n+        <var>obs_id</var> has it's 8 most significant bits equal to the value\n+        of the <code>debug_drop_domain_id</code> option in the OVN Northbound\n+        and it's 24 least significant bits equal to the datapath's tunnel key.\n+        </li>\n+      </ul>\n+    </p>\n+\n+</manpage>\ndiff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml\nindex 4d6370da6..e5d460382 100644\n--- a/northd/ovn-northd.8.xml\n+++ b/northd/ovn-northd.8.xml\n@@ -255,6068 +255,13 @@\n     </p>\n \n     <h1>Logical Flow Table Structure</h1>\n-\n-    <p>\n-      One of the main purposes of <code>ovn-northd</code> is to populate the\n-      <code>Logical_Flow</code> table in the <code>OVN_Southbound</code>\n-      database.  This section describes how <code>ovn-northd</code> does this\n-      for switch and router logical datapaths.\n-    </p>\n-\n-    <h2>Logical Switch Datapaths</h2>\n-\n-    <h3>Ingress Table 0: Admission Control and Ingress Port Security check</h3>\n-\n-    <p>\n-      Ingress table 0 contains these logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        Priority 100 flows to drop packets with VLAN tags or multicast Ethernet\n-        source addresses.\n-      </li>\n-\n-      <li>\n-        For each disabled logical port, a priority 100 flow is added which\n-        matches on all packets and applies the action\n-        <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code> so that the packets are\n-        dropped in the next stage.\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each logical port that's defined as a target of routing protocol\n-          redirecting (via <code>routing-protocol-redirect</code> option set on\n-          Logical Router Port), a filter is set in place that disallows\n-          following traffic exiting this port:\n-        </p>\n-        <ul>\n-          <li>\n-            ARP replies\n-          </li>\n-          <li>\n-            IPv6 Neighbor Discovery - Router Advertisements\n-          </li>\n-          <li>\n-            IPv6 Neighbor Discovery - Neighbor Advertisements\n-          </li>\n-        </ul>\n-        <p>\n-          Since this port shares IP and MAC addresses with the Logical Router\n-          Port, we wan't to prevent duplicate replies and advertisements. This\n-          is achieved by a rule with priority 80 that sets\n-          <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        For each logical switch that has connected physical ports\n-        (localnet or l2gateway) and is also connected to a distributed router,\n-        filtering rules are added for ARP requests coming from localnet or\n-        l2gateway ports, allowed for processing on gateway chassis.\n-        The <code>REGBIT_EXT_ARP</code> register is set for all ARP requests\n-        originating from physical ports with priority 75 flow.\n-      </li>\n-\n-      <li>\n-        For each (enabled) vtep logical port, a priority 70 flow is added which\n-        matches on all packets and applies the action\n-        <code>next(pipeline=ingress, table=S_SWITCH_IN_L3_LKUP) = 1;</code>\n-        to skip most stages of ingress pipeline and go directly to ingress L2\n-        lookup table to determine the output port. Packets from VTEP (RAMP)\n-        switch should not be subjected to any ACL checks. Egress pipeline will\n-        do the ACL checks.\n-      </li>\n-\n-      <li>\n-        For each enabled logical port configured with qdisc queue id in the\n-        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/>, a priority 70 flow is added which\n-        matches on all packets and applies the action\n-        <code>set_queue(id);\n-        REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;\"</code>.\n-      </li>\n-\n-      <li>\n-        A priority 1 flow is added which matches on all packets for all the\n-        logical ports and applies the action\n-        <code>REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;</code> to\n-        evaluate the port security.  The action <code>check_in_port_sec</code>\n-        applies the port security rules defined in the\n-        <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 1: Ingress Port Security - Apply</h3>\n-\n-    <p>\n-      For each logical switch port <var>P</var> of type router connected to a\n-      gw router a priority-120 flow that matches 'recirculated' icmp{4,6} error\n-      'packet too big' and <code>eth.src == <var>D</var> &amp;&amp;\n-      outport == <var>P</var> &amp;&amp; flags.tunnel_rx == 1</code> where\n-      <var>D</var> is the peer logical router port <var>RP</var> mac address,\n-      swaps inport and outport and applies the action <code>next</code>.\n-    </p>\n-\n-    <p>\n-      For each logical switch port <var>P</var> of type router connected to a\n-      distributed router a priority-120 flow that matches 'recirculated'\n-      icmp{4,6} error 'packet too big' and <code>eth.dst == <var>D</var>\n-      &amp;&amp; flags.tunnel_rx == 1</code> where <var>D</var> is the peer\n-      logical router port <var>RP</var> mac address, swaps inport and outport\n-      and applies the action <code> next(pipeline=S_SWITCH_IN_L2_LKUP)</code>.\n-    </p>\n-\n-    <p>\n-      For each logical switch port <var>P</var> a priority-110 flow that\n-      matches 'recirculated' icmp{4,6} error 'packet too big' and <code>\n-      eth.src == <var>D</var> &amp;&amp; outport == <var>P</var> &amp;&amp;\n-      !is_chassis_resident(\"<var>P</var>\") &amp;&amp; flags.tunnel_rx == 1\n-      </code> where <var>D</var> is the logical switch port mac address,\n-      swaps inport and outport and applies the action <code>next</code>.\n-    </p>\n-\n-    <p>\n-      This table adds a priority-105 flow that matches 'recirculated' icmp{4,6}\n-      error 'packet too big' to drop the packet.\n-    </p>\n-\n-    <p>\n-      This table drops the packets if the port security check failed\n-      in the previous stage i.e the register bit\n-      <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n-    </p>\n-\n-    <p>\n-      Ingress table 1 contains these logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-50 fallback flow that drops the packet if the register\n-        bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-\n-      <li>\n-        Priority 75: Allows <code>REGBIT_EXT_ARP</code> packets only on gateway\n-        chassis and chassis with distributed NAT entries.\n-        Priority 70: Drops <code>REGBIT_EXT_ARP</code> packets on non-gateway\n-        chassis (complements the priority 75 flow).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 2: Mirror </h3>\n-\n-    <p>\n-      Overlay remote mirror table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For each logical switch port with an attached mirror, a logical flow\n-        with a priority of 100 is added. This flow matches all incoming packets\n-        to the attached port, clones them, and forwards the cloned packets to\n-        the mirror target port.\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-\n-      <li>\n-        A logical flow added for each Mirror Rule in Mirror table attached\n-        to logical switch ports, matches all incoming packets that match\n-        rules and clones the packet and sends cloned packet to mirror\n-        target port.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 3: Lookup MAC address learning table</h3>\n-\n-    <p>\n-      This table looks up the MAC learning table of the logical switch\n-      datapath to check if the <code>port-mac</code> pair is present\n-      or not. MAC is learnt for logical switch VIF ports whose\n-      port security is disabled and 'unknown' address setn as well as\n-      for localnet ports with option localnet_learn_fdb. A localnet\n-      port entry does not overwrite a VIF port entry.\n-      Logical switch ports with type <code>switch</code> have implicit\n-      'unknown' addresses and so they are also eligible for MAC learning.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each such VIF logical port <var>p</var> whose port security\n-          is disabled and 'unknown' address set following flow\n-          is added.\n-        </p>\n-\n-        <ul>\n-          <li>\n-            Priority 100 flow with the match\n-            <code>inport == <var>p</var></code> and action\n-            <code>reg0[11] = lookup_fdb(inport, eth.src); next;</code>\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each such localnet logical port <var>p</var> following flow\n-          is added.\n-        </p>\n-\n-        <ul>\n-          <li>\n-            Priority 100 flow with the match\n-            <code>inport == <var>p</var></code> and action\n-            <code>flags.localnet = 1;</code>\n-            <code>reg0[11] = lookup_fdb(inport, eth.src); next;</code>\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 4: Learn MAC of 'unknown' ports.</h3>\n-\n-    <p>\n-      This table learns the MAC addresses seen on the VIF or 'switch' logical\n-      ports whose port security is disabled and 'unknown' address set (note:\n-      'switch' ports have implicit 'unknown' addresses) as well\n-      as on localnet ports with localnet_learn_fdb option set\n-      if the <code>lookup_fdb</code> action returned false in the\n-      previous table. For localnet ports (with flags.localnet = 1),\n-      lookup_fdb returns true if (port, mac) is found or if a mac\n-      is found for a port of type vif.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each such VIF logical port <var>p</var> whose port security is\n-          disabled and 'unknown' address set and localnet port following flow\n-          is added.\n-        </p>\n-\n-        <ul>\n-          <li>\n-            Priority 100 flow with the match\n-            <code>inport == <var>p</var> &amp;&amp; reg0[11] == 0</code> and\n-            action <code>put_fdb(inport, eth.src); next;</code> which stores\n-            the <code>port-mac</code> in the mac learning table of the\n-            logical switch datapath and advances the packet to the next table.\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 5: <code>from-lport</code> Pre-ACLs</h3>\n-\n-    <p>\n-      This table prepares flows for possible stateful ACL processing in\n-      ingress table <code>ACLs</code>.  It contains a priority-0 flow that\n-      simply moves traffic to the next table.  If stateful ACLs are used in the\n-      logical datapath, a priority-100 flow is added that sets a hint\n-      (with <code>reg0[0] = 1; next;</code>) for table\n-      <code>Pre-stateful</code> to send IP packets to the connection tracker\n-      before eventually advancing to ingress table <code>ACLs</code>. If\n-      special ports such as route ports or localnet ports can't use ct(), a\n-      priority-110 flow is added to skip over stateful ACLs.  This\n-      priority-110 flow is not addd for router ports if the option\n-      enable_router_port_acl is set to true in\n-      <ref column=\"options:enable_router_port_acl\"\n-      table=\"Logical_Switch_Port\" db=\"OVN_Northbound\"/> column of\n-      <ref table=\"Logical_Switch_Port\" db=\"OVN_Northbound\"/>.  Multicast, IPv6\n-      Neighbor Discovery and MLD traffic also skips stateful ACLs. For\n-      \"allow-stateless\" ACLs, a flow is added to bypass setting the hint for\n-      connection tracker processing when there are stateful ACLs or LB rules;\n-      <code>REGBIT_ACL_STATELESS</code> is set for traffic matching stateless\n-      ACL flows.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>eth.dst == <var>E</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>E</var>\n-      is the service monitor mac defined in the\n-      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> table.\n-    </p>\n-\n-    <h3>Ingress Table 6: Pre-LB</h3>\n-\n-    <p>\n-      This table prepares flows for possible stateful load balancing processing\n-      in ingress table <code>LB</code> and <code>Stateful</code>.  It contains\n-      a priority-0 flow that simply moves traffic to the next table. Moreover\n-      it contains two priority-110 flows to move multicast, IPv6 Neighbor\n-      Discovery and MLD traffic to the next table. It also contains two\n-      priority-110 flows to move stateless traffic, i.e traffic for which\n-      <code>REGBIT_ACL_STATELESS</code> is set, to the next table. If load\n-      balancing rules with virtual IP addresses (and ports) are configured in\n-      <code>OVN_Northbound</code> database for a logical switch datapath, a\n-      priority-100 flow is added with the match <code>ip</code> to match on IP\n-      packets and sets the action <code>reg0[2] = 1; next;</code> to act as a\n-      hint for table <code>Pre-stateful</code> to send IP packets to the\n-      connection tracker for packet de-fragmentation (and to possibly do DNAT\n-      for already established load balanced traffic) before eventually\n-      advancing to ingress table <code>Stateful</code>.\n-      If controller_event has been enabled and load balancing rules with\n-      empty backends have been added in <code>OVN_Northbound</code>, a 130 flow\n-      is added to trigger ovn-controller events whenever the chassis receives a\n-      packet for that particular VIP. If <code>event-elb</code> meter has been\n-      previously created, it will be associated to the empty_lb logical flow\n-    </p>\n-\n-    <p>\n-      Prior to <code>OVN 20.09</code> we were setting the\n-      <code>reg0[0] = 1</code> only if the IP destination matches the load\n-      balancer VIP. However this had few issues cases where a logical switch\n-      doesn't have any ACLs with <code>allow-related</code> action.\n-      To understand the issue lets a take a TCP load balancer -\n-      <code>10.0.0.10:80=10.0.0.3:80</code>. If a logical port - p1 with\n-      IP - 10.0.0.5 opens a TCP connection with the VIP - 10.0.0.10, then the\n-      packet in the ingress pipeline of 'p1' is sent to the p1's conntrack zone\n-      id and the packet is load balanced to the backend - 10.0.0.3. For the\n-      reply packet from the backend lport, it is not sent to the conntrack of\n-      backend lport's zone id. This is fine as long as the packet is valid.\n-      Suppose the backend lport sends an invalid TCP packet (like incorrect\n-      sequence number), the packet gets delivered to the lport 'p1' without\n-      unDNATing the packet to the VIP - 10.0.0.10. And this causes the\n-      connection to be reset by the lport p1's VIF.\n-    </p>\n-\n-    <p>\n-      We can't fix this issue by adding a logical flow to drop ct.inv packets\n-      in the egress pipeline since it will drop all other connections not\n-      destined to the load balancers. To fix this issue, we send all the\n-      packets to the conntrack in the ingress pipeline if a load balancer is\n-      configured. We can now add a lflow to drop ct.inv packets.\n-    </p>\n-\n-    <p>\n-      This table also has priority-120 flows that punt all IGMP/MLD packets to\n-      <code>ovn-controller</code> if the switch is an interconnect switch\n-      with multicast snooping enabled.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>eth.dst == <var>E</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>E</var>\n-      is the service monitor mac defined in the\n-      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> table.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>inport == <var>I</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>I</var>\n-      is the peer of a logical router port. This flow is added to\n-      skip the connection tracking of packets which enter from\n-      logical router datapath to logical switch datapath.\n-    </p>\n-\n-    <h3>Ingress Table 7: Pre-stateful</h3>\n-\n-    <p>\n-      This table prepares flows for all possible stateful processing\n-      in next tables.  It contains a priority-0 flow that simply moves\n-      traffic to the next table.\n-    </p>\n-    <ul>\n-      <li>\n-        Priority-120 flows that send the packets to connection tracker using\n-        <code>ct_lb_mark;</code> as the action so that the already established\n-        traffic destined to the load balancer VIP gets DNATted. These flows\n-        match each VIPs IP and port. For IPv4 traffic the flows also load the\n-        original destination IP and transport port in registers\n-        <code>reg1</code> and <code>reg2</code>.  For IPv6 traffic the flows\n-        also load the original destination IP and transport port in\n-        registers <code>xxreg1</code> and <code>reg2</code>.\n-      </li>\n-\n-      <li>\n-         A priority-110 flow sends the packets that don't match the above flows\n-         to connection tracker based on a hint provided by the previous tables\n-         (with a match for <code>reg0[2] == 1</code>) by using the\n-         <code>ct_lb_mark;</code> action.\n-      </li>\n-\n-      <li>\n-         A priority-105 added enabled when enable-stateless-acl-with-lb and\n-         send all packet directed to VIP that don't match the above flows to\n-         connection tracker.\n-      </li>\n-\n-      <li>\n-         A priority-100 flow sends the packets to connection tracker based\n-         on a hint provided by the previous tables\n-         (with a match for <code>reg0[0] == 1</code>) by using the\n-         <code>ct_next;</code> action.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 8: <code>from-lport</code> ACL hints</h3>\n-\n-    <p>\n-      This table consists of logical flows that set hints\n-      (<code>reg0</code> bits) to be used in the next stage, in the ACL\n-      processing table, if stateful ACLs or load balancers are configured.\n-      Multiple hints can be set for the same packet.\n-      The possible hints are:\n-    </p>\n-    <ul>\n-      <li>\n-        <code>reg0[7]</code>: the packet might match an\n-        <code>allow-related</code> ACL and might have to commit the\n-        connection to conntrack.\n-      </li>\n-      <li>\n-        <code>reg0[8]</code>: the packet might match an\n-        <code>allow-related</code> ACL but there will be no need to commit\n-        the connection to conntrack because it already exists.\n-      </li>\n-      <li>\n-        <code>reg0[9]</code>: the packet might match a\n-        <code>drop/reject</code>.\n-      </li>\n-      <li>\n-        <code>reg0[10]</code>: the packet might match a\n-        <code>drop/reject</code> ACL but the connection was previously\n-        allowed so it might have to be committed again with\n-        <code>ct_label=1/1</code>.\n-      </li>\n-    </ul>\n-\n-    <p>\n-      The table contains the following flows:\n-    </p>\n-    <ul>\n-      <li>\n-        A priority-65535 flow to advance to the next table if the logical\n-        switch has <code>no</code> ACLs configured, otherwise a\n-        priority-0 flow to advance to the next table.\n-      </li>\n-    </ul>\n-\n-    <ul>\n-      <li>\n-        A priority-7 flow that matches on packets that initiate a new session.\n-        This flow sets <code>reg0[7]</code> and <code>reg0[9]</code> and\n-        then advances to the next table.\n-      </li>\n-      <li>\n-        A priority-6 flow that matches on packets that are in the request\n-        direction of an already existing session that has been marked\n-        as blocked. This flow sets <code>reg0[7]</code> and\n-        <code>reg0[9]</code> and then advances to the next table.\n-      </li>\n-      <li>\n-        A priority-5 flow that matches untracked packets. This flow sets\n-        <code>reg0[8]</code> and <code>reg0[9]</code> and then advances to\n-        the next table.\n-      </li>\n-      <li>\n-        A priority-4 flow that matches on packets that are in the request\n-        direction of an already existing session that has not been marked\n-        as blocked. This flow sets <code>reg0[8]</code> and\n-        <code>reg0[10]</code> and then advances to the next table.\n-      </li>\n-      <li>\n-        A priority-3 flow that matches on packets that are in not part of\n-        established sessions. This flow sets <code>reg0[9]</code> and then\n-        advances to the next table.\n-      </li>\n-      <li>\n-        A priority-2 flow that matches on packets that are part of an\n-        established session that has been marked as blocked.\n-        This flow sets <code>reg0[9]</code> and then advances to the next\n-        table.\n-      </li>\n-      <li>\n-        A priority-1 flow that matches on packets that are part of an\n-        established session that has not been marked as blocked.\n-        This flow sets <code>reg0[10]</code> and then advances to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress table 9: <code>from-lport</code> ACL evaluation before LB</h3>\n-\n-    <p>\n-      Logical flows in this table closely reproduce those in the\n-      <code>ACL</code> table in the <code>OVN_Northbound</code> database\n-      for the <code>from-lport</code> direction without the option\n-      <code>apply-after-lb</code> set or set to <code>false</code>.\n-      The <code>priority</code> values from the <code>ACL</code> table have a\n-      limited range and have 1000 added to them to leave room for OVN default\n-      flows at both higher and lower priorities.\n-    </p>\n-    <ul>\n-      <li>\n-        This table is responsible for evaluating ACLs, and setting a register\n-        bit to indicate whether the ACL decided to allow, drop, or reject the\n-        traffic. The allow bit is <code>reg8[16]</code>. The drop bit is\n-        <code>reg8[17]</code>. All flows in this table will advance the packet\n-        to the next table, where the bits from before are evaluated to\n-        determine what to do with the packet. Any flows in this table that\n-        intend for the packet to pass will set <code>reg8[16]</code> to 1,\n-        even if an ACL with an allow-type action was not matched. This lets the\n-        next table know to allow the traffic to pass. These bits will be\n-        referred to as the \"allow\", \"drop\", and \"reject\" bits in the upcoming\n-        paragraphs.\n-      </li>\n-      <li>\n-        If the <code>tier</code> column has been configured on the ACL, then\n-        OVN will also match the current tier counter against the configured\n-        ACL tier. OVN keeps count of the current tier in\n-        <code>reg8[30..31]</code>.\n-      </li>\n-      <li>\n-        <code>allow</code> ACLs translate into logical flows that set the allow\n-        bit to 1 and advance the packet to the next table. If there are any\n-        stateful ACLs on this datapath, then <code>allow</code> ACLs set the\n-        allow bit to one and in addition perform <code>ct_commit;</code> (which\n-        acts as a hint for future tables to commit the connection to\n-        conntrack). In case the <code>ACL</code> has a label then\n-        <code>reg3</code> is loaded with the label value and\n-        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n-        next tables to commit the label to conntrack).\n-      </li>\n-      <li>\n-        <code>allow-related</code> ACLs translate into logical flows that set\n-        the allow bit and additionally have <code>ct_commit { ct_label=0/1; };\n-        next;</code> actions for new connections and <code>reg0[1] = 1;\n-        next;</code> for existing connections.  In case the <code>ACL</code>\n-        has a label then <code>reg3</code> is loaded with the label value and\n-        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n-        next tables to commit the label to conntrack).\n-      </li>\n-      <li>\n-        For <code>allow</code> and <code>allow-related</code> ACL, an\n-        additonal set of registers get set in case the ACL has the column\n-        <code>network_function_group</code> set to the <var>id</var> of one\n-        of the entities in <code>Network_Function_Group</code> table. The\n-        <var>id</var> is an internally generated unique identifier for a\n-        <code>Network_Function_Group</code> entity. The flow sets\n-        <code>reg8[21] = 1</code> (to indicate need for packet redirection),\n-        <code>reg8[22] = 1</code> (to indicate this is a request packet) and\n-        <code>reg0[22..29] = <var>id</var></code>. These registers are later\n-        used in the <code>Network Function</code> table.\n-      </li>\n-\n-      <li>\n-        <code>allow-stateless</code> ACLs translate into logical flows that set\n-        the allow bit and advance to the next table.\n-      </li>\n-      <li>\n-        <code>reject</code> ACLs translate into logical flows with that set the\n-        reject bit and advance to the next table.\n-      </li>\n-      <li>\n-        <code>pass</code> ACLs translate into logical flows that do not set the\n-        allow, drop, or reject bit and advance to the next table.\n-      </li>\n-      <li>\n-        Other ACLs set the drop bit and advance to the next table for new or\n-        untracked connections. For known connections, they set the drop bit,\n-        as well as running the <code>ct_commit { ct_label=1/1; };</code>\n-        action.  Setting <code>ct_label</code> marks a connection as one that\n-        was previously allowed, but should no longer be allowed due to a policy\n-        change.\n-      </li>\n-    </ul>\n-\n-    <p>\n-      This table contains a priority-65535 flow to set the allow bit and\n-      advance to the next table if the logical switch has <code>no</code>\n-      ACLs configured, otherwise a priority-0 flow to advance to the next\n-      table is added. This flow does not set the allow bit, so that the next\n-      table can decide whether to allow or drop the packet based on the value\n-      of the <ref column=\"options:default_acl_drop\" table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> column of the <ref table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> table.\n-    </p>\n-\n-    <p>\n-      A priority-65532 flow is added that sets the allow bit for\n-      IPv6 Neighbor solicitation, Neighbor discover, Router solicitation,\n-      Router advertisement and MLD packets regardless of other ACLs defined.\n-    </p>\n-\n-    <p>\n-      If the logical datapath has a stateful ACL or a load balancer with VIP\n-      configured, the following flows will also be added:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        If <ref column=\"options:default_acl_drop\" table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> is <code>false</code> or not set, a priority-1\n-        flow that sets the hint to commit IP traffic that is not part of\n-        established sessions to the connection tracker (with action\n-        <code>reg0[1] = 1; next;</code>).  This is needed for\n-        the default allow policy because, while the initiator's direction\n-        may not have any stateful rules, the server's may and then\n-        its return traffic would not be known and marked as invalid.\n-      </li>\n-\n-      <li>\n-        A priority-1 flow that sets the allow bit and sets the hint to commit\n-        IP traffic to the connection tracker (with action <code>reg0[1] = 1;\n-        next;</code>).  This is needed for the default allow policy because,\n-        while the initiator's direction may not have any stateful rules, the\n-        server's may and then its return traffic would not be known and marked\n-        as invalid.\n-      </li>\n-\n-      <li>\n-        A priority-65532 flow that sets the allow bit for any traffic in the\n-        reply direction for a connection that has been committed to the\n-        connection tracker (i.e., established flows), as long as\n-        the committed flow does not have <code>ct_mark.blocked</code> set.\n-        We only handle traffic in the reply direction here because\n-        we want all packets going in the request direction to still\n-        go through the flows that implement the currently defined\n-        policy based on ACLs.  If a connection is no longer allowed by\n-        policy, <code>ct_mark.blocked</code> will get set and packets in the\n-        reply direction will no longer be allowed, either. This flow also\n-        clears the register bits <code>reg0[9]</code> and\n-        <code>reg0[10]</code> and sets register bit <code>reg0[17]</code>.\n-        If ACL logging and logging of related packets is enabled, then a\n-        companion priority-65533 flow will be installed that\n-        accomplishes the same thing but also logs the traffic.\n-      </li>\n-\n-      <li>\n-        The priority-65532 flows that allow response and related traffic, also\n-        set <code>reg8[21] = ct_label.nf</code>, which gets checked in\n-        the <code>Network Function</code> table.\n-      </li>\n-\n-      <li>\n-        A priority-65532 flow that sets the allow bit for any traffic that is\n-        considered related to a committed flow in the connection tracker (e.g.,\n-        an ICMP Port Unreachable from a non-listening UDP port), as long\n-        as the committed flow does not have <code>ct_mark.blocked</code> set.\n-        This flow also applies NAT to the related traffic so that ICMP headers\n-        and the inner packet have correct addresses.\n-        If ACL logging and logging of related packets is enabled, then a\n-        companion priority-65533 flow will be installed that accomplishes the\n-        same thing but also logs the traffic.\n-      </li>\n-\n-      <li>\n-        A priority-65532 flow that sets the drop bit for all traffic marked by\n-        the connection tracker as invalid.\n-      </li>\n-\n-      <li>\n-        A priority-65532 flow that sets the drop bit for all traffic in the\n-        reply direction with <code>ct_mark.blocked</code> set meaning that the\n-        connection should no longer be allowed due to a policy change.  Packets\n-        in the request direction are skipped here to let a newly created\n-        ACL re-allow this connection.\n-      </li>\n-    </ul>\n-\n-    <p>\n-      If the logical datapath has any ACL or a load balancer with VIP\n-      configured, the following flow will also be added:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority 34000 logical flow is added for each logical switch datapath\n-        with the match <code>eth.dst = <var>E</var></code> to allow the service\n-        monitor reply packet destined to <code>ovn-controller</code>\n-        that sets the allow bit, where <var>E</var> is the\n-        service monitor mac defined in the\n-        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 10: <code>from-lport</code> ACL sampling</h3>\n-\n-    <p>\n-      Logical flows in this table sample traffic matched by\n-      <code>from-lport</code> ACLs with sampling enabled.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        If no ACLs have sampling enabled, then a priority 0 flow is installed\n-        that matches everything and advances to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_new configured a priority 1100 flow is\n-        installed that matches on the saved observation_point_id value.\n-        This flow generates a <code>sample()</code> action and then advances\n-        the packet to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_est configured a priority 1200 flow is\n-        installed that matches on the saved observation_point_id value\n-        for established traffic in the original direction.  This flow\n-        generates a <code>sample()</code> action and then advances\n-        the packet to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_est configured a priority 1200 flow is\n-        installed that matches on the saved observation_point_id\n-        value for established traffic in the reply direction.  This flow\n-        generates a <code>sample()</code> action and then advances\n-        the packet to the next table.  Note: this flow is installed in the\n-        opposite pipeline (in the ingress pipeline for ACLs applied in the\n-        egress direction and in the egress pipeline for ACLs applied in the\n-        ingress direction).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 11: <code>from-lport</code> ACL action</h3>\n-\n-    <p>\n-      Logical flows in this table decide how to proceed based on the values of\n-      the allow, drop, and reject bits that may have been set in the previous\n-      table.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        If no ACLs are configured, then a priority 0 flow is installed that\n-        matches everything and advances to the next table.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will advance the packet to the\n-        next table if the allow bit is set.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will run the <code>drop;</code>\n-        action if the drop bit is set.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will run the <code>tcp_reset\n-        { output &lt;-&gt; inport; next(pipeline=egress,table=5);}</code>\n-        action for TCP connections,<code>icmp4/icmp6</code> action\n-        for UDP connections, and <code>sctp_abort {output &lt;-%gt; inport;\n-        next(pipeline=egress,table=5);}</code> action for SCTP associations.\n-      </li>\n-\n-      <li>\n-        If any ACLs have tiers configured on them, then three priority 500\n-        flows are installed. If the current tier counter is 0, 1, or 2, then\n-        the current tier counter is incremented by one and the packet is sent\n-        back to the previous table for re-evaluation.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 12: <code>from-lport</code> QoS</h3>\n-\n-    <p>\n-      Logical flows in this table closely reproduce those in the\n-      <code>QoS</code> table with the <code>action</code> or\n-      <code>bandwidth</code> column set in the\n-      <code>OVN_Northbound</code> database for the\n-      <code>from-lport</code> direction.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For every qos_rules entry in a logical switch with DSCP marking,\n-        packet marking or metering enabled a flow will be added at the priority\n-        mentioned in the QoS table.\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 13: Connection Tracking Field Extraction</h3>\n-\n-    <p>\n-      This table extracts connection tracking fields for new connections\n-      to be used by subsequent load balancing stages.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-100 flow matches <code>ct.new &amp;&amp; ip</code> and\n-        extracts connection tracking protocol and destination port information\n-        into registers <code>reg1[16..23]</code> (protocol) and\n-        <code>reg1[0..15]</code> (destination port) using the actions\n-        <code>reg1[16..23] = ct_proto(); reg1[0..15] = ct_tp_dst(); next;</code>.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow matches all packets and advances to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 14: Load balancing affinity check</h3>\n-\n-    <p>\n-      Load balancing affinity check table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a switch in\n-        <code>OVN_Northbound</code> database where a positive affinity timeout\n-        is specified in <code>options</code> column, that includes a L4 port\n-        <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>,\n-        a priority-100 flow is added. For IPv4 <var>VIPs</var>, the flow\n-        matches <code>ct.new &amp;&amp; ip &amp;&amp; ip4.dst == <var>VIP</var>\n-        &amp;&amp; reg1[16..23] == <var>PROTO_NUM</var> &amp;&amp;\n-        reg1[0..15] == <var>PORT</var></code>. For IPv6\n-        <var>VIPs</var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n-        ip6.dst == <var>VIP</var> &amp;&amp; reg1[16..23] ==\n-        <var>PROTO_NUM</var> &amp;&amp; reg1[0..15] == <var>PORT</var></code>.\n-        The flow's action is <code>reg9[6] = chk_lb_aff(); next;</code>.\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 15: LB</h3>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a switch in\n-        <code>OVN_Northbound</code> database where a positive affinity timeout\n-        is specified in <code>options</code> column, that includes a L4 port\n-        <var>PORT</var> of protocol <var>P</var> and IP address <var>VIP</var>,\n-        a priority-150 flow is added. For IPv4 <var>VIPs</var>, the flow\n-        matches <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp; ip &amp;&amp;\n-        ip4.dst == <var>VIP</var> &amp;&amp; <var>P</var>.dst == <var>PORT\n-        </var></code>. For IPv6 <var>VIPs</var>, the flow matches\n-        <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp; ip &amp;&amp;\n-        ip6.dst == <var> VIP </var>&amp;&amp; <var>P</var> &amp;&amp;\n-        <var>P</var>.dst == <var> PORT</var></code>.\n-        The flow's action is <code>ct_lb_mark(<var>args</var>)</code>, where\n-        <var>args</var> contains comma separated IP addresses (and optional\n-        port numbers) to load balance to.  The address family of the IP\n-        addresses of <var>args</var> is the same as the address family\n-        of <var>VIP</var>.\n-      </li>\n-\n-      <li>\n-        For all the configured load balancing rules for a switch in\n-        <code>OVN_Northbound</code> database that includes a L4 port\n-        <var>PORT</var> of protocol <var>P</var> and IP address\n-        <var>VIP</var>, a priority-120 flow is added.  For IPv4 <var>VIPs\n-        </var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n-        ip4.dst == <var>VIP</var> &amp;&amp; reg1[16..23] ==\n-        <var>PROTO_NUM</var> &amp;&amp; reg1[0..15] == <var>PORT</var></code>.\n-        For IPv6 <var>VIPs</var>,\n-        the flow matches <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>\n-        VIP </var>&amp;&amp; reg1[16..23] == <var>PROTO_NUM</var> &amp;&amp;\n-        reg1[0..15] == <var>PORT</var></code>. The flow's action is\n-        <code>ct_lb_mark(<var>args</var>)\n-        </code>, where <var>args</var> contains comma separated IP addresses\n-        (and optional port numbers) to load balance to.  The address family of\n-        the IP addresses of <var>args</var> is the same as the address family\n-        of <var>VIP</var>. If health check is enabled, then <var>args</var>\n-        will only contain those endpoints whose service monitor status entry\n-        in <code>OVN_Southbound</code> db is either <code>online</code> or\n-        empty.  For IPv4 traffic the flow also loads the original destination\n-        IP and transport port in registers <code>reg1</code> and\n-        <code>reg2</code>.  For IPv6 traffic the flow also loads the original\n-        destination IP and transport port in registers <code>xxreg1</code> and\n-        <code>reg2</code>.\n-        The above flow is created even if the load balancer is attached to a\n-        logical router connected to the current logical switch and\n-        the <code>install_ls_lb_from_router</code> variable in\n-        <ref table=\"NB_Global\" column=\"options\"/> is set to true.\n-      </li>\n-      <li>\n-        For all the configured load balancing rules for a switch in\n-        <code>OVN_Northbound</code> database that includes just an IP address\n-        <var>VIP</var> to match on, OVN adds a priority-110 flow.  For IPv4\n-        <var>VIPs</var>, the flow matches <code>ct.new &amp;&amp; ip &amp;&amp;\n-        ip4.dst == <var>VIP</var></code>. For IPv6 <var>VIPs</var>,\n-        the flow matches <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>\n-        VIP</var></code>. The action on this flow is <code>\n-        ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains comma\n-        separated IP addresses of the same address family as <var>VIP</var>.\n-        For IPv4 traffic the flow also loads the original destination\n-        IP and transport port in registers <code>reg1</code> and\n-        <code>reg2</code>.  For IPv6 traffic the flow also loads the original\n-        destination IP and transport port in registers <code>xxreg1</code> and\n-        <code>reg2</code>.\n-        The above flow is created even if the load balancer is attached to a\n-        logical router connected to the current logical switch and\n-        the <code>install_ls_lb_from_router</code> variable in\n-        <ref table=\"NB_Global\" column=\"options\"/> is set to true.\n-      </li>\n-\n-      <li>\n-        If the load balancer is created with <code>--reject</code> option and\n-        it has no active backends, a TCP reset segment (for tcp) or an ICMP\n-        port unreachable packet (for all other kind of traffic) will be sent\n-        whenever an incoming packet is received for this load-balancer.\n-        Please note using <code>--reject</code> option will disable\n-        empty_lb SB controller event for this load balancer.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 16: Load balancing affinity learn</h3>\n-\n-    <p>\n-      Load balancing affinity learn table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a switch in\n-        <code>OVN_Northbound</code> database where a positive affinity timeout\n-        <var>T</var> is specified in <code>options</code> column, that includes\n-        a L4 port <var>PORT</var> of protocol <var>P</var> and IP address\n-        <var>VIP</var>, a priority-100 flow is added. For IPv4 <var>VIPs</var>,\n-        the flow matches <code>reg9[6] == 0 &amp;&amp; ct.new &amp;&amp; ip\n-        &amp;&amp; ip4.dst == <var>VIP</var> &amp;&amp; <var>P</var>.dst ==\n-        <var>PORT</var></code>. For IPv6 <var>VIPs</var>, the flow matches\n-        <code>ct.new &amp;&amp; ip &amp;&amp; ip6.dst == <var>VIP</var>\n-        &amp;&amp; <var>P</var> &amp;&amp; <var>P</var>.dst == <var>PORT</var>\n-        </code>. The flow's action is <code>commit_lb_aff(vip =\n-        <var>VIP</var>:<var>PORT</var>, backend = <var>backend ip</var>:\n-        <var>backend port</var>, proto = <var>P</var>, timeout = <var>T</var>);\n-        </code>.\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 17: Pre-Hairpin</h3>\n-    <ul>\n-      <li>\n-        If the logical switch has load balancer(s) configured, then a\n-        priority-100 flow is added with the match\n-        <code>ip &amp;&amp; ct.trk</code> to check if the\n-        packet needs to be hairpinned (if after load balancing the destination\n-        IP matches the source IP) or not by executing the actions\n-        <code>reg0[6] = chk_lb_hairpin();</code> and\n-        <code>reg0[12] = chk_lb_hairpin_reply();</code> and advances the packet\n-        to the next table.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 18: Nat-Hairpin</h3>\n-    <ul>\n-      <li>\n-         If the logical switch has load balancer(s) configured, then a\n-         priority-100 flow is added with the match\n-         <code>ip &amp;&amp; ct.new &amp;&amp; ct.trk &amp;&amp;\n-         reg0[6] == 1</code> which hairpins the traffic by\n-         NATting source IP to the load balancer VIP by executing the action\n-         <code>ct_snat_to_vip</code> and advances the packet to the next table.\n-      </li>\n-\n-      <li>\n-         If the logical switch has load balancer(s) configured, then a\n-         priority-100 flow is added with the match\n-         <code>ip &amp;&amp; ct.est &amp;&amp; ct.trk &amp;&amp;\n-         reg0[6] == 1</code> which hairpins the traffic by\n-         NATting source IP to the load balancer VIP by executing the action\n-         <code>ct_snat</code> and advances the packet to the next table.\n-      </li>\n-\n-      <li>\n-         If the logical switch has load balancer(s) configured, then a\n-         priority-90 flow is added with the match\n-         <code>ip &amp;&amp; reg0[12] == 1</code> which matches on the replies\n-         of hairpinned traffic (i.e., destination IP is VIP,\n-         source IP is the backend IP and source L4 port is backend port for L4\n-         load balancers) and executes <code>ct_snat</code> and advances the\n-         packet to the next table.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 19: Hairpin</h3>\n-    <ul>\n-      <li>\n-        <p>\n-          If logical switch has attached logical switch port of <var>vtep</var>\n-          type, then for each distributed gateway router port <var>RP</var>\n-          attached to this logical switch and has chassis redirect port\n-          <var>cr-RP</var>, a priority-2000 flow is added with the match\n-          <pre>\n-<code>reg0[14] == 1 &amp;&amp; is_chassis_resident(<var>cr-RP</var>)</code>\n-          </pre>\n-          and action <code>next;</code>.\n-        </p>\n-\n-        <p>\n-          <code>reg0[14]</code> register bit is set in the ingress L2 port\n-          security check table for traffic received from HW VTEP (ramp) ports.\n-        </p>\n-      </li>\n-\n-      <li>\n-        If logical switch has attached logical switch port of <var>vtep</var>\n-        type, then a priority-1000 flow that matches on\n-        <code>reg0[14]</code> register bit for the traffic received from HW\n-        VTEP (ramp) ports.  This traffic is passed to ingress table\n-        ls_in_l2_lkup.\n-      </li>\n-      <li>\n-        A priority-1 flow that hairpins traffic matched by non-default\n-        flows in the Pre-Hairpin table. Hairpinning is done at L2, Ethernet\n-        addresses are swapped and the packets are looped back on the input\n-        port.\n-      </li>\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress table 20: <code>from-lport</code> ACL evaluation after LB</h3>\n-\n-    <p>\n-      Logical flows in this table closely reproduce those in the\n-      <code>ACL eval</code> table in the <code>OVN_Northbound</code> database\n-      for the <code>from-lport</code> direction with the option\n-      <code>apply-after-lb</code> set to <code>true</code>.\n-      The <code>priority</code> values from the <code>ACL</code> table have a\n-      limited range and have 1000 added to them to leave room for OVN default\n-      flows at both higher and lower priorities. The flows in this table\n-      indicate the ACL verdict by setting <code>reg8[16]</code> for\n-      <code>allow-type</code> ACLs, <code>reg8[17]</code> for <code>drop</code>\n-      ACLs, and <code>reg8[17]</code> for <code>reject</code> ACLs, and then\n-      advancing the packet to the next table. These will be reffered to as the\n-      allow bit, drop bit, and reject bit throughout the documentation for this\n-      table and the next one.\n-    </p>\n-\n-    <p>\n-      Like with ACLs that are evaluated before load balancers, if the ACL is\n-      configured with a tier value, then the current tier counter, supplied\n-      in reg8[30..31] is matched against the ACL's configured tier in addition\n-      to the ACL's match.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <code>allow</code> apply-after-lb ACLs translate into logical flows\n-        that set the allow bit.  If there are any stateful ACLs\n-        (including both before-lb and after-lb ACLs)\n-        on this datapath, then <code>allow</code> ACLs also run\n-        <code>ct_commit; next;</code> (which acts as a hint for an upcoming\n-        table to commit the connection to conntrack). In case the\n-        <code>ACL</code> has a label then <code>reg3</code> is loaded with the\n-        label value and <code>reg0[13]</code> bit is set to 1 (which acts as a\n-        hint for the next tables to commit the label to conntrack).\n-      </li>\n-      <li>\n-        <code>allow-related</code> apply-after-lb ACLs translate into logical\n-        flows that set the allow bit and run the\n-        <code>ct_commit {ct_label=0/1; }; next;</code> actions for new\n-        connections and <code>reg0[1] = 1; next;</code> for existing\n-        connections.  In case the <code>ACL</code> has a label then\n-        <code>reg3</code> is loaded with the label value and\n-        <code>reg0[13]</code> bit is set to 1 (which acts as a hint for the\n-        next tables to commit the label to conntrack).\n-      </li>\n-      <li>\n-        <code>allow-stateless</code> apply-after-lb ACLs translate into logical\n-        flows that set the allow bit and advance to the next table.\n-      </li>\n-      <li>\n-        <code>reject</code> apply-after-lb ACLs translate into logical\n-        flows that set the reject bit and advance to the next table.\n-      </li>\n-      <li>\n-        <code>pass</code> apply-after-lb ACLs translate into logical flows that\n-        do not set the allow, drop, or reject bit and advance to the next\n-        table.\n-      </li>\n-      <li>\n-        Other apply-after-lb ACLs set the drop bit for new or untracked\n-        connections and <code>ct_commit { ct_label=1/1; }</code> for known\n-        connections.  Setting <code>ct_label</code> marks a connection\n-        as one that was previously allowed, but should no longer be\n-        allowed due to a policy change.\n-      </li>\n-    </ul>\n-\n-    <ul>\n-      <li>\n-        One priority-65532 flow matching packets with <code>reg0[17]</code>\n-        set (either replies to existing sessions or traffic related to\n-        existing sessions) and allows these by setting the allow bit and\n-        advancing to the next table.\n-      </li>\n-    </ul>\n-\n-    <ul>\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 21: <code>from-lport</code> ACL sampling after LB</h3>\n-\n-    <p>\n-      Logical flows in this table sample traffic matched by\n-      <code>from-lport</code> ACLs (evaluation after LB) with sampling enabled.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        If no ACLs have sampling enabled, then a priority 0 flow is installed\n-        that matches everything and advances to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_new configured a priority 1100 flow is\n-        installed that matches on the saved observation_point_id value.\n-        This flow generates a <code>sample()</code> action and then advances\n-        the packet to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_est configured a priority 1200 flow is\n-        installed that matches on the saved observation_point_id value\n-        for established traffic in the original direction.  This flow\n-        generates a <code>sample()</code> action and then advances\n-        the packet to the next table.\n-      </li>\n-\n-      <li>\n-        For each ACL with sample_est configured a priority 1200 flow is\n-        installed that matches on the saved observation_point_id\n-        value for established traffic in the reply direction.  This flow\n-        generates a <code>sample()</code> action and then advances\n-        the packet to the next table.  Note: this flow is installed in the\n-        opposite pipeline (in the ingress pipeline for ACLs applied in the\n-        egress direction and in the egress pipeline for ACLs applied in the\n-        ingress direction).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 22: <code>from-lport</code> ACL action after LB</h3>\n-\n-    <p>\n-      Logical flows in this table decide how to proceed based on the values of\n-      the allow, drop, and reject bits that may have been set in the previous\n-      table.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        If no ACLs are configured, then a priority 0 flow is installed that\n-        matches everything and advances to the next table.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will advance the packet to the\n-        next table if the allow bit is set.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will run the <code>drop;</code>\n-        action if the drop bit is set.\n-      </li>\n-\n-      <li>\n-        A priority 1000 flow is installed that will run the <code>tcp_reset\n-        { output &lt;-&gt; inport; next(pipeline=egress,table=5);}</code>\n-        action for TCP connections,<code>icmp4/icmp6</code> action\n-        for UDP connections, and <code>sctp_abort {output &lt;-%gt; inport;\n-        next(pipeline=egress,table=5);}</code> action for SCTP associations.\n-      </li>\n-\n-      <li>\n-        If any ACLs have tiers configured on them, then three priority 500\n-        flows are installed. If the current tier counter is 0, 1, or 2, then\n-        the current tier counter is incremented by one and the packet is sent\n-        back to the previous table for re-evaluation.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 23: Pre Network Function</h3>\n-    <p>\n-      This stage selects the active network function from a\n-      <code>Network_Function_Group</code> based on the network function group\n-      ID set by the ACL eval stage earlier. This stage is applicable for\n-      request packets of <code>from-lport</code> ACLs\n-      (<code>reg8[22] == 1</code>). Response packets for\n-      <code>to-lport</code> ACLs bypass this stage and use\n-      <code>ct_label.nf_id</code> directly in the Network Function table.\n-    </p>\n-\n-    <p>\n-      A network function group can contain one or more network functions.\n-      Health monitoring is performed by sending datapath probes as per\n-      parameters defined in <code>Network_Function_Health_Check</code>. This\n-      stage selects one of the healthy network functions. If none are healthy,\n-      the behavior follows the <code>fallback</code> column configured in the\n-      <code>Network_Function_Group</code> table. If health monitoring is not\n-      configured, any one from the group is selected.\n-    </p>\n-\n-    <p>\n-      When a request packet matches a <code>from-lport</code> ACL with\n-      <code>network_function_group</code> set, the ACL eval stage sets\n-      <code>reg8[21] = 1</code> (NF enabled), <code>reg8[22] = 1</code>\n-      (request direction), and <code>reg0[22..29]</code> to the network\n-      function group ID. This table then selects the active network function\n-      from the group and overwrites <code>reg0[22..29]</code> with the\n-      specific <code>id</code> of a <code>Network_Function</code> table entry.\n-      The subsequent Network Function table uses this NF ID to redirect packets\n-      to the appropriate network function port. In the future, this stage will\n-      be extended to support network function load balancing.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For each network_function_group <var>id</var> with an active network\n-        function, a priority-99 flow matches <code>reg8[21] == 1 &amp;&amp;\n-        reg8[22] == 1 &amp;&amp; reg0[22..29] == <var>id</var></code> and\n-        sets <code>reg0[22..29] = <var>nf_id</var>; next;</code> where\n-        <var>nf_id</var> is the ID of the active network function. This\n-        prepares request packets that matched a <code>from-lport</code> ACL\n-        with network_function_group for redirection in the subsequent Network\n-        Function table.\n-      </li>\n-\n-      <li>\n-        For each network function group with <var>id</var> that has\n-        <code>fallback</code> set to <code>fail-open</code>, a priority-10 flow\n-        matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n-        reg0[22..29] == <var>id</var></code> and sets <code>reg8[21] = 0;\n-        reg0[22..29] = 0; next;</code>. This clears both the NF enabled bit and\n-        the NF group ID, allowing packets to continue processing through the\n-        pipeline without network function redirection when no active network\n-        function is available (fail-open behavior).\n-      </li>\n-\n-      <li>\n-        A priority-1 flow matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1\n-        </code> and sets <code>reg0[22..29] = 0; next;</code>. This is a\n-        catch-all flow for network function groups with <code>fallback</code>\n-        set to <code>fail-close</code> (or default) when no active network\n-        function is available. It clears only the NF group ID, leaving the NF\n-        enabled bit set. These packets will be dropped by the priority-1 drop\n-        rule in the subsequent Network Function table (fail-close behavior).\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 24: Stateful</h3>\n-\n-    <ul>\n-      <li>\n-        A priority 100 flow is added which commits the packet to the conntrack\n-        and sets the most significant 32-bits of <code>ct_label</code> with the\n-        <code>reg3</code> value based on the hint provided by previous tables\n-        (with a match for <code>reg0[1] == 1 &amp;&amp; reg0[13] == 1</code>).\n-        This is used by the <code>ACLs</code> with label to commit the label\n-        value to conntrack.\n-      </li>\n-\n-      <li>\n-        For <code>ACLs</code> without label, a second priority-100 flow commits\n-        packets to connection tracker using <code>ct_commit; next;</code>\n-        action based on a hint provided by the previous tables (with a match\n-        for <code>reg0[1] == 1 &amp;&amp; reg0[13] == 0</code>).\n-      </li>\n-\n-      <li>\n-        Corresponding to each of the two priority 100 flows above, a priority\n-        110 flow is added, which has the following extra match and\n-        action, but otherwise identical to the priority 100 flow.\n-        Match: <code>reg8[21] == 1</code> (packet matched an ACL with\n-        <code>network_function_group</code> set)\n-        Action: <code>ct_label.nf = 1;\n-        ct_label.nf_id = reg0[22..29];</code>\n-        This is to commit the network_function information in conntrack so that\n-        the response and related packets can be redirected to it as well.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 25: Network Function</h3>\n-    <p>\n-      This table implements packet redirection to network functions. When a\n-      packet matches an ACL with <code>network_function_group</code> column\n-      set to the <code>id</code> of a <code>Network_Function_Group</code>\n-      table entry, the ACL eval stage sets <code>reg8[21] = 1</code> (NF\n-      enabled), <code>reg8[22] = 1</code> (request direction), and\n-      <code>reg0[22..29]</code> to the network function group ID. The Pre\n-      Network Function stage then selects the active network function from the\n-      group and overwrites <code>reg0[22..29]</code> with the specific\n-      <code>id</code> of a <code>Network_Function</code> table entry. This\n-      table uses that NF ID to redirect packets to the appropriate network\n-      function port.\n-    </p>\n-\n-    <p>\n-      This table handles request packets for <code>from-lport</code> ACLs\n-      and response packets for <code>to-lport</code> ACLs. For\n-      <code>from-lport</code> ACLs, request packets are redirected to the\n-      network function's <code>inport</code>, and corresponding\n-      response/related packets are handled in the egress pipeline. For\n-      <code>to-lport</code> ACLs, request packets are handled in the egress\n-      pipeline, but corresponding response/related packets for those flows\n-      are redirected here using the network function ID stored in\n-      <code>ct_label.nf_id</code> during request processing.\n-    </p>\n-\n-    <p>\n-      If the network function ports are not present on this logical switch,\n-      their child ports (if any) are used. In the statements below, network\n-      function ports refer to either the parent or child ports as applicable to\n-      this logical switch.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For each network_function port <var>P</var>, a priority-100 flow is\n-        added that matches <code>inport == <var>P</var></code> and advances\n-        packets to the next table. Thus packets coming from network function\n-        are not subject to redirection. This flow also sets\n-        <code>reg5[16..31] = ct_label.tun_if_id</code>. This is used for\n-        tunneling packet to originating host in case of cross host traffic\n-        redirection for VLAN subnet. This ct_label field stores the openflow\n-        tunnel interface id of the originating host for this connection and\n-        gets populated in egress <code>Stateful</code> table.\n-      </li>\n-\n-      <li>\n-        For each active network function with <var>id</var> that is referenced\n-        in a network function group, a priority-99 flow matches\n-        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n-        reg0[22..29] == <var>id</var></code> and sets\n-        <code>outport=<var>P</var>; output;</code> where <var>P</var> is the\n-        <code>inport</code> of that network function. This redirects request\n-        packets for flows matching <code>from-lport</code> ACLs with\n-        network_function_group to the specific network function selected by\n-        the Pre Network Function stage.\n-      </li>\n-\n-      <li>\n-        For each active network function with <var>id</var> that is referenced\n-        in a network function group, a priority-99 rule matches\n-        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 0 &amp;&amp;\n-        ct_label.nf_id == <var>id</var></code> and takes identical action as\n-        above. This redirects response and related packets for\n-        <code>to-lport</code> ACLs to the same network function that handled\n-        the request, using the NF ID stored in the connection tracking label.\n-      </li>\n-\n-      <li>\n-        In each of the above cases, when the same packet comes out unchanged\n-        through the other port of the network_function, it would match the\n-        priority 100 flow and be forwarded to the next table.\n-      </li>\n-\n-      <li>\n-        One priority-100 rule to skip redirection of multicast packets that hit\n-        a network_function ACL. Match on <code>reg8[21] == 1 &amp;&amp;\n-        eth.mcast</code> and action is to advance to the next table.\n-      </li>\n-\n-      <li>\n-        One priority-1 rule that checks <code>reg8[21] == 1</code>, and drops\n-        such packets. This is to address the case where a packet hit an ACL\n-        with network function but the network function does not have ports or\n-        child ports on this logical switch.\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 26: ARP/ND responder</h3>\n-\n-    <p>\n-      This table implements ARP/ND responder in a logical switch for known\n-      IPs.  The advantage of the ARP responder flow is to limit ARP\n-      broadcasts by locally responding to ARP requests without the need to\n-      send to other hypervisors.  One common case is when the inport is a\n-      logical port associated with a VIF and the broadcast is responded to\n-      on the local hypervisor rather than broadcast across the whole\n-      network and responded to by the destination VM.  This behavior is\n-      proxy ARP.\n-    </p>\n-\n-    <p>\n-      ARP requests arrive from VMs from a logical switch inport of type\n-      default.  For this case, the logical switch proxy ARP rules can be\n-      for other VMs or logical router ports.  Logical switch proxy ARP\n-      rules may be programmed both for mac binding of IP addresses on\n-      other logical switch VIF ports (which are of the default logical\n-      switch port type, representing connectivity to VMs or containers),\n-      and for mac binding of IP addresses on logical switch router type\n-      ports, representing their logical router port peers.  In order to\n-      support proxy ARP for logical router ports, an IP address must be\n-      configured on the logical switch router type port, with the same\n-      value as the peer logical router port.  The configured MAC addresses\n-      must match as well.  When a VM sends an ARP request for a distributed\n-      logical router port and if the peer router type port of the attached\n-      logical switch does not have an IP address configured, the ARP request\n-      will be broadcast on the logical switch.  One of the copies of the ARP\n-      request will go through the logical switch router type port to the\n-      logical router datapath, where the logical router ARP responder will\n-      generate a reply.  The MAC binding of a distributed logical router,\n-      once learned by an associated VM, is used for all that VM's\n-      communication needing routing.  Hence, the action of a VM re-arping for\n-      the mac binding of the logical router port should be rare.\n-    </p>\n-\n-    <p>\n-      Logical switch ARP responder proxy ARP rules can also be hit when\n-      receiving ARP requests externally on a L2 gateway port.  In this case,\n-      the hypervisor acting as an L2 gateway, responds to the ARP request on\n-      behalf of a destination VM.\n-    </p>\n-\n-    <p>\n-      Note that ARP requests received from <code>localnet</code> logical\n-      inports can either go directly to VMs, in which case the VM responds or\n-      can hit an ARP responder for a logical router port if the packet is used\n-      to resolve a logical router port next hop address.  In either case,\n-      logical switch ARP responder rules will not be hit.  It contains these\n-      logical flows:\n-     </p>\n-\n-    <ul>\n-      <li>\n-        If packet was received from HW VTEP (ramp switch), and this packet is\n-        ARP or Neighbor Solicitation, such packet is passed to next table with\n-        max proirity.  ARP/ND requests from HW VTEP must be handled in logical\n-        router ingress pipeline.\n-      </li>\n-      <li>\n-        If the logical switch has no router ports with options:arp_proxy\n-        configured add a priority-100 flows to skip the ARP responder if inport\n-        is of type <code>localnet</code> advances directly to the next table.\n-        ARP requests sent to <code>localnet</code> ports can be received by\n-        multiple hypervisors.  Now, because the same mac binding rules are\n-        downloaded to all hypervisors, each of the multiple hypervisors will\n-        respond.  This will confuse L2 learning on the source of the ARP\n-        requests.  ARP requests received on an inport of type\n-        <code>router</code> are not expected to hit any logical switch ARP\n-        responder flows.  However, no skip flows are installed for these\n-        packets, as there would be some additional flow cost for this and the\n-        value appears limited.\n-      </li>\n-\n-      <li>\n-        <p>\n-          If inport <code>V</code> is of type <code>virtual</code> adds a\n-          priority-100 logical flows for each <var>P</var> configured in the\n-          <ref table=\"Logical_Switch_Port\" column=\"options:virtual-parents\"/>\n-          column with the match\n-        </p>\n-        <pre>\n-<code>inport == <var>P</var> &amp;&amp; &amp;&amp; ((arp.op == 1 &amp;&amp; arp.spa == <var>VIP</var> &amp;&amp; arp.tpa == <var>VIP</var>) || (arp.op == 2 &amp;&amp; arp.spa == <var>VIP</var>))</code>\n-<code>inport == <var>P</var> &amp;&amp; &amp;&amp; ((nd_ns &amp;&amp; ip6.dst == <var>{VIP, NS_MULTICAST_ADDR}</var> &amp;&amp; nd.target == <var>VIP</var>) || (nd_na &amp;&amp; nd.target == <var>VIP</var>))</code>\n-        </pre>\n-\n-        <p>\n-          and applies the action\n-        </p>\n-        <pre>\n-<code>bind_vport(<var>V</var>, inport);</code>\n-        </pre>\n-\n-        <p>\n-         and advances the packet to the next table.\n-        </p>\n-\n-        <p>\n-          Where <var>VIP</var> is the virtual ip configured in the column\n-          <ref table=\"Logical_Switch_Port\" column=\"options:virtual-ip\"/> and\n-          NS_MULTICAST_ADDR is solicited-node multicast address corresponding\n-          to the VIP.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-50 flows that match only broadcast ARP requests to each\n-          known IPv4 address <var>A</var> of every logical switch port, and\n-          respond with ARP replies directly with corresponding Ethernet\n-          address <var>E</var>:\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-arp.op = 2; /* ARP reply. */\n-arp.tha = arp.sha;\n-arp.sha = <var>E</var>;\n-arp.tpa = arp.spa;\n-arp.spa = <var>A</var>;\n-outport = inport;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          These flows are omitted for logical ports (other than router ports or\n-          <code>localport</code> ports) that are down (unless <code>\n-          ignore_lsp_down</code> is configured as true in <code>options</code>\n-          column of <code>NB_Global</code> table of the <code>Northbound</code>\n-          database), for logical ports of type <code>virtual</code>, for\n-          logical ports with 'unknown' address set, for logical ports with\n-          the <code>options:disable_arp_nd_rsp=true</code> and for logical\n-          ports of a logical switch configured with\n-          <code>other_config:vlan-passthru=true</code>.\n-        </p>\n-\n-      <p>\n-        The above ARP responder flows are added for the list of IPv4 addresses\n-        if defined in <code>options:arp_proxy</code> column of\n-        <code>Logical_Switch_Port</code> table for logical switch ports of\n-        type <code>router</code>.\n-      </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-50 flows that match IPv6 ND neighbor solicitations to\n-          each known IP address <var>A</var> (and <var>A</var>'s\n-          solicited node address) of every logical switch port except of type\n-          router, and respond with neighbor advertisements directly with\n-          corresponding Ethernet address <var>E</var>:\n-        </p>\n-\n-        <pre>\n-nd_na {\n-    eth.src = <var>E</var>;\n-    ip6.src = <var>A</var>;\n-    nd.target = <var>A</var>;\n-    nd.tll = <var>E</var>;\n-    outport = inport;\n-    flags.loopback = 1;\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          Priority-50 flows that match IPv6 ND neighbor solicitations to\n-          each known IP address <var>A</var> (and <var>A</var>'s\n-          solicited node address) of logical switch port of type router, and\n-          respond with neighbor advertisements directly with\n-          corresponding Ethernet address <var>E</var>:\n-        </p>\n-\n-        <pre>\n-nd_na_router {\n-    eth.src = <var>E</var>;\n-    ip6.src = <var>A</var>;\n-    nd.target = <var>A</var>;\n-    nd.tll = <var>E</var>;\n-    outport = inport;\n-    flags.loopback = 1;\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          These flows are omitted for logical ports (other than router ports or\n-          <code>localport</code> ports) that are down (unless <code>\n-          ignore_lsp_down</code> is configured as true in <code>options</code>\n-          column of <code>NB_Global</code> table of the <code>Northbound</code>\n-          database), for logical ports of type <code>virtual</code> and for\n-          logical ports with 'unknown' address set.\n-        </p>\n-\n-        <p>\n-          The above NDP responder flows are added for the list of\n-          IPv6 addresses if defined in <code>options:arp_proxy</code> column of\n-          <code>Logical_Switch_Port</code> table for logical switch ports of\n-          type <code>router</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-100 flows with match criteria like the ARP and ND flows\n-          above, except that they only match packets from the\n-          <code>inport</code> that owns the IP addresses in question, with\n-          action <code>next;</code>.  These flows prevent OVN from replying to,\n-          for example, an ARP request emitted by a VM for its own IP address.\n-          A VM only makes this kind of request to attempt to detect a duplicate\n-          IP address assignment, so sending a reply will prevent the VM from\n-          accepting the IP address that it owns.\n-        </p>\n-\n-        <p>\n-          In place of <code>next;</code>, it would be reasonable to use\n-          <code>drop;</code> for the flows' actions.  If everything is working\n-          as it is configured, then this would produce equivalent results,\n-          since no host should reply to the request.  But ARPing for one's own\n-          IP address is intended to detect situations where the network is not\n-          working as configured, so dropping the request would frustrate that\n-          intent.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each <var>SVC_MON_SRC_IP</var> defined in the value of\n-          the <ref column=\"ip_port_mappings:ENDPOINT_IP\"\n-          table=\"Load_Balancer\" db=\"OVN_Northbound\"/> column of\n-          <ref table=\"Load_Balancer\" db=\"OVN_Northbound\"/> table, priority-110\n-          logical flow is added with the match\n-          <code>arp.tpa == <var>SVC_MON_SRC_IP</var>\n-          &amp;&amp; &amp;&amp; arp.op == 1</code> and applies the action\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-arp.op = 2; /* ARP reply. */\n-arp.tha = arp.sha;\n-arp.sha = <var>E</var>;\n-arp.tpa = arp.spa;\n-arp.spa = <var>A</var>;\n-outport = inport;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          where <var>E</var> is the service monitor source mac defined in\n-          the <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-          db=\"OVN_Northbound\"/> column in the <ref table=\"NB_Global\"\n-          db=\"OVN_Northbound\"/> table. This mac is used as the source mac\n-          in the service monitor packets for the load balancer endpoint IP\n-          health checks.\n-        </p>\n-\n-        <p>\n-          <var>SVC_MON_SRC_IP</var> is used as the source ip in the\n-          service monitor IPv4 packets for the load balancer endpoint IP\n-          health checks.\n-        </p>\n-\n-        <p>\n-          These flows are required if an ARP request is sent for the IP\n-          <var>SVC_MON_SRC_IP</var>.\n-        </p>\n-\n-        <p>\n-          For IPv6 the similar flow is added with the following action\n-        </p>\n-\n-        <pre>\n-nd_na {\n-    eth.dst = eth.src;\n-    eth.src = <var>E</var>;\n-    ip6.src = <var>A</var>;\n-    nd.target = <var>A</var>;\n-    nd.tll = <var>E</var>;\n-    outport = inport;\n-    flags.loopback = 1;\n-    output;\n-};\n-        </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each <var>VIP</var> configured in the table\n-          <ref table=\"Forwarding_Group\" db=\"OVN_Northbound\"/>\n-          a priority-50 logical flow is added with the match\n-          <code>arp.tpa == <var>vip</var> &amp;&amp; &amp;&amp; arp.op == 1\n-          </code> and applies the action\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-arp.op = 2; /* ARP reply. */\n-arp.tha = arp.sha;\n-arp.sha = <var>E</var>;\n-arp.tpa = arp.spa;\n-arp.spa = <var>A</var>;\n-outport = inport;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          where <var>E</var> is the forwarding group's mac defined in\n-          the <ref column=\"vmac\" table=\"Forwarding_Group\"\n-          db=\"OVN_Northbound\"/>.\n-        </p>\n-\n-        <p>\n-          <var>A</var> is used as either the destination ip for load balancing\n-          traffic to child ports or as nexthop to hosts behind the child ports.\n-        </p>\n-\n-        <p>\n-          These flows are required to respond to an ARP request if an ARP\n-          request is sent for the IP <var>vip</var>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets and advances to\n-        the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 27: DHCP option processing</h3>\n-\n-    <p>\n-      This table adds the DHCPv4 options to a DHCPv4 packet from the\n-      logical ports configured with IPv4 address(es) and DHCPv4 options,\n-      and similarly for DHCPv6 options. This table also adds flows for the\n-      logical ports of type <code>external</code>.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-100 logical flow is added for these logical ports\n-          which matches the IPv4 packet with <code>udp.src</code> = 68 and\n-          <code>udp.dst</code> = 67 and applies the action\n-          <code>put_dhcp_opts</code> and advances the packet to the next table.\n-        </p>\n-\n-        <pre>\n-reg0[3] = put_dhcp_opts(offer_ip = <var>ip</var>, <var>options</var>...);\n-next;\n-        </pre>\n-\n-        <p>\n-          For DHCPDISCOVER and DHCPREQUEST, this transforms the packet into a\n-          DHCP reply, adds the DHCP offer IP <var>ip</var> and options to the\n-          packet, and stores 1 into reg0[3].  For other kinds of packets, it\n-          just stores 0 into reg0[3].  Either way, it continues to the next\n-          table.\n-        </p>\n-\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-100 logical flow is added for these logical ports\n-          which matches the IPv6 packet with <code>udp.src</code> = 546 and\n-          <code>udp.dst</code> = 547 and applies the action\n-          <code>put_dhcpv6_opts</code> and advances the packet to the next\n-          table.\n-        </p>\n-\n-        <pre>\n-reg0[3] = put_dhcpv6_opts(ia_addr = <var>ip</var>, <var>options</var>...);\n-next;\n-        </pre>\n-\n-        <p>\n-          For DHCPv6 Solicit/Request/Confirm packets, this transforms the\n-          packet into a DHCPv6 Advertise/Reply, adds the DHCPv6 offer IP\n-          <var>ip</var> and options to the packet, and stores 1 into reg0[3].\n-          For other kinds of packets, it just stores 0 into reg0[3]. Either\n-          way, it continues to the next table.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advances to table 16.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 28: DHCP responses</h3>\n-\n-    <p>\n-      This table implements DHCP responder for the DHCP replies generated by\n-      the previous table.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority 100 logical flow is added for the logical ports configured\n-          with DHCPv4 options which matches IPv4 packets with <code>udp.src == 68\n-          &amp;&amp; udp.dst == 67 &amp;&amp; reg0[3] == 1</code> and\n-          responds back to the <code>inport</code> after applying these\n-          actions.  If <code>reg0[3]</code> is set to 1, it means that the\n-          action <code>put_dhcp_opts</code> was successful.\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-ip4.src = <var>S</var>;\n-udp.src = 67;\n-udp.dst = 68;\n-outport = <var>P</var>;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          where <var>E</var> is the server MAC address and <var>S</var> is the\n-          server IPv4 address defined in the DHCPv4 options. Note that\n-          <code>ip4.dst</code> field is handled by <code>put_dhcp_opts</code>.\n-        </p>\n-\n-        <p>\n-          (This terminates ingress packet processing; the packet does not go\n-           to the next ingress table.)\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority 100 logical flow is added for the logical ports configured\n-          with DHCPv6 options which matches IPv6 packets with <code>udp.src == 546\n-          &amp;&amp; udp.dst == 547 &amp;&amp; reg0[3] == 1</code> and\n-          responds back to the <code>inport</code> after applying these\n-          actions.  If <code>reg0[3]</code> is set to 1, it means that the\n-          action <code>put_dhcpv6_opts</code> was successful.\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-ip6.dst = <var>A</var>;\n-ip6.src = <var>S</var>;\n-udp.src = 547;\n-udp.dst = 546;\n-outport = <var>P</var>;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          where <var>E</var> is the server MAC address and <var>S</var> is the\n-          server IPv6 LLA address  generated from the <code>server_id</code>\n-          defined in the DHCPv6 options and <var>A</var> is\n-          the IPv6 address defined in the logical port's addresses column.\n-        </p>\n-\n-        <p>\n-          (This terminates packet processing; the packet does not go on the\n-          next ingress table.)\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advances to table 17.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 29 DNS Lookup</h3>\n-\n-    <p>\n-      This table looks up and resolves the DNS names to the corresponding\n-      configured IP address(es).\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-100 logical flow for each logical switch datapath\n-          if it is configured with DNS records, which matches the IPv4 and IPv6\n-          packets with <code>udp.dst</code> = 53 and applies the action\n-          <code>dns_lookup</code> and advances the packet to the next table.\n-        </p>\n-\n-        <pre>\n-reg0[4] = dns_lookup(); next;\n-        </pre>\n-\n-        <p>\n-          For valid DNS packets, this transforms the packet into a DNS\n-          reply if the DNS name can be resolved, and stores 1 into reg0[4].\n-          For failed DNS resolution or other kinds of packets, it just stores\n-          0 into reg0[4]. Either way, it continues to the next table.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 30 DNS Responses</h3>\n-\n-    <p>\n-      This table implements DNS responder for the DNS replies generated by\n-      the previous table.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-100 logical flow for each logical switch datapath\n-          if it is configured with DNS records, which matches the IPv4 and IPv6\n-          packets with <code>udp.dst = 53 &amp;&amp; reg0[4] == 1</code>\n-          and responds back to the <code>inport</code> after applying these\n-          actions.  If <code>reg0[4]</code> is set to 1, it means that the\n-          action <code>dns_lookup</code> was successful.\n-        </p>\n-\n-        <pre>\n-eth.dst &lt;-&gt; eth.src;\n-ip4.src &lt;-&gt; ip4.dst;\n-udp.dst = udp.src;\n-udp.src = 53;\n-outport = <var>P</var>;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          (This terminates ingress packet processing; the packet does not go\n-           to the next ingress table.)\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress table 31 External ports</h3>\n-\n-    <p>\n-      Traffic from the <code>external</code> logical ports enter the ingress\n-      datapath pipeline via the <code>localnet</code> port. This table adds the\n-      below logical flows to handle the traffic from these ports.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-100 flow is added for each <code>external</code> logical\n-          port which doesn't reside on a chassis to drop the ARP/IPv6 NS\n-          request to the router IP(s) (of the logical switch) which matches\n-          on the <code>inport</code> of the <code>external</code> logical port\n-          and the valid <code>eth.src</code> address(es) of the\n-          <code>external</code> logical port.\n-        </p>\n-\n-        <p>\n-          This flow guarantees that the ARP/NS request to the router IP\n-          address from the external ports is responded by only the chassis\n-          which has claimed these external ports. All the other chassis,\n-          drops these packets.\n-        </p>\n-\n-        <p>\n-          A priority-100 flow is added for each <code>external</code> logical\n-          port which doesn't reside on a chassis to drop any packet destined\n-          to the router mac - with the match\n-          <code>inport == <var>external</var> &amp;&amp;\n-          eth.src == <var>E</var> &amp;&amp; eth.dst == <var>R</var>\n-          &amp;&amp; !is_chassis_resident(\"<var>external</var>\")</code>\n-          where <var>E</var> is the external port mac and <var>R</var> is the\n-          router port mac.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advances to table 20.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 32 Destination Lookup</h3>\n-\n-    <p>\n-      This table implements switching behavior.  It contains these logical\n-      flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-110 flow with the match\n-        <code>eth.src == <var>E</var></code> for all logical switch\n-        datapaths and applies the action <code>handle_svc_check(inport)</code>.\n-        Where <var>E</var> is the service monitor mac defined in the\n-        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> table.\n-      </li>\n-\n-      <li>\n-        A priority-100 flow that punts all IGMP/MLD packets to\n-        <code>ovn-controller</code> if multicast snooping is enabled on the\n-        logical switch.\n-      </li>\n-\n-      <li>\n-        A priority-100 flow that forwards all DHCP broadcast packets coming\n-        from VIFs to the logical router port's MAC when DHCP relay is enabled\n-        on the logical switch.\n-      </li>\n-\n-      <li>\n-        A priority-100 flow that matches <code>reg8[23] == 1</code> and does\n-        <code>output</code> action. This ensures that packets that got injected\n-        back into this table from egress table <code>Network Function</code>\n-        (after it set the <code>outport</code> for packet redirection) get\n-        forwarded without any further processing.\n-      </li>\n-\n-      <li>\n-        <p>\n-          For any logical port that's defined as a target of routing protocol\n-          redirecting (via <code>routing-protocol-redirect</code> option set on\n-          Logical Router Port), we redirect the traffic related to protocols\n-          specified in <code>routing-protocols</code> option. It's acoomplished\n-          with following priority-100 flows:\n-        </p>\n-        <ul>\n-          <li>\n-            Flows that match Logical Router Port's IPs and destination port of\n-            the routing daemon are redirected to this port to allow external\n-            peers' connection to the daemon listening on this port.\n-          </li>\n-          <li>\n-            Flows that match Logical Router Port's IPs and source port of\n-            the routing daemon are redirected to this port to allow replies\n-            from the peers.\n-          </li>\n-        </ul>\n-        <p>\n-          In addition to this, we add priority-100 rules that\n-          <code>clone</code> ARP replies and IPv6 Neighbor Advertisements to\n-          this port as well. These allow to build proper ARP/IPv6 neighbor\n-          list on this port.\n-        </p>\n-      </li>\n-\n-      <li>\n-        Priority-90 flows for transit switches that forward registered\n-        IP multicast traffic to their corresponding multicast group , which\n-        <code>ovn-northd</code> creates based on learnt\n-        <ref table=\"IGMP_Group\" db=\"OVN_Southbound\"/> entries.\n-      </li>\n-\n-      <li>\n-        Priority-90 flows that forward registered IP multicast traffic to\n-        their corresponding multicast group, which <code>ovn-northd</code>\n-        creates based on learnt <ref table=\"IGMP_Group\" db=\"OVN_Southbound\"/>\n-        entries.  The flows also forward packets to the\n-        <code>MC_MROUTER_FLOOD</code> multicast group, which\n-        <code>ovn-nortdh</code> populates with all the logical ports that\n-        are connected to logical routers with\n-        <ref column=\"options\" table=\"Logical_Router\"/>:mcast_relay='true'.\n-      </li>\n-\n-      <li>\n-        A priority-85 flow that forwards all IP multicast traffic destined to\n-        224.0.0.X to the <code>MC_FLOOD_L2</code> multicast group, which\n-        <code>ovn-northd</code> populates with all non-router logical ports.\n-      </li>\n-\n-      <li>\n-        A priority-85 flow that forwards all IP multicast traffic destined to\n-        reserved multicast IPv6 addresses (RFC 4291, 2.7.1, e.g.,\n-        Solicited-Node multicast) to the <code>MC_FLOOD</code> multicast\n-        group, which <code>ovn-northd</code> populates with all enabled\n-        logical ports.\n-      </li>\n-\n-      <li>\n-        A priority-80 flow that forwards all unregistered IP multicast traffic\n-        to the <code>MC_STATIC</code> multicast group, which\n-        <code>ovn-northd</code> populates with all the logical ports that\n-        have <ref column=\"options\" table=\"Logical_Switch_Port\"/>\n-        <code>:mcast_flood='true'</code>. The flow also forwards\n-        unregistered IP multicast traffic to the <code>MC_MROUTER_FLOOD</code>\n-        multicast group, which <code>ovn-northd</code> populates with all the\n-        logical ports connected to logical routers that have\n-        <ref column=\"options\" table=\"Logical_Router\"/>\n-        <code>:mcast_relay='true'</code>.\n-      </li>\n-\n-      <li>\n-        A priority-80 flow that drops all unregistered IP multicast traffic\n-        if <ref column=\"other_config\" table=\"Logical_Switch\"/>\n-        <code>:mcast_snoop='true'</code> and\n-        <ref column=\"other_config\" table=\"Logical_Switch\"/>\n-        <code>:mcast_flood_unregistered='false'</code> and the switch is\n-        not connected to a logical router that has\n-        <ref column=\"options\" table=\"Logical_Router\"/>\n-        <code>:mcast_relay='true'</code> and the switch doesn't have any\n-        logical port with <ref column=\"options\" table=\"Logical_Switch_Port\"/>\n-        <code>:mcast_flood='true'</code>.\n-      </li>\n-\n-      <li>\n-        Priority-80 flows for each IP address/VIP/NAT address owned by a\n-        router port connected to the switch. These flows match ARP requests\n-        and ND packets for the specific IP addresses.  Matched packets are\n-        forwarded only to the router that owns the IP address and to the\n-        <code>MC_FLOOD_L2</code> multicast group which contains all non-router\n-        logical ports.\n-      </li>\n-\n-      <li>\n-        Priority-75 flows for each port connected to a logical router\n-        matching self originated ARP request/RARP request/ND packets.  These\n-        packets are flooded to the <code>MC_FLOOD_L2</code> which contains all\n-        non-router logical ports.\n-      </li>\n-\n-      <li>\n-        A priority-72 flow that outputs all ND NA (Neighbor Advertisement),\n-        ND RS (Router Solicitation) and ND RA (Router Advertisement) packets\n-        with an Ethernet broadcast or multicast <code>eth.dst</code> to the\n-        <code>MC_FLOOD</code> multicast group, which includes all ports.\n-        ND NA must reach routers for neighbor learning; ND RS must reach\n-        routers so they can respond with Router Advertisements; ND RA must\n-        reach routers for proper IPv6 network operation.\n-      </li>\n-\n-      <li>\n-        A priority-72 flow that outputs all ARP requests and ND NS (Neighbor\n-        Solicitation) packets with an Ethernet broadcast or multicast\n-        <code>eth.dst</code> to the <code>MC_FLOOD_L2</code> multicast group\n-        if <code>other_config:broadcast-arps-to-all-routers=false</code>.\n-      </li>\n-\n-      <li>\n-        A priority-71 flow that outputs all ARP packets with an Ethernet\n-        broadcast or multicast <code>eth.dst</code> to the\n-        <code>MC_FLOOD</code> multicast group.\n-      </li>\n-\n-      <li>\n-        A priority-71 flow that outputs all IP packets with an Ethernet\n-        broadcast or multicast <code>eth.dst</code> to the\n-        <code>MC_FLOOD_L2</code> multicast group, which contains only\n-        non-router logical ports.  If any connected router has\n-        <code>options:mcast_relay=true</code>, the packet is also cloned to\n-        the <code>MC_MROUTER_FLOOD</code> multicast group (which contains\n-        only the router ports with relay enabled).  If any port has\n-        <code>options:mcast_flood=true</code>, it is also cloned to the\n-        <code>MC_STATIC</code> multicast group.  This prevents IP multicast\n-        from being unnecessarily forwarded to routers that would drop it.\n-      </li>\n-\n-      <li>\n-        A priority-70 flow that outputs all packets with an Ethernet broadcast\n-        or multicast <code>eth.dst</code> to the <code>MC_FLOOD_L2</code>\n-        multicast group.\n-      </li>\n-\n-      <li>\n-        <p>\n-          One priority-50 flow that matches each known Ethernet address against\n-          <code>eth.dst</code>.  Action of this flow outputs the packet to the\n-          single associated output port if it is enabled. <code>drop;</code>\n-          action is applied if LSP is disabled.  If the logical switch port\n-          of type VIF has the option <code>options:pkt_clone_type</code>\n-          is set to the value <code>mc_unknown</code>, then the packet is\n-          also forwarded to the  <code>MC_UNKNOWN</code> multicast group.\n-        </p>\n-\n-        <p>\n-          The above flow is not added if the logical switch port is of type\n-          VIF, has <code>unknown</code> as one of its address and has the\n-          option <code>options:force_fdb_lookup</code> set to true.\n-        </p>\n-\n-        <p>\n-          For the Ethernet address on a logical switch port of type\n-          <code>router</code>, when that logical switch port's\n-          <ref column=\"addresses\" table=\"Logical_Switch_Port\"\n-          db=\"OVN_Northbound\"/> column is set to <code>router</code> and\n-          the connected logical router port has a gateway chassis:\n-        </p>\n-\n-        <ul>\n-          <li>\n-            The flow for the connected logical router port's Ethernet\n-            address is only programmed on the gateway chassis.\n-          </li>\n-\n-          <li>\n-            If the logical router has rules specified in\n-            <ref column=\"nat\" table=\"Logical_Router\" db=\"OVN_Northbound\"/> with\n-            <ref column=\"external_mac\" table=\"NAT\" db=\"OVN_Northbound\"/>, then\n-            those addresses are also used to populate the switch's destination\n-            lookup on the chassis where\n-            <ref column=\"logical_port\" table=\"NAT\" db=\"OVN_Northbound\"/> is\n-            resident.\n-          </li>\n-        </ul>\n-\n-        <p>\n-          For the Ethernet address on a logical switch port of type\n-          <code>router</code>, when that logical switch port's\n-          <ref column=\"addresses\" table=\"Logical_Switch_Port\"\n-          db=\"OVN_Northbound\"/> column is set to <code>router</code> and\n-          the connected logical router port specifies a\n-          <code>reside-on-redirect-chassis</code> and the logical router\n-          to which the connected logical router port belongs to has a\n-          distributed gateway LRP:\n-        </p>\n-\n-        <ul>\n-          <li>\n-            The flow for the connected logical router port's Ethernet\n-            address is only programmed on the gateway chassis.\n-          </li>\n-        </ul>\n-\n-        <p>\n-          For each forwarding group configured on the logical switch datapath,\n-          a priority-50 flow that matches on <code>eth.dst == <var>VIP</var>\n-          </code> with an action of <code>fwd_group(childports=<var>args\n-          </var>)</code>, where <var>args</var> contains comma separated\n-          logical switch child ports to load balance to.\n-          If <code>liveness</code> is enabled, then action also includes\n-          <code> liveness=true</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that matches all packets with the\n-        action <code>outport = get_fdb(eth.dst); next;</code>. The action\n-        <code>get_fdb</code> gets the port for the <code>eth.dst</code>\n-        in the MAC learning table of the logical switch datapath. If there\n-        is no entry for <code>eth.dst</code> in the MAC learning table,\n-        then it stores <code>none</code> in the <code>outport</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 33 Destination unknown</h3>\n-\n-    <p>\n-      This table handles the packets whose destination was not found or\n-      and looked up in the MAC learning table of the logical switch\n-      datapath. It contains the following flows.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          Priority 50 flow with the match <code>outport == <var>P</var></code>\n-          is added for each disabled Logical Switch Port <code>P</code>.  This\n-          flow has action <code>drop;</code>.\n-        </p>\n-      </li>\n-      <li>\n-        <p>\n-          If the logical switch has logical ports with 'unknown' addresses set,\n-          then the below logical flow is added\n-        </p>\n-\n-        <ul>\n-          <li>\n-            Priority 50 flow with the match <code>outport == \"none\"</code> then\n-            outputs them to the <code>MC_UNKNOWN</code> multicast group, which\n-            <code>ovn-northd</code> populates with all enabled logical ports\n-            that accept unknown destination packets.  As a small optimization,\n-            if no logical ports accept unknown destination packets,\n-            <code>ovn-northd</code> omits this multicast group and logical\n-            flow.\n-          </li>\n-        </ul>\n-\n-        <p>\n-          If the logical switch has no logical ports with 'unknown' address\n-          set, then the below logical flow is added\n-        </p>\n-\n-        <ul>\n-          <li>\n-            Priority 50 flow with the match <code>outport == none</code>\n-            and drops the packets.\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-        One priority-0 fallback flow that outputs the packet to the egress\n-        stage with the outport learnt from <code>get_fdb</code> action.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 0: Lookup MAC address learning table</h3>\n-    <p>\n-      This is similar to ingress table <code>Lookup MAC address learning table\n-      </code> with the difference that MAC address learning lookup is only\n-      happening for ports with type <code>remote</code> whose port security is\n-      disabled and 'unknown' address set.  This stage facilitates MAC learning\n-      on a transit switch connecting multiple availability zones.\n-    </p>\n-\n-    <h3>Egress Table 1: Learn MAC of 'unknown' ports.</h3>\n-    <p>\n-      This is similar to ingress table <code>Learn MAC of 'unknown' ports\n-      </code> with the difference that MAC address learning is only happening\n-      for ports with type <code>remote</code> whose port security is disabled\n-      and 'unknown' address set.  This stage facilitates MAC learning on a\n-      transit switch connecting multiple availability zones.\n-    </p>\n-\n-    <h3>Egress Table 2: <code>to-lport</code> Pre-ACLs</h3>\n-\n-    <p>\n-      This is similar to ingress table <code>Pre-ACLs</code> except for\n-     <code>to-lport</code> traffic.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>eth.src == <var>E</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>E</var>\n-      is the service monitor mac defined in the\n-      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> table.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>outport == <var>I</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>I</var>\n-      is the peer of a logical router port. This flow is added to\n-      skip the connection tracking of packets which will be entering\n-      logical router datapath from logical switch datapath for routing.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow for each network_function\n-      <code>inport</code> <var>P</var> that matches <code>inport ==\n-      <var>P</var></code>. The action is to skip all the egress tables up to\n-      the <code>Network Function</code> table and advance the packet directly\n-      to the table after that. This is for the case where packet redirection\n-      happens in egress <code>Network Function</code> table. The same packet\n-      when it comes out of the other port of network function, they should not\n-      be processed again by the same egress stages, specially they should\n-      skip the conntrack processing.\n-    </p>\n-\n-    <h3>Egress Table 3: Pre-LB</h3>\n-\n-    <p>\n-      This table is similar to ingress table <code>Pre-LB</code>.  It\n-      contains a priority-0 flow that simply moves traffic to the next table.\n-      Moreover it contains two priority-110 flows to move multicast, IPv6\n-      Neighbor Discovery and MLD traffic to the next table. If any load\n-      balancing rules exist for the datapath, a priority-100 flow is added with\n-      a match of <code>ip</code> and action of <code>reg0[2] = 1; next;</code>\n-      to act as a hint for table <code>Pre-stateful</code> to send IP packets\n-      to the connection tracker for packet de-fragmentation and possibly DNAT\n-      the destination VIP to one of the selected backend for already committed\n-      load balanced traffic.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>eth.src == <var>E</var></code> for all logical switch\n-      datapaths to move traffic to the next table. Where <var>E</var>\n-      is the service monitor mac defined in the\n-      <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-      db=\"OVN_Northbound\"/> table.\n-    </p>\n-\n-    <p>\n-      This table also has a priority-110 flow with the match\n-      <code>outport == <var>I</var></code> for all logical switch\n-      datapaths to move traffic to the next table, and, if there are no\n-      stateful_acl, clear the ct_state. Where <var>I</var>\n-      is the peer of a logical router port. This flow is added to\n-      skip the connection tracking of packets which will be entering\n-      logical router datapath from logical switch datapath for routing.\n-    </p>\n-\n-    <p>\n-      When <code>enable-stateless-acl-with-lb</code> is enabled,\n-      additional priority-115 flow is added to match traffic with\n-      <code>REGBIT_ACL_STATELESS</code> set and pass connection tracking.\n-    </p>\n-\n-    <h3>Egress Table 4: Pre-stateful</h3>\n-\n-    <p>\n-      This is similar to ingress table <code>Pre-stateful</code>.  This table\n-      adds the below 3 logical flows.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A Priority-120 flow that send the packets to connection tracker using\n-        <code>ct_lb_mark;</code> as the action so that the already established\n-        traffic gets unDNATted from the backend IP to the load balancer VIP\n-        based on a hint provided by the previous tables with a match\n-        for <code>reg0[2] == 1</code>.  If the packet was not DNATted earlier,\n-        then <code>ct_lb_mark</code> functions like <code>ct_next</code>.\n-      </li>\n-\n-      <li>\n-        A priority-100 flow sends the packets to connection tracker based\n-        on a hint provided by the previous tables\n-        (with a match for <code>reg0[0] == 1</code>) by using the\n-        <code>ct_next;</code> action.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advance to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 5: <code>from-lport</code> ACL hints</h3>\n-    <p>\n-      This is similar to ingress table <code>ACL hints</code>.\n-    </p>\n-\n-    <h3>Egress Table 6: <code>to-lport</code> ACL evaluation</h3>\n-\n-    <p>\n-      This is similar to ingress table <code>ACL eval</code> except for\n-      <code>to-lport</code> ACLs. As a reminder, these flows use the\n-      following register bits to indicate their verdicts.\n-      <code>Allow-type</code> ACLs set <code>reg8[16]</code>, <code>drop</code>\n-      ACLs set <code>reg8[17]</code>, and <code>reject</code> ACLs set\n-      <code>reg8[18]</code>.\n-    </p>\n-\n-    <p>\n-      Also like with ingress ACLs, egress ACLs can have network_function_group\n-      <var>id</var> and in that case the flow will set <code>reg8[21] = 1;\n-      reg8[22] = 1; reg0[22..29] = <var>id</var></code>. These registers are used\n-      in the <code>Network Function</code> table.\n-    </p>\n-\n-    <p>\n-      Also like with ingress ACLs, egress ACLs can have a configured\n-      <code>tier</code>. If a tier is configured, then the current tier\n-      counter is evaluated against the ACL's configured tier in addition\n-      to the ACL's match. The current tier counter is stored in\n-      <code>reg8[30..31]</code>.\n-    </p>\n-\n-    <p>\n-      Similar to ingress table, a priority-65532 flow is added to allow IPv6\n-      Neighbor solicitation, Neighbor discover, Router solicitation, Router\n-      advertisement and MLD packets regardless of other ACLs defined.\n-    </p>\n-\n-    <p>\n-      In addition, the following flows are added.\n-    </p>\n-    <ul>\n-      <li>\n-        A priority 34000 logical flow is added for each logical port which\n-        has DHCPv4 options defined to allow the DHCPv4 reply packet and which has\n-        DHCPv6 options defined to allow the DHCPv6 reply packet from the\n-        <code>Ingress Table 26: DHCP responses</code>. This is indicated by\n-        setting the allow bit.\n-      </li>\n-\n-      <li>\n-        A priority 34000 logical flow is added for each logical switch datapath\n-        configured with DNS records with the match <code>udp.dst = 53</code>\n-        to allow the DNS reply packet from the\n-        <code>Ingress Table 28: DNS responses</code>. This is indicated by\n-        setting the allow bit.\n-      </li>\n-\n-      <li>\n-        A priority 34000 logical flow is added for each logical switch datapath\n-        with the match <code>eth.src = <var>E</var></code> to allow the service\n-        monitor request packet generated by <code>ovn-controller</code>\n-        with the action <code>next</code>, where <var>E</var> is the\n-        service monitor mac defined in the\n-        <ref column=\"options:svc_monitor_mac\" table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"NB_Global\"\n-        db=\"OVN_Northbound\"/> table. This is indicated by setting the allow\n-        bit.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 7: <code>to-lport</code> ACL sampling</h3>\n-    <p>\n-      This is similar to ingress table <code>ACL sampling</code>.\n-    </p>\n-\n-    <h3>Egress Table 8: <code>to-lport</code> ACL action</h3>\n-    <p>\n-      This is similar to ingress table <code>ACL action</code>.\n-    </p>\n-\n-    <h3>Egress Table 9: Mirror </h3>\n-\n-    <p>\n-      Overlay remote mirror table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For each logical switch port with an attached mirror, a logical flow\n-        with a priority of 100 is added. This flow matches all outcoming\n-        packets to the attached port, clones them, and forwards the cloned\n-        packets to the mirror target port.\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-\n-      <li>\n-        A logical flow added for each Mirror Rule in Mirror table attached\n-        to logical switch ports, matches all outcoming packets that match\n-        rules and clones the packet and sends cloned packet to mirror\n-        target port.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 10: <code>to-lport</code> QoS</h3>\n-\n-    <p>\n-      This is similar to ingress table <code>QoS</code> except\n-      they apply to <code>to-lport</code> QoS rules.\n-    </p>\n-\n-    <h3>Egress Table 11: Pre Network Function</h3>\n-\n-    <p>\n-      This stage selects the active network function from a\n-      <code>Network_Function_Group</code> based on the network function group\n-      ID set by the ACL eval stage earlier. This stage is applicable for\n-      request packets of <code>to-lport</code> ACLs\n-      (<code>reg8[22] == 1</code>). Response packets for\n-      <code>from-lport</code> ACLs bypass this stage and use\n-      <code>ct_label.nf_id</code> directly in the Network Function table.\n-    </p>\n-\n-    <p>\n-      A network function group can contain one or more network functions.\n-      Health monitoring is performed by sending datapath probes as per\n-      parameters defined in <code>Network_Function_Health_Check</code>. This\n-      stage selects one of the healthy network functions. If none are healthy,\n-      the behavior follows the <code>fallback</code> column configured in the\n-      <code>Network_Function_Group</code> table. If health monitoring is not\n-      configured, any one from the group is selected.\n-    </p>\n-\n-    <p>\n-      When a request packet matches a <code>to-lport</code> ACL with\n-      <code>network_function_group</code> set, the ACL eval stage sets\n-      <code>reg8[21] = 1</code> (NF enabled), <code>reg8[22] = 1</code>\n-      (request direction), and <code>reg0[22..29]</code> to the network\n-      function group ID. This table then selects the active network function\n-      from the group and overwrites <code>reg0[22..29]</code> with the\n-      specific <code>id</code> of a <code>Network_Function</code> table entry.\n-      The subsequent Network Function table uses this NF ID to redirect packets\n-      to the appropriate network function port. In the future, this stage will\n-      be extended to support network function load balancing.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For each network function group with <var>id</var> that has an active\n-        network function, a priority-99 flow matches <code>reg8[21] == 1\n-        &amp;&amp; reg8[22] == 1 &amp;&amp; reg0[22..29] == <var>id</var></code>\n-        and sets <code>reg0[22..29] = <var>nf_id</var>; next;</code> where\n-        <var>nf_id</var> is the <code>id</code> of the active\n-        <code>Network_Function</code> selected from the group. This prepares\n-        request packets that matched a <code>to-lport</code> ACL with\n-        network_function_group for redirection in the subsequent Network\n-        Function table.\n-      </li>\n-\n-      <li>\n-        For each network function group with <var>id</var> that has\n-        <code>fallback</code> set to <code>fail-open</code>, a priority-10 flow\n-        matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n-        reg0[22..29] == <var>id</var></code> and sets <code>reg8[21] = 0;\n-        reg0[22..29] = 0; next;</code>. This clears both the NF enabled bit and\n-        the NF group ID, allowing packets to continue processing through the\n-        pipeline without network function redirection when no active network\n-        function is available (fail-open behavior).\n-      </li>\n-\n-      <li>\n-        A priority-1 flow matches <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1\n-        </code> and sets <code>reg0[22..29] = 0; next;</code>. This is a\n-        catch-all flow for network function groups with <code>fallback</code>\n-        set to <code>fail-close</code> (or default) when no active network\n-        function is available. It clears only the NF group ID, leaving the NF\n-        enabled bit set. These packets will be dropped by the priority-1 drop\n-        rule in the subsequent Network Function table (fail-close behavior).\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that simply moves traffic to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 12: Stateful</h3>\n-\n-    <p>\n-      This is similar to ingress table <code>Stateful</code> except that\n-      there are no rules added for load balancing new connections.\n-      When <code>enable-stateless-acl-with-lb</code> is enabled, new\n-      stateless connections bypass connection tracking.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority 120 flow is added for each network function port\n-        <var>P</var> that is identical to the priority 100 flow except for\n-        additional match <code>outport == <var>P</var></code> and additional\n-        action  <code>ct_label.tun_if_id = reg5[16..31]</code>. In case packets\n-        redirected by network function logic gets tunneled from host1 to host2\n-        where the network function port resides, host2's physical table 0\n-        populates reg5[16..31] with the openflow tunnel interface id on which\n-        the packet was received. This priority 120 flow commits the tunnel id\n-        to the ct_label. That way, when the same packet comes out of the other\n-        port of the network function it can retrieve this information from the\n-        peer port's CT entry and tunnel the packet back to host1. This is\n-        required to make cross host traffic redirection work for VLAN subnet.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 13: Network Function</h3>\n-\n-    <p>\n-      This table handles request packets for <code>to-lport</code> ACLs\n-      and response packets for <code>from-lport</code> ACLs. For\n-      <code>to-lport</code> ACLs, request packets are redirected to the\n-      network function's <code>outport</code>, and corresponding\n-      response/related packets are handled in the ingress pipeline. For\n-      <code>from-lport</code> ACLs, request packets are handled in the\n-      ingress pipeline, but corresponding response/related packets for those\n-      flows are redirected here using the network function ID stored in\n-      <code>ct_label.nf_id</code> during request processing.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        Similar to ingress <code>Network Function</code> a priority-100 flow is\n-        added for each network_function port, that matches the inport with the\n-        network function port and advances the packet to the next table.\n-      </li>\n-\n-      <li>\n-        For each active network function with <var>id</var> that is\n-        referenced in a network function group, a priority-99 flow matches\n-        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 1 &amp;&amp;\n-        reg0[22..29] == <var>id</var></code> and sets\n-        <code>outport=<var>P</var>; reg8[23] = 1; next(pipeline=ingress,\n-        table=<var>T</var>)</code> where <var>P</var> is the\n-        <code>outport</code> of that network function and <var>T</var> is\n-        the ingress table <code>Destination Lookup</code>. This redirects\n-        request packets matching <code>to-lport</code> ACLs with\n-        network_function_group to the specific network function selected by\n-        the Pre Network Function stage. The packets are injected back to the\n-        ingress pipeline from where they get sent out, skipping any further\n-        lookup because of <code>reg8[23]</code>.\n-      </li>\n-\n-      <li>\n-        For each active network function with <var>id</var> that is referenced\n-        in a network function group, a priority-99 rule matches\n-        <code>reg8[21] == 1 &amp;&amp; reg8[22] == 0 &amp;&amp;\n-        ct_label.nf_id == <var>id</var></code> and takes identical action as\n-        above. This redirects response and related packets for\n-        <code>from-lport</code> ACLs to the same network function that handled\n-        the request, using the NF ID stored in the connection tracking label.\n-      </li>\n-\n-      <li>\n-        In each of the above cases, when the same packet comes out unchanged\n-        through the other port of the network_function, it would match the\n-        priority 100 flow and be forwarded to the next table.\n-      </li>\n-\n-      <li>\n-        One priority-100 multicast match flow same as\n-        ingress <code>Network Function</code>.\n-      </li>\n-\n-      <li>\n-        One priority-1 flow same as ingress <code>Network Function</code>.\n-      </li>\n-\n-      <li>\n-        One priority-0 flow same as ingress <code>Network Function</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 14: Egress Port Security - check</h3>\n-\n-    <p>\n-      This is similar to the port security logic in table\n-      <code>Ingress Port Security check</code> except that action\n-      <code>check_out_port_sec</code> is used to check the port security\n-      rules.  This table adds the below logical flows.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority 100 flow which matches on the multicast traffic and applies\n-        the action <code>REGBIT_PORT_SEC_DROP\" = 0; next;\"</code> to skip\n-        the out port security checks.\n-      </li>\n-\n-      <li>\n-        A priority 0 logical flow is added which matches on all the packets\n-        and applies the action\n-        <code>REGBIT_PORT_SEC_DROP\" = check_out_port_sec(); next;\"</code>.\n-        The action <code>check_out_port_sec</code> applies the port security\n-        rules based on the addresses defined in the\n-        <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> table before delivering the packet to the\n-        <code>outport</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 15: Egress Port Security - Apply</h3>\n-\n-    <p>\n-      This is similar to the ingress port security logic in ingress table\n-      <code>A Ingress Port Security - Apply</code>.  This table drops the\n-      packets if the port security check failed in the previous stage i.e\n-      the register bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n-    </p>\n-\n-    <p>\n-      The following flows are added.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-        For each port configured with egress qos in the\n-        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/>, running a localnet port on the same logical\n-        switch, a priority 110 flow is added which matches on the localnet\n-        <code>outport</code> and on the port <code>inport</code> and\n-        applies the action <code>set_queue(id); output;\"</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-        For each localnet port configured with egress qos in the\n-        <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n-        db=\"OVN_Northbound\"/>, a priority 100 flow is added which\n-        matches on the localnet <code>outport</code> and applies the action\n-        <code>set_queue(id); output;\"</code>.\n-        </p>\n-\n-        <p>\n-          Please remember to mark the corresponding physical interface with\n-          <code>ovn-egress-iface</code> set to true in\n-          <ref column=\"external_ids\" table=\"Interface\" db=\"Open_vSwitch\"/>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-50 flow that drops the packet if the register\n-        bit <code>REGBIT_PORT_SEC_DROP</code> is set to 1.\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that outputs the packet to the <code>outport</code>.\n-      </li>\n-    </ul>\n-\n-    <h2>Logical Router Datapaths</h2>\n-\n-    <p>\n-      Logical router datapaths will only exist for <ref table=\"Logical_Router\"\n-      db=\"OVN_Northbound\"/> rows in the <ref db=\"OVN_Northbound\"/> database\n-      that do not have <ref column=\"enabled\" table=\"Logical_Router\"\n-      db=\"OVN_Northbound\"/> set to <code>false</code>\n-    </p>\n-\n-    <h3>Ingress Table 0: L2 Admission Control</h3>\n-\n-    <p>\n-      This table drops packets that the router shouldn't see at all based on\n-      their Ethernet headers.  It contains the following flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        Priority-100 flows to drop packets with VLAN tags or multicast Ethernet\n-        source addresses.\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each enabled router port <var>P</var> with Ethernet address\n-          <var>E</var>, a priority-50 flow that matches <code>inport ==\n-          <var>P</var> &amp;&amp; (eth.mcast || eth.dst ==\n-          <var>E</var></code>), stores the router port ethernet address\n-          and advances to next table, with action\n-          <code>xreg0[0..47]=E; next;</code>.\n-        </p>\n-\n-        <p>\n-          For the gateway port on a distributed logical router (where\n-          one of the logical router ports specifies a\n-          gateway chassis), the above flow matching\n-          <code>eth.dst == <var>E</var></code> is only programmed on\n-          the gateway port instance on the gateway chassis.\n-          If LRP's logical switch has attached LSP of <code>vtep</code> type,\n-          the <code>is_chassis_resident()</code> part is not added to lflow to\n-          allow traffic originated from logical switch to reach LR services\n-          (LBs, NAT).\n-        </p>\n-\n-        <p>\n-          For each gateway port <var>GW</var> on a distributed logical router\n-          a priority-120 flow that matches 'recirculated' icmp{4,6} error\n-          'packet too big' and <code>eth.dst == <var>D</var> &amp;&amp;\n-          !is_chassis_resident(<var> cr-GW</var>)</code> where <var>D</var>\n-          is the gateway port mac address and <var>cr-GW</var> is the chassis\n-          resident port of <var>GW</var>, swap inport and outport and stores\n-          <var>GW</var> as inport.\n-        </p>\n-\n-        <p>\n-          This table adds a priority-105 flow that matches 'recirculated'\n-          icmp{4,6} error 'packet too big' to drop the packet.\n-        </p>\n-\n-        <p>\n-          For unicast L2 traffic on a distributed logical router or for\n-          gateway router where the port is configured with\n-          <code>options:gateway_mtu</code> the action of the above flow\n-          is modified adding <code>check_pkt_larger</code> in order to mark\n-          the packet setting <code>REGBIT_PKT_LARGER</code> if the size is\n-          greater than the MTU.\n-\n-          If the port is also configured with\n-          <code>options:gateway_mtu_bypass</code> then another flow is\n-          added, with priority-55, to bypass the <code>check_pkt_larger</code>\n-          flow.  This is useful for traffic that normally doesn't need to be\n-          fragmented and for which check_pkt_larger, which might not be\n-          offloadable, is not really needed.  One such example is TCP traffic.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each <code>dnat_and_snat</code> NAT rule on a distributed\n-          router that specifies an external Ethernet address <var>E</var>,\n-          a priority-50 flow that matches <code>inport == <var>GW</var>\n-          &amp;&amp; eth.dst == <var>E</var></code>, where <var>GW</var>\n-          is the logical router distributed gateway port corresponding to the\n-          NAT rule (specified or inferred), with action\n-          <code>xreg0[0..47]=E; next;</code>.\n-        </p>\n-\n-        <p>\n-          This flow is only programmed on the gateway port instance on\n-          the chassis where the <code>logical_port</code> specified in\n-          the NAT rule resides.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow that matches all packets not already handled\n-        (match <code>1</code>) and drops them (action <code>drop;</code>).\n-      </li>\n-    </ul>\n-\n-    <p>\n-      Other packets are implicitly dropped.\n-    </p>\n-\n-    <h3>Ingress Table 1: Neighbor lookup</h3>\n-\n-    <p>\n-      For ARP and IPv6 Neighbor Discovery packets, this table looks into the\n-      <ref db=\"OVN_Southbound\" table=\"MAC_Binding\"/> records to determine\n-      if OVN needs to learn the mac bindings. Following flows are added:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each router port <var>P</var> that owns IP address <var>A</var>,\n-          which belongs to subnet <var>S</var> with prefix length <var>L</var>,\n-          if the option <code>always_learn_from_arp_request</code> is\n-          <code>true</code> for this router, a priority-100 flow is added which\n-          matches <code>inport == <var>P</var> &amp;&amp; arp.spa ==\n-          <var>S</var>/<var>L</var> &amp;&amp; arp.op == 1</code> (ARP request)\n-          with the following actions:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n-next;\n-        </pre>\n-\n-        <p>\n-          If the option <code>always_learn_from_arp_request</code> is\n-          <code>false</code>, the following two flows are added.\n-        </p>\n-\n-        <p>\n-          A priority-110 flow is added which matches <code>inport ==\n-          <var>P</var> &amp;&amp; arp.spa == <var>S</var>/<var>L</var>\n-          &amp;&amp; arp.tpa == <var>A</var> &amp;&amp; arp.op == 1</code>\n-          (ARP request) with the following actions:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n-reg9[3] = 1;\n-next;\n-        </pre>\n-\n-        <p>\n-          A priority-100 flow is added which matches <code>inport ==\n-          <var>P</var> &amp;&amp; arp.spa == <var>S</var>/<var>L</var>\n-          &amp;&amp; arp.op == 1</code> (ARP request) with the following\n-          actions:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n-reg9[3] = lookup_arp_ip(inport, arp.spa);\n-next;\n-        </pre>\n-\n-        <p>\n-          If the logical router port <var>P</var> is a distributed gateway\n-          router port, additional match\n-          <code>is_chassis_resident(cr-<var>P</var>)</code> is added for all\n-          these flows.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-100 flow which matches on ARP reply packets and applies\n-          the actions if the option <code>always_learn_from_arp_request</code>\n-          is <code>true</code>:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n-next;\n-        </pre>\n-\n-        <p>\n-          If the option <code>always_learn_from_arp_request</code>\n-          is <code>false</code>, the above actions will be:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n-reg9[3] = 1;\n-next;\n-        </pre>\n-\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-100 flow which matches on IPv6 Neighbor Discovery\n-          advertisement packet and applies the actions if the option\n-          <code>always_learn_from_arp_request</code> is <code>true</code>:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n-next;\n-        </pre>\n-\n-        <p>\n-          If the option <code>always_learn_from_arp_request</code>\n-          is <code>false</code>, the above actions will be:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n-reg9[3] = 1;\n-next;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-100 flow which matches on IPv6 Neighbor Discovery\n-          solicitation packet and applies the actions if the option\n-          <code>always_learn_from_arp_request</code> is <code>true</code>:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n-next;\n-        </pre>\n-\n-        <p>\n-          If the option <code>always_learn_from_arp_request</code>\n-          is <code>false</code>, the above actions will be:\n-        </p>\n-\n-        <pre>\n-reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n-reg9[3] = lookup_nd_ip(inport, ip6.src);\n-next;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        A priority-0 fallback flow that matches all packets and applies\n-        the action <code>reg9[2] = 1; next;</code>\n-        advancing the packet to the next table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 2: Neighbor learning</h3>\n-\n-    <p>\n-      This table adds flows to learn the mac bindings from the ARP and\n-      IPv6 Neighbor Solicitation/Advertisement packets if it is needed\n-      according to the lookup results from the previous stage.\n-    </p>\n-\n-    <p>\n-      reg9[2] will be <code>1</code> if the <code>lookup_arp/lookup_nd</code>\n-      in the previous table was successful or skipped, meaning no need\n-      to learn mac binding from the packet.\n-    </p>\n-\n-    <p>\n-      reg9[3] will be <code>1</code> if the\n-      <code>lookup_arp_ip/lookup_nd_ip</code> in the previous table was\n-      successful or skipped, meaning it is ok to learn mac binding from\n-      the packet (if reg9[2] is 0).\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-100 flow with the match <code>reg9[2] == 1 || reg9[3] ==\n-        0</code> and advances the packet to the next table as there is no need\n-        to learn the neighbor.\n-      </li>\n-\n-      <li>\n-        A priority-95 flow with the match <code>nd_ns &amp;&amp;\n-          (ip6.src == 0 || nd.sll == 0)</code> and applies the action\n-        <code>next;</code>\n-      </li>\n-\n-      <li>\n-        A priority-90 flow with the match <code>arp</code> and\n-        applies the action\n-        <code>put_arp(inport, arp.spa, arp.sha); next;</code>\n-      </li>\n-\n-      <li>\n-        A priority-95 flow with the match <code>nd_na  &amp;&amp;\n-        nd.tll == 0</code> and applies the action\n-        <code>put_nd(inport, nd.target, eth.src); next;</code>\n-      </li>\n-\n-      <li>\n-        A priority-90 flow with the match <code>nd_na</code> and\n-        applies the action\n-        <code>put_nd(inport, nd.target, nd.tll); next;</code>\n-      </li>\n-\n-      <li>\n-        A priority-90 flow with the match <code>nd_ns</code> and\n-        applies the action\n-        <code>put_nd(inport, ip6.src, nd.sll); next;</code>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow that matches all packets not already handled\n-        (match <code>1</code>) and drops them (action <code>drop;</code>).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 3: IP Input</h3>\n-\n-    <p>\n-      This table is the core of the logical router datapath functionality.  It\n-      contains the following flows to implement very basic IP host\n-      functionality.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each <code>dnat_and_snat</code> NAT rule on a distributed\n-          logical routers or gateway routers with gateway port\n-          configured with <code>options:gateway_mtu</code> to a valid integer\n-          value <var>M</var>, a priority-160 flow with the match\n-          <code>inport == <var>LRP</var> &amp;&amp; REGBIT_PKT_LARGER\n-          &amp;&amp; REGBIT_EGRESS_LOOPBACK == 0</code>, where <var>LRP</var>\n-          is the logical router port and applies the following action for ipv4\n-          and ipv6 respectively:\n-        </p>\n-\n-    <pre>\n-icmp4_error {\n-    icmp4.type = 3; /* Destination Unreachable. */\n-    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n-    icmp4.frag_mtu = <var>M</var>;\n-    eth.dst = eth.src;\n-    eth.src = <var>E</var>;\n-    ip4.dst = ip4.src;\n-    ip4.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER 0;\n-    outport = <var>LRP</var>;\n-    flags.loopback = 1;\n-    output;\n-};\n-\n-icmp6_error {\n-    icmp6.type = 2;\n-    icmp6.code = 0;\n-    icmp6.frag_mtu = <var>M</var>;\n-    eth.dst = eth.src;\n-    eth.src = <var>E</var>;\n-    ip6.dst = ip6.src;\n-    ip6.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER 0;\n-    outport = <var>LRP</var>;\n-    flags.loopback = 1;\n-    output;\n-};\n-    </pre>\n-        <p>\n-          where <var>E</var> and <var>I</var> are the NAT rule external mac\n-          and IP respectively.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For distributed logical routers or gateway routers with gateway port\n-          configured with <code>options:gateway_mtu</code> to a valid integer\n-          value, a priority-150 flow with the match <code>inport ==\n-          <var>LRP</var> &amp;&amp; REGBIT_PKT_LARGER &amp;&amp;\n-          REGBIT_EGRESS_LOOPBACK == 0</code>, where <var>LRP</var> is the\n-          logical router port and applies the following action for ipv4\n-          and ipv6 respectively:\n-        </p>\n-\n-    <pre>\n-icmp4_error {\n-    icmp4.type = 3; /* Destination Unreachable. */\n-    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n-    icmp4.frag_mtu = <var>M</var>;\n-    eth.dst = <var>E</var>;\n-    ip4.dst = ip4.src;\n-    ip4.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER 0;\n-    next(pipeline=ingress, table=0);\n-};\n-\n-icmp6_error {\n-    icmp6.type = 2;\n-    icmp6.code = 0;\n-    icmp6.frag_mtu = <var>M</var>;\n-    eth.dst = <var>E</var>;\n-    ip6.dst = ip6.src;\n-    ip6.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER 0;\n-    next(pipeline=ingress, table=0);\n-};\n-    </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each NAT entry of a distributed logical router  (with\n-          distributed gateway router port(s)) of type <code>snat</code>,\n-          a priority-120 flow with the match <code>inport == <var>P</var>\n-          &amp;&amp; ip4.src == <var>A</var></code> advances the packet to\n-          the next pipeline, where <var>P</var> is the distributed logical\n-          router port corresponding to the NAT entry (specified or inferred)\n-          and <var>A</var> is the <code>external_ip</code> set\n-          in the NAT entry. If <var>A</var> is an IPv6 address, then\n-          <code>ip6.src</code> is used for the match.\n-        </p>\n-\n-        <p>\n-          The above flow is required to handle the routing of the East/west NAT\n-          traffic.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-            For each BFD port the two following priority-110 flows are added\n-            to manage BFD traffic:\n-\n-            <ul>\n-              <li>\n-               if <code>ip4.src</code> or <code>ip6.src</code> is any IP\n-               address owned by the router port and <code>udp.dst == 3784\n-               </code>, the packet is advanced to the next pipeline stage.\n-              </li>\n-\n-              <li>\n-               if <code>ip4.dst</code> or <code>ip6.dst</code> is any IP\n-               address owned by the router port and <code>udp.dst == 3784\n-               </code>, the <code>handle_bfd_msg</code> action is executed.\n-              </li>\n-            </ul>\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-            For each logical router port configured with DHCP relay the\n-            following priority-110 flows are added to manage the DHCP relay\n-            traffic:\n-\n-            <ul>\n-              <li>\n-                <p>\n-                  if <code>inport</code> is lrp and <code>ip4.src == 0.0.0.0\n-                  </code> and <code>ip4.dst == 255.255.255.255</code> and\n-                  <code>ip4.frag == 0 </code> and <code>udp.src == 68</code>\n-                  and <code>udp.dst == 67</code>, the <code>dhcp_relay_req_chk\n-                  </code> action is executed.\n-                </p>\n-\n-              <pre>\n-                reg9[7] = dhcp_relay_req_chk(<var>lrp_ip</var>,\n-                                            <var>dhcp_server_ip</var>);next\n-              </pre>\n-\n-              <p>\n-                if action is successful then, GIADDR in the dhcp header is\n-                updated with lrp ip and stores 1 into reg9[7] else stores 0\n-                into reg9[7].\n-              </p>\n-              </li>\n-\n-              <li>\n-               if <code>ip4.src</code> is DHCP server ip and <code>ip4.dst\n-               </code> is lrp IP and <code>udp.src == 67</code> and\n-               <code>udp.dst == 67</code>, the packet is advanced to the next\n-               pipeline stage.\n-              </li>\n-            </ul>\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          L3 admission control: Priority-120 flows allows IGMP and MLD packets\n-          if the router has logical ports that have\n-          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n-          <code>:mcast_flood='true'</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          L3 admission control: A priority-100 flow drops packets that match\n-          any of the following:\n-        </p>\n-\n-        <ul>\n-          <li>\n-            <code>ip4.src[28..31] == 0xe</code> (multicast source)\n-          </li>\n-          <li>\n-            <code>ip4.src == 255.255.255.255</code> (broadcast source)\n-          </li>\n-          <li>\n-            <code>ip4.src == 127.0.0.0/8 || ip4.dst == 127.0.0.0/8</code>\n-            (localhost source or destination)\n-          </li>\n-          <li>\n-            <code>ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8</code> (zero\n-            network source or destination)\n-          </li>\n-          <li>\n-            <code>ip4.src</code> or <code>ip6.src</code> is any IP\n-            address owned by the router, unless the packet was recirculated\n-            due to egress loopback as indicated by\n-            <code>REGBIT_EGRESS_LOOPBACK</code>.\n-          </li>\n-          <li>\n-            <code>ip4.src</code> is the broadcast address of any IP network\n-            known to the router.\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-          A priority-100 flow parses DHCPv6 replies from IPv6 prefix\n-          delegation routers (<code>udp.src == 547 &amp;&amp;\n-          udp.dst == 546</code>). The <code>handle_dhcpv6_reply</code>\n-          is used to send IPv6 prefix delegation messages to the delegation\n-          router.\n-      </li>\n-\n-      <li>\n-          For each load balancer applied to this logical router configured\n-          with <code>VIP</code> template, a priority-100 flow matching\n-          <code>ip4.dst</code> or <code>ip6.dst</code> with the configured\n-          load balancer <code>VIP</code> and action <code>next;</code>.\n-          These flows avoid dropping the packet if the <code>VIP</code> is\n-          set to one of the router IPs.\n-      </li>\n-\n-      <li>\n-        <p>\n-          ICMP echo reply.  These flows reply to ICMP echo requests received\n-          for the router's IP address.  Let <var>A</var> be an IP address\n-          owned by a router port.  Then, for each <var>A</var> that is\n-          an IPv4 address, a priority-90 flow matches on\n-          <code>ip4.dst == <var>A</var></code> and\n-          <code>icmp4.type == 8 &amp;&amp; icmp4.code == 0</code>\n-          (ICMP echo request).  For each <var>A</var> that is an IPv6\n-          address, a priority-90 flow matches on\n-          <code>ip6.dst == <var>A</var></code> and\n-          <code>icmp6.type == 128 &amp;&amp; icmp6.code == 0</code>\n-          (ICMPv6 echo request).  The port of the router that receives the\n-          echo request does not matter. Also, the <code>ip.ttl</code> of\n-          the echo request packet is not checked, so it complies with\n-          RFC 1812, section 4.2.2.9. Flows for ICMPv4 echo requests use the\n-          following actions:\n-        </p>\n-\n-        <pre>\n-ip4.dst &lt;-&gt; ip4.src;\n-ip.ttl = 255;\n-icmp4.type = 0;\n-flags.loopback = 1;\n-next;\n-        </pre>\n-\n-        <p>\n-          Flows for ICMPv6 echo requests use the following actions:\n-        </p>\n-\n-        <pre>\n-ip6.dst &lt;-&gt; ip6.src;\n-ip.ttl = 255;\n-icmp6.type = 129;\n-flags.loopback = 1;\n-next;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Reply to ARP requests.\n-        </p>\n-\n-        <p>\n-          These flows reply to ARP requests for the router's own IP address.\n-          The ARP requests are handled only if the requestor's IP belongs\n-          to the same subnets of the logical router port.\n-          For each router port <var>P</var> that owns IP address <var>A</var>,\n-          which belongs to subnet <var>S</var> with prefix length <var>L</var>,\n-          and Ethernet address <var>E</var>, a priority-90 flow matches\n-          <code>inport == <var>P</var> &amp;&amp;\n-          arp.spa == <var>S</var>/<var>L</var> &amp;&amp; arp.op == 1\n-          &amp;&amp; arp.tpa == <var>A</var></code> (ARP request) with the\n-          following actions:\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = xreg0[0..47];\n-arp.op = 2; /* ARP reply. */\n-arp.tha = arp.sha;\n-arp.sha = xreg0[0..47];\n-arp.tpa = arp.spa;\n-arp.spa = <var>A</var>;\n-outport = inport;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          For the gateway port on a distributed logical router (where\n-          one of the logical router ports specifies a\n-          gateway chassis), the above flows are only\n-          programmed on the gateway port instance on the\n-          gateway chassis.  This behavior avoids generation\n-          of multiple ARP responses from different chassis, and allows\n-          upstream MAC learning to point to the gateway chassis.\n-        </p>\n-\n-        <p>\n-          For the logical router port with the option\n-          <code>reside-on-redirect-chassis</code> set (which is centralized),\n-          the above flows are only programmed on the gateway port instance on\n-          the gateway chassis (if the logical router has a\n-          distributed gateway port). This behavior avoids generation\n-          of multiple ARP responses from different chassis, and allows\n-          upstream MAC learning to point to the gateway chassis.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Reply to IPv6 Neighbor Solicitations.  These flows reply to\n-          Neighbor Solicitation requests for the router's own IPv6\n-          address and populate the logical router's mac binding table.\n-        </p>\n-\n-        <p>\n-          For each router port <var>P</var> that\n-          owns IPv6 address <var>A</var>, solicited node address <var>S</var>,\n-          and Ethernet address <var>E</var>, a priority-90 flow matches\n-          <code>inport == <var>P</var> &amp;&amp;\n-          nd_ns &amp;&amp; ip6.dst == {<var>A</var>, <var>E</var>} &amp;&amp;\n-          nd.target == <var>A</var></code> with the following actions:\n-        </p>\n-\n-        <pre>\n-nd_na_router {\n-    eth.src = xreg0[0..47];\n-    ip6.src = <var>A</var>;\n-    nd.target = <var>A</var>;\n-    nd.tll = xreg0[0..47];\n-    outport = inport;\n-    flags.loopback = 1;\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          For the gateway port on a distributed logical router (where\n-          one of the logical router ports specifies a\n-          gateway chassis), the above flows replying to\n-          IPv6 Neighbor Solicitations are only programmed on the\n-          gateway port instance on the gateway chassis.\n-          This behavior avoids generation of multiple replies from\n-          different chassis, and allows upstream MAC learning to point\n-          to the gateway chassis.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          These flows reply to ARP requests or IPv6 neighbor solicitation\n-          for the virtual IP addresses configured in the router for NAT\n-          (both DNAT and SNAT) or load balancing.\n-        </p>\n-\n-        <p>\n-          IPv4: For a configured NAT (both DNAT and SNAT) IP address or a\n-          load balancer IPv4 VIP <var>A</var>, for each router port\n-          <var>P</var> with Ethernet address <var>E</var>, a priority-90 flow\n-          matches <code>arp.op == 1 &amp;&amp; arp.tpa == <var>A</var></code>\n-          (ARP request) with the following actions:\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = xreg0[0..47];\n-arp.op = 2; /* ARP reply. */\n-arp.tha = arp.sha;\n-arp.sha = xreg0[0..47];\n-arp.tpa &lt;-&gt; arp.spa;\n-outport = inport;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          IPv4: For a configured load balancer IPv4 VIP, a similar flow is\n-          added with the additional match <code>inport == <var>P</var></code>\n-          if the VIP is reachable from any logical router port of the logical\n-          router.\n-        </p>\n-\n-        <p>\n-          If the router port <var>P</var> is a distributed gateway router\n-          port, then the <code>is_chassis_resident(<var>P</var>)</code> is\n-          also added in the match condition for the load balancer IPv4\n-          VIP <var>A</var>.\n-        </p>\n-\n-        <p>\n-          IPv6: For a configured NAT (both DNAT and SNAT) IP address or a\n-          load balancer IPv6 VIP <var>A</var> (if the VIP is reachable from any\n-          logical router port of the logical router), solicited node address\n-          <var>S</var>, for each router port <var>P</var> with\n-          Ethernet address <var>E</var>, a priority-90 flow matches\n-          <code>inport == <var>P</var> &amp;&amp; nd_ns &amp;&amp;\n-          ip6.dst == {<var>A</var>, <var>S</var>} &amp;&amp;\n-          nd.target == <var>A</var></code>\n-          with the following actions:\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-nd_na {\n-    eth.src = xreg0[0..47];\n-    nd.tll = xreg0[0..47];\n-    ip6.src = <var>A</var>;\n-    nd.target = <var>A</var>;\n-    outport = inport;\n-    flags.loopback = 1;\n-    output;\n-}\n-        </pre>\n-\n-        <p>\n-          If the router port <var>P</var> is a distributed gateway router\n-          port, then the <code>is_chassis_resident(<var>P</var>)</code>\n-          is also added in the match condition for the load balancer IPv6\n-          VIP <var>A</var>.\n-        </p>\n-\n-        <p>\n-          For the gateway port on a distributed logical router with NAT\n-          (where one of the logical router ports specifies a\n-          gateway chassis):\n-        </p>\n-\n-        <ul>\n-          <li>\n-            If the corresponding NAT rule cannot be handled in a\n-            distributed manner, then a priority-92 flow is programmed on\n-            the gateway port instance on the\n-            gateway chassis.  A priority-91 drop flow is\n-            programmed on the other chassis when ARP requests/NS packets\n-            are received on the gateway port. This behavior avoids\n-            generation of multiple ARP responses from different chassis,\n-            and allows upstream MAC learning to point to the\n-            gateway chassis.\n-          </li>\n-\n-          <li>\n-            <p>\n-              If the corresponding NAT rule can be handled in a distributed\n-              manner, then this flow is only programmed on the gateway port\n-              instance where the <code>logical_port</code> specified in the\n-              NAT rule resides.\n-            </p>\n-\n-            <p>\n-              Some of the actions are different for this case, using the\n-              <code>external_mac</code> specified in the NAT rule rather\n-              than the gateway port's Ethernet address <var>E</var>:\n-            </p>\n-\n-            <pre>\n-eth.src = <var>external_mac</var>;\n-arp.sha = <var>external_mac</var>;\n-            </pre>\n-\n-            <p>\n-              or in the case of IPv6 neighbor solicition:\n-            </p>\n-\n-            <pre>\n-eth.src = <var>external_mac</var>;\n-nd.tll = <var>external_mac</var>;\n-            </pre>\n-\n-            <p>\n-              This behavior avoids generation of multiple ARP responses\n-              from different chassis, and allows upstream MAC learning to\n-              point to the correct chassis.\n-            </p>\n-          </li>\n-        </ul>\n-      </li>\n-\n-      <li>\n-        Priority-85 flows which drops the ARP and IPv6 Neighbor Discovery\n-        packets.\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-84 flow explicitly allows IPv6 multicast traffic that is\n-          supposed to reach the router pipeline (i.e., router solicitation\n-          and router advertisement packets).\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-83 flow explicitly drops IPv6 multicast traffic that is\n-          destined to reserved multicast groups.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-82 flow allows IP multicast traffic if\n-          <ref column=\"options\" table=\"Logical_Router\"/>:mcast_relay='true',\n-          otherwise drops it.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          UDP port unreachable.  Priority-80 flows generate ICMP port\n-          unreachable messages in reply to UDP datagrams directed to the\n-          router's IP address, except in the special case of gateways,\n-          which accept traffic directed to a router IP for load balancing\n-          and NAT purposes.\n-        </p>\n-\n-        <p>\n-          These flows should not match IP fragments with nonzero offset.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          TCP reset.  Priority-80 flows generate TCP reset messages in reply\n-          to TCP datagrams directed to the router's IP address, except in\n-          the special case of gateways, which accept traffic directed to a\n-          router IP for load balancing and NAT purposes.\n-        </p>\n-\n-        <p>\n-          These flows should not match IP fragments with nonzero offset.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Protocol or address unreachable. Priority-70 flows generate ICMP\n-          protocol or address unreachable messages for IPv4 and IPv6\n-          respectively in reply to packets directed to the router's IP\n-          address on IP protocols other than UDP, TCP, and ICMP, except in the\n-          special case of gateways, which accept traffic directed to a router\n-          IP for load balancing purposes.\n-        </p>\n-\n-        <p>\n-          These flows should not match IP fragments with nonzero offset.\n-        </p>\n-      </li>\n-\n-      <li>\n-        Drop other IP traffic to this router.  These flows drop any other\n-        traffic destined to an IP address of this router that is not already\n-        handled by one of the flows above, which amounts to ICMP (other than\n-        echo requests) and fragments with nonzero offsets.  For each IP address\n-        <var>A</var> owned by the router, a priority-60 flow matches\n-        <code>ip4.dst == <var>A</var></code> or\n-        <code>ip6.dst == <var>A</var></code>\n-        and drops the traffic.  An exception is made and the above flow\n-        is not added if the router port's own IP address is used to SNAT\n-        packets passing through that router or if it is used as a\n-        load balancer VIP.\n-      </li>\n-    </ul>\n-\n-    <p>\n-      The flows above handle all of the traffic that might be directed to the\n-      router itself.  The following flows (with lower priorities) handle the\n-      remaining traffic, potentially for forwarding:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        Drop Ethernet local broadcast.  A priority-50 flow with match\n-        <code>eth.bcast</code> drops traffic destined to the local Ethernet\n-        broadcast address.  By definition this traffic should not be forwarded.\n-      </li>\n-\n-      <li>\n-        Avoid ICMP time exceeded for multicast.  A priority-32 flow with match\n-        <code>ip.ttl == {0, 1} &amp;&amp; !ip.later_frag &amp;&amp;\n-        (ip4.mcast || ip6.mcast)</code> and actions <code>drop;</code> drops\n-        multicast packets whose TTL has expired without sending ICMP time\n-        exceeded.\n-      </li>\n-\n-      <li>\n-        <p>\n-          ICMP time exceeded.  For each router port <var>P</var>, whose IP\n-          address is <var>A</var>, a priority-31 flow with match <code>inport\n-          == <var>P</var> &amp;&amp; ip.ttl == {0, 1} &amp;&amp;\n-          !ip.later_frag</code> matches packets whose TTL has expired, with the\n-          following actions to send an ICMP time exceeded reply for IPv4 and\n-          IPv6 respectively:\n-        </p>\n-\n-        <pre>\n-icmp4 {\n-    icmp4.type = 11; /* Time exceeded. */\n-    icmp4.code = 0;  /* TTL exceeded in transit. */\n-    ip4.dst = ip4.src;\n-    ip4.src = <var>A</var>;\n-    ip.ttl = 254;\n-    next;\n-};\n-\n-icmp6 {\n-    icmp6.type = 3; /* Time exceeded. */\n-    icmp6.code = 0;  /* TTL exceeded in transit. */\n-    ip6.dst = ip6.src;\n-    ip6.src = <var>A</var>;\n-    ip.ttl = 254;\n-    next;\n-};\n-        </pre>\n-      </li>\n-\n-      <li>\n-        TTL discard.  A priority-30 flow with match <code>ip.ttl == {0,\n-        1}</code> and actions <code>drop;</code> drops other packets whose TTL\n-        has expired, that should not receive a ICMP error reply (i.e. fragments\n-        with nonzero offset).\n-      </li>\n-\n-      <li>\n-        Next table.  A priority-0 flows match all packets that aren't already\n-        handled and uses actions <code>next;</code> to feed them to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-\n-    <h3>Ingress Table 4: DHCP Relay Request</h3>\n-    <p>\n-      This stage process the DHCP request packets on which\n-      <code>dhcp_relay_req_chk</code> action is applied in the IP input stage.\n-    </p>\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-100 logical flow is added for each logical router port\n-          configured with DHCP relay that matches <code>inport</code> is lrp\n-          and <code>ip4.src == 0.0.0.0</code> and\n-          <code>ip4.dst == 255.255.255.255</code> and <code>udp.src == 68\n-          </code> and <code>udp.dst == 67</code> and <code>reg9[7] == 1</code>\n-          and applies following actions. If <code>reg9[7]</code> is set to 1\n-          then, <code>dhcp_relay_req_chk</code> action was successful.\n-        </p>\n-\n-        <pre>\n-ip4.src=<var>lrp ip</var>;\n-ip4.dst=<var>dhcp server ip</var>;\n-udp.src = 67;\n-next;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-1 logical flow is added for each logical router port\n-          configured with DHCP relay that matches <code>inport</code> is lrp\n-          and <code>ip4.src == 0.0.0.0</code> and\n-          <code>ip4.dst == 255.255.255.255</code> and <code>udp.src == 68\n-          </code> and <code>udp.dst == 67</code> and <code>reg9[7] == 0</code>\n-          and drops the packet. If <code>reg9[7]</code> is set to 0 then,\n-          <code>dhcp_relay_req_chk</code> action was unsuccessful.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advance to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 5: UNSNAT</h3>\n-\n-    <p>\n-      This is for already established connections' reverse traffic.\n-      i.e., SNAT has already been done in egress pipeline and now the\n-      packet has entered the ingress pipeline as part of a reply.  It is\n-      unSNATted here.\n-    </p>\n-\n-    <p>Ingress Table 5: UNSNAT on Gateway and Distributed Routers</p>\n-    <ul>\n-      <li>\n-        <p>\n-          If the Router (Gateway or Distributed) is configured with\n-          load balancers, then below lflows are added:\n-        </p>\n-\n-        <p>\n-          For each IPv4 address <var>A</var> defined as load balancer\n-          VIP with the protocol <var>P</var> (and the protocol port\n-          <var>T</var> if defined) is also present as an\n-          <code>external_ip</code> in the NAT table,\n-          a priority-120 logical flow is added with the match\n-          <code>ip4 &amp;&amp; ip4.dst == <var>A</var> &amp;&amp;\n-          <var>P</var></code> with the action <code>next;</code> to\n-          advance the packet to the next table. If the load balancer\n-          has protocol port <code>B</code> defined, then the match also has\n-          <code><var>P</var>.dst == <var>B</var></code>.\n-        </p>\n-\n-        <p>\n-          The above flows are also added for IPv6 load balancers.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <p>Ingress Table 5: UNSNAT on Gateway Routers</p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          If the Gateway router has been configured to force SNAT any\n-          previously DNATted packets to <var>B</var>, a priority-110 flow\n-          matches <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n-          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n-          with an action <code>ct_snat; </code>.\n-        </p>\n-\n-        <p>\n-          If the Gateway router is configured with\n-          <code>lb_force_snat_ip=router_ip</code> then for every logical router\n-          port <var>P</var> attached to the Gateway router with the router ip\n-          <var>B</var>, a priority-110 flow is added with the match\n-          <code>inport == <var>P</var> &amp;&amp;\n-          ip4.dst == <var>B</var></code> or <code>inport == <var>P</var>\n-          &amp;&amp; ip6.dst == <var>B</var></code> with an action\n-          <code>ct_snat; </code>.\n-        </p>\n-\n-        <p>\n-          If the Gateway router has been configured to force SNAT any\n-          previously load-balanced packets to <var>B</var>, a priority-100 flow\n-          matches <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n-          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n-          with an action <code>ct_snat; </code>.\n-        </p>\n-\n-        <p>\n-          For each NAT configuration in the OVN Northbound database, that asks\n-          to change the source IP address of a packet from <var>A</var> to\n-          <var>B</var>, a priority-90 flow matches\n-          <code>ip &amp;&amp; ip4.dst == <var>B</var></code> or\n-          <code>ip &amp;&amp; ip6.dst == <var>B</var></code>\n-          with an action <code>ct_snat; </code>. If the NAT rule is of type\n-          dnat_and_snat and has <code>stateless=true</code> in the\n-          options, then the action would be <code>next;</code>.\n-        </p>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-          <code>next;</code>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <p>Ingress Table 5: UNSNAT on Distributed Routers</p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the source IP address of a packet from <var>A</var> to\n-          <var>B</var>, two priority-100 flows are added.\n-        </p>\n-\n-        <p>\n-          If the NAT rule cannot be handled in a distributed manner, then\n-          the below priority-100 flows are only programmed on the\n-          gateway chassis.\n-        </p>\n-\n-        <ul>\n-          <li>\n-            <p>\n-              The first flow matches <code>ip &amp;&amp;\n-              ip4.dst == <var>B</var> &amp;&amp; inport == <var>GW</var>\n-              </code> or <code>ip &amp;&amp; ip6.dst == <var>B</var> &amp;&amp;\n-              inport == <var>GW</var></code>\n-              where <var>GW</var> is the distributed gateway port\n-              corresponding to the NAT rule (specified or inferred), with an\n-              action <code>ct_snat;</code> to unSNAT in the common\n-              zone.  If the NAT rule is of type dnat_and_snat and has\n-              <code>stateless=true</code> in the options, then the action\n-              would be <code>next;</code>.\n-            </p>\n-\n-            <p>\n-              If the NAT entry is of type <code>snat</code>, then there is an\n-              additional match <code>is_chassis_resident(<var>cr-GW</var>)\n-              </code> where <var>cr-GW</var> is the chassis resident port of\n-              <var>GW</var>.\n-            </p>\n-          </li>\n-        </ul>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-          <code>next;</code>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 6: POST USNAT</h3>\n-\n-    <p>\n-      This is to check whether the packet is already tracked in SNAT zone.\n-      It contains a priority-0 flow that simply moves traffic to the next\n-      table.\n-    </p>\n-\n-    <p>\n-      If the <code>options:ct-commit-all</code> is set to <code>true</code> the\n-      following two flows are configured matching on <code>ip &amp;&amp;\n-      ct.new</code> with an action <code>flags.unsnat_new = 1; next; </code>\n-      and <code>ip &amp;&amp; !ct.trk</code> with an action\n-      <code>flags.unsnat_not_tracked = 1; next;</code> Which sets one of the\n-      flags that is used in later stages. There is extra match on both when\n-      there is configured DGP\n-      <code>inport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n-    </p>\n-\n-    <h3>Ingress Table 7: DEFRAG</h3>\n-\n-    <p>\n-      This is to send packets to connection tracker for tracking and\n-      defragmentation.  It contains a priority-0 flow that simply moves traffic\n-      to the next table.\n-    </p>\n-\n-    <p>\n-      For all load balancing rules that are configured in\n-      <code>OVN_Northbound</code> database for a Gateway router,\n-      a priority-100 flow is added for each configured virtual IP address\n-      <var>VIP</var>. For IPv4 <var>VIPs</var> the flow matches\n-      <code>ip &amp;&amp; ip4.dst == <var>VIP</var></code>.  For IPv6\n-      <var>VIPs</var>, the flow matches <code>ip &amp;&amp; ip6.dst ==\n-      <var>VIP</var></code>. The flow applies the action <code> ct_dnat;</code>\n-      to send IP packets to the connection tracker for packet de-fragmentation\n-      and to dnat the destination IP for the committed connection before\n-      sending it to the next table.\n-    </p>\n-\n-    <p>\n-      If ECMP routes with symmetric reply are configured in the\n-      <code>OVN_Northbound</code> database for a gateway router, a priority-100\n-      flow is added for each router port on which symmetric replies are\n-      configured. The matching logic for these ports essentially reverses the\n-      configured logic of the ECMP route. So for instance, a route with a\n-      destination routing policy will instead match if the source IP address\n-      matches the static route's prefix. The flow uses the actions\n-      <code>chk_ecmp_nh_mac(); ct_next</code> or\n-      <code>chk_ecmp_nh(); ct_next</code> to send IP packets to table\n-      <code>76</code> or to table <code>77</code> in order to check if source\n-      info are already stored by OVN and then to the connection tracker for\n-      packet de-fragmentation and tracking before sending it to the next table.\n-    </p>\n-\n-    <p>\n-      If load balancing rules are configured in <code>OVN_Northbound</code>\n-      database for a Gateway router, a priority 50 flow that matches\n-      <code>icmp || icmp6</code> with an action of <code>ct_dnat;</code>,\n-      this allows potentially related ICMP traffic to pass through CT.\n-    </p>\n-\n-    <p>\n-      If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-      the following flow is configured matching on <code>ip &amp;&amp;\n-      (!ct.trk || !ct.rpl)</code> with an action <code>ct_next(dnat);</code>.\n-      There is extra match when the LR is configured as DGP\n-      <code>inport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n-    </p>\n-\n-   <h3>Ingress Table 8: Connection tracking field extraction</h3>\n-\n-    <p>\n-      This table extracts connection tracking fields for new connections\n-      and stores them in registers for use by subsequent load balancing\n-      stages.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For all new connections (<code>ct.new</code>), a priority-100 flow\n-          extracts the connection tracking protocol and destination port\n-          information into registers:\n-        </p>\n-\n-        <pre>\n-reg1[16..23] = ct_proto();\n-reg1[0..15] = ct_tp_dst();\n-next;\n-        </pre>\n-\n-        <p>\n-          This stores the connection tracking destination port in\n-          <code>REG_CT_TP_DST</code> (reg1[0..15]) and the protocol\n-          in <code>REG_CT_PROTO</code> (reg1[16..23]).\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets and advances to the\n-        next table with action <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 9: Load balancing affinity check</h3>\n-\n-    <p>\n-      Load balancing affinity check table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a logical router where\n-        a positive affinity timeout is specified in <code>options</code>\n-        column, that includes a L4 port <var>PORT</var> of protocol\n-        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-100\n-        flow that matches on <code>ct.new &amp;&amp; ip &amp;&amp;\n-        ip.dst == <var>VIP</var> &amp;&amp; REG_CT_PROTO == <var>P_NUM</var>\n-        &amp;&amp; REG_CT_TP_DST == <var>PORT</var></code> (<code>xxreg0 ==\n-        <var>VIP</var></code> in the IPv6 case) with an action of\n-        <code>reg0 = ip.dst; reg9[16..31] = P.dst; reg9[6] = chk_lb_aff();\n-        next;</code> (<code>xxreg0 == <var>ip6.dst</var> </code> in the IPv6\n-        case), where <var>P_NUM</var> is the protocol number (6 for TCP, 17\n-        for UDP, 132 for SCTP).\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 10: DNAT</h3>\n-\n-    <p>\n-      Packets enter the pipeline with destination IP address that needs to\n-      be DNATted from a virtual IP address to a real IP address.  Packets\n-      in the reverse direction needs to be unDNATed.\n-    </p>\n-\n-    <p>Ingress Table 8: Load balancing DNAT rules</p>\n-\n-    <p>\n-      Following load balancing DNAT flows are added for Gateway router or\n-      Router with gateway port. These flows are programmed only on the\n-      gateway chassis.  These flows do not get programmed for\n-      load balancers with IPv6 <var>VIPs</var>.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a logical router where\n-        a positive affinity timeout is specified in <code>options</code>\n-        column, that includes a L4 port <var>PORT</var> of protocol\n-        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-150\n-        flow that matches on <code>reg9[6] == 1 &amp;&amp; ct.new &amp;&amp;\n-        ip &amp;&amp; ip.dst == <var>VIP</var> &amp;&amp; REG_CT_PROTO ==\n-        <var>P_NUM</var> &amp;&amp;\n-        REG_CT_TP_DST == <var>PORT</var></code> with an action of\n-        <code>ct_lb_mark(<var>args</var>) </code>, where <var>args</var>\n-        contains comma separated IP addresses (and optional port numbers)\n-        to load balance to, and <var>P_NUM</var> is the protocol number\n-        (6 for TCP, 17 for UDP, 132 for SCTP). The address family of the IP\n-        addresses of <var>args</var> is the same as the address family of\n-        <var>VIP</var>.\n-      </li>\n-\n-      <li>\n-        If controller_event has been enabled for all the configured load\n-        balancing rules for a Gateway router or Router with gateway port\n-        in <code>OVN_Northbound</code> database that does not have configured\n-        backends, a priority-130 flow is added to trigger ovn-controller events\n-        whenever the chassis receives a packet for that particular VIP.\n-        If <code>event-elb</code> meter has been previously created, it will be\n-        associated to the empty_lb logical flow\n-      </li>\n-\n-      <li>\n-        <p>\n-          For all the configured load balancing rules for a Gateway router or\n-          Router with gateway port in <code>OVN_Northbound</code> database that\n-          includes a L4 port <var>PORT</var> of protocol <var>P</var> and IPv4\n-          or IPv6 address <var>VIP</var>, a priority-120 flow that matches on\n-          <code>ct.new &amp;&amp; !ct.rel &amp;&amp; ip &amp;&amp; ip.dst ==\n-          <var>VIP</var> &amp;&amp; REG_CT_PROTO == <var>P_NUM</var> &amp;&amp;\n-          REG_CT_TP_DST == <var>PORT</var></code> with an action of\n-          <code>ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains\n-          comma separated IPv4 or IPv6 addresses (and optional port numbers) to\n-          load balance to, and <var>P_NUM</var> is the protocol number\n-          (6 for TCP, 17 for UDP, 132 for SCTP). If the router is configured\n-          to force SNAT any\n-          load-balanced packets, the above action will be replaced by\n-          <code>flags.force_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n-          force_snat);</code>.\n-          If the load balancing rule is configured with <code>skip_snat</code>\n-          set to true, the above action will be replaced by\n-          <code>flags.skip_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n-          skip_snat);</code>.\n-          If health check is enabled, then\n-          <var>args</var> will only contain those endpoints whose service\n-          monitor status entry in <code>OVN_Southbound</code> db is\n-          either <code>online</code> or empty.\n-        </p>\n-\n-      </li>\n-\n-      <li>\n-        <p>\n-          For all the configured load balancing rules for a router in\n-          <code>OVN_Northbound</code> database that includes just an IP address\n-          <var>VIP</var> to match on, a priority-110 flow that matches on\n-          <code>ct.new &amp;&amp; !ct.rel &amp;&amp; ip4 &amp;&amp; ip.dst ==\n-          <var>VIP</var></code> with an action of\n-          <code>ct_lb_mark(<var>args</var>)</code>, where <var>args</var> contains\n-          comma separated IPv4 or IPv6 addresses.  If the router is configured\n-          to force SNAT any load-balanced packets, the above action will be\n-          replaced by <code>flags.force_snat_for_lb = 1;\n-          ct_lb_mark(<var>args</var>; force_snat);</code>.\n-          If the load balancing rule is configured with <code>skip_snat</code>\n-          set to true, the above action will be replaced by\n-          <code>flags.skip_snat_for_lb = 1; ct_lb_mark(<var>args</var>;\n-          skip_snat);</code>.\n-        </p>\n-\n-        <p>\n-          The previous table <code>lr_in_defrag</code> sets the register\n-          <code>reg0</code> (or <code>xxreg0</code> for IPv6) and does\n-          <code>ct_dnat</code>.  Hence for established traffic, this\n-          table just advances the packet to the next stage.\n-        </p>\n-      </li>\n-\n-      <li>\n-        If the load balancer is created with <code>--reject</code> option and\n-        it has no active backends, a TCP reset segment (for tcp) or an ICMP\n-        port unreachable packet (for all other kind of traffic) will be sent\n-        whenever an incoming packet is received for this load-balancer.\n-        Please note using <code>--reject</code> option will disable\n-        empty_lb SB controller event for this load balancer.\n-      </li>\n-\n-      <li>\n-        <p>\n-            For the related traffic, a priority 50 flow that matches\n-            <code>ct.rel &amp;&amp; !ct.est &amp;&amp; !ct.new </code>\n-            with an action of <code>ct_commit_nat;</code>, if the router\n-            has load balancer assigned to it. Along with two priority 70 flows\n-            that match <code>skip_snat</code> and <code>force_snat</code>\n-            flags, setting the <code>flags.force_snat_for_lb = 1</code> or\n-            <code>flags.skip_snat_for_lb = 1</code> accordingly.\n-        </p>\n-      </li>\n-      <li>\n-        <p>\n-          For the established traffic, a priority 50 flow that matches\n-          <code>ct.est &amp;&amp; !ct.rel &amp;&amp; !ct.new &amp;&amp;\n-          ct_mark.natted</code> with an action of <code>next;</code>,\n-          if the router has load balancer assigned to it. Along with two\n-          priority 70 flows that match <code>skip_snat</code> and\n-          <code>force_snat</code> flags, setting the\n-          <code>flags.force_snat_for_lb = 1</code> or\n-          <code>flags.skip_snat_for_lb = 1</code> accordingly.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <p>Ingress Table 9: DNAT on Gateway Routers</p>\n-\n-    <ul>\n-      <li>\n-        For each configuration in the OVN Northbound database, that asks\n-        to change the destination IP address of a packet from <var>A</var> to\n-        <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;\n-        ip4.dst == <var>A</var></code> or <code>ip &amp;&amp;\n-        ip6.dst == <var>A</var></code> with an action\n-        <code>flags.loopback = 1; ct_dnat(<var>B</var>);</code>.  If the\n-        Gateway router is configured to force SNAT any DNATed packet,\n-        the above action will be replaced by\n-        <code>flags.force_snat_for_dnat = 1; flags.loopback = 1;\n-        ct_dnat(<var>B</var>);</code>. If the NAT rule is of type\n-        dnat_and_snat and has <code>stateless=true</code> in the\n-        options, then the action would be <code>ip4/6.dst=\n-        (<var>B</var>)</code>.\n-\n-        <p>\n-          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n-          there is an additional match <code>ip4.src == <var>allowed_ext_ips\n-          </var></code>. Similarly, for IPV6, match would be <code>ip6.src ==\n-          <var>allowed_ext_ips</var></code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule has <code>exempted_ext_ips</code> set, then\n-          there is an additional flow configured at priority 101.\n-          The flow matches if source ip is an <code>exempted_ext_ip</code>\n-          and the action is <code>next; </code>. This flow is used to\n-          bypass the ct_dnat action for a packet originating from\n-          <code>exempted_ext_ips</code>.\n-        </p>\n-\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the destination IP address of a packet from <var>A</var>\n-          to <var>B</var>, match <var>M</var> and priority <var>P</var>,\n-          a logical flow that matches <code>ip &amp;&amp; ip4.dst ==\n-          <var>A</var></code> or <code>ip &amp;&amp; ip6.dst == <var>A</var>\n-          &amp;&amp; (<var>M</var>)</code> with an action\n-          <code>flags.loopback = 1; ct_dnat(<var>B</var>);</code>.\n-          The priority of the flow is calculated based as\n-          <code>300 + <var>P</var></code>.  If the Gateway router is\n-          configured to force SNAT any DNATed packet, the above action will\n-          be replaced by <code>flags.force_snat_for_dnat = 1;\n-          flags.loopback = 1; ct_dnat(<var>B</var>);</code>. If the NAT rule\n-          is of type dnat_and_snat and has <code>stateless=true</code> in the\n-          options, then the action would be <code>ip4/6.dst=\n-          (<var>B</var>)</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-          the following flow is configured matching on <code>ip &amp;&amp;\n-          ct.new</code> with an action <code>ct_commit_to_zone(dnat);</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <p>Ingress Table 9: DNAT on Distributed Routers</p>\n-\n-    <p>\n-      On distributed routers, the DNAT table only handles packets\n-      with destination IP address that needs to be DNATted from a\n-      virtual IP address to a real IP address.  The unDNAT processing\n-      in the reverse direction is handled in a separate table in the\n-      egress pipeline.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the destination IP address of a packet from <var>A</var> to\n-          <var>B</var>, a priority-100 flow matches <code>ip &amp;&amp;\n-          ip4.dst == <var>B</var> &amp;&amp; inport == <var>GW</var></code>,\n-          where <var>GW</var> is the logical router gateway port corresponding\n-          to the NAT rule (specified or inferred), with an action\n-          <code>ct_dnat(<var>B</var>);</code>.  The match will include\n-          <code>ip6.dst == <var>B</var></code> in the IPv6 case.\n-          If the NAT rule is of type dnat_and_snat and has\n-          <code>stateless=true</code> in the options, then the action\n-          would be <code>ip4/6.dst=(<var>B</var>)</code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule cannot be handled in a distributed manner, then\n-          the priority-100 flow above is only programmed on the\n-          gateway chassis.\n-        </p>\n-\n-        <p>\n-          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n-          there is an additional match <code>ip4.src == <var>allowed_ext_ips\n-          </var></code>. Similarly, for IPV6, match would be <code>ip6.src ==\n-          <var>allowed_ext_ips</var></code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule has <code>exempted_ext_ips</code> set, then\n-          there is an additional flow configured at priority 101.\n-          The flow matches if source ip is an <code>exempted_ext_ip</code>\n-          and the action is <code>next; </code>. This flow is used to\n-          bypass the ct_dnat action for a packet originating from\n-          <code>exempted_ext_ips</code>.\n-        </p>\n-\n-        <p>\n-          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-          the following flow is configured matching on <code>ip &amp;&amp;\n-          ct.new &amp;&amp; inport == DGP &amp;&amp;\n-          is_chassis_resident(CHASSIS)</code> with an action\n-          <code>ct_commit_to_zone(dnat);</code>.\n-        </p>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-          <code>next;</code>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 11: Load balancing affinity learn</h3>\n-\n-    <p>\n-      Load balancing affinity learn table contains the following\n-      logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules for a logical router where\n-        a positive affinity timeout <var>T</var> is specified in <code>options\n-        </code> column, that includes a L4 port <var>PORT</var> of protocol\n-        <var>P</var> and IPv4 or IPv6 address <var>VIP</var>, a priority-100\n-        flow that matches on <code>reg9[6] == 0 &amp;&amp; ct.new &amp;&amp;\n-        ip &amp;&amp; reg0 == <var>VIP</var> &amp;&amp; <var>P</var> &amp;&amp;\n-        reg9[16..31] == </code> <code><var>PORT</var></code> (<code>xxreg0 ==\n-        <var>VIP</var> </code> in the IPv6 case) with an action of\n-        <code>commit_lb_aff(vip = <var>VIP</var>:<var>PORT</var>, backend =\n-        <var>backend ip</var>: <var>backend port</var>, proto = <var>P</var>,\n-        timeout = <var>T</var>);</code>.\n-      </li>\n-\n-      <li>\n-        A priority 0 flow is added which matches on all packets and applies\n-        the action <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 12: ECMP symmetric reply processing</h3>\n-    <ul>\n-      <li>\n-        If ECMP routes with symmetric reply are configured in the\n-        <code>OVN_Northbound</code> database for a gateway router, a\n-        priority-100 flow is added for each router port on which symmetric\n-        replies are configured. The matching logic for these ports essentially\n-        reverses the configured logic of the ECMP route. So for instance, a\n-        route with a destination routing policy will instead match if the\n-        source IP address matches the static route's prefix. The flow uses\n-        the action <code>ct_commit { ct_label.ecmp_reply_eth = eth.src;\"\n-        \" ct_mark.ecmp_reply_port = <var>K</var>;}; commit_ecmp_nh(); next;\n-        </code> to commit the connection and storing <code>eth.src</code> and\n-        the ECMP reply port binding tunnel key <var>K</var> in the\n-        <code>ct_label</code> and the traffic pattern to table\n-        <code>76</code> or <code>77</code>.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 13: IPv6 ND RA option processing</h3>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-50 logical flow is added for each logical router port\n-          configured with IPv6 ND RA options which matches IPv6 ND Router\n-          Solicitation packet and applies the action\n-          <code>put_nd_ra_opts</code> and advances the packet to the next\n-          table.\n-        </p>\n-\n-        <pre>\n-reg0[5] = put_nd_ra_opts(<var>options</var>);next;\n-        </pre>\n-\n-        <p>\n-          For a valid IPv6 ND RS packet, this transforms the packet into an\n-          IPv6 ND RA reply and sets the RA options to the packet and stores 1\n-          into reg0[5]. For other kinds of packets, it just stores 0 into\n-          reg0[5]. Either way, it continues to the next table.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 14: IPv6 ND RA responder</h3>\n-\n-    <p>\n-      This table implements IPv6 ND RA responder for the IPv6 ND RA replies\n-      generated by the previous table.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-50 logical flow is added for each logical router port\n-          configured with IPv6 ND RA options which matches IPv6 ND RA\n-          packets and <code>reg0[5] == 1</code> and responds back to the\n-          <code>inport</code> after applying these actions.\n-          If <code>reg0[5]</code> is set to 1, it means that the action\n-          <code>put_nd_ra_opts</code> was successful.\n-        </p>\n-\n-        <pre>\n-eth.dst = eth.src;\n-eth.src = <var>E</var>;\n-ip6.dst = ip6.src;\n-ip6.src = <var>I</var>;\n-outport = <var>P</var>;\n-flags.loopback = 1;\n-output;\n-        </pre>\n-\n-        <p>\n-          where <var>E</var> is the MAC address and <var>I</var> is the IPv6\n-          link local address of the logical router port.\n-        </p>\n-\n-        <p>\n-          (This terminates packet processing in ingress pipeline; the packet\n-          does not go to the next ingress table.)\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 15: IP Routing Pre</h3>\n-\n-    <p>\n-      If a packet arrived at this table from Logical Router Port <var>P</var>\n-      which has <code>options:route_table</code> value set, a logical flow with\n-      match <code>inport == \"<var>P</var>\"</code> with priority 100 and action\n-      setting unique-generated per-datapath 32-bit value (non-zero) in OVS\n-      register 7.  This register's value is checked in next table.  If packet\n-      didn't match any configured inport (<var>&lt;main&gt;</var> route table),\n-      register 7 value is set to 0.\n-    </p>\n-\n-    <p>\n-      This table contains the following logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          Priority-100 flow with match <code>inport == \"LRP_NAME\"</code> value\n-          and action, which set route table identifier in reg7.\n-        </p>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-          <code>reg7 = 0; next;</code>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 16: IP Routing</h3>\n-\n-    <p>\n-      A packet that arrives at this table is an IP packet that should be\n-      routed to the address in <code>ip4.dst</code> or\n-      <code>ip6.dst</code>.  This table implements IP routing, setting\n-      <code>reg0</code> (or <code>xxreg0</code> for IPv6) to the next-hop IP\n-      address (leaving <code>ip4.dst</code> or <code>ip6.dst</code>, the\n-      packet's final destination, unchanged) and advances to the next\n-      table for ARP resolution.  It also sets <code>reg1</code> (or\n-      <code>xxreg1</code>) to the IP address owned by the selected router\n-      port (ingress table <code>ARP Request</code> will generate an ARP\n-      request, if needed, with <code>reg0</code> as the target protocol\n-      address and <code>reg1</code> as the source protocol address).\n-    </p>\n-\n-    <p>\n-      For ECMP routes, i.e. multiple static routes with same policy and\n-      prefix but different nexthops, the above actions are deferred to next\n-      table.  This table, instead, is responsible for determine the ECMP\n-      group id and select a member id within the group based on 5-tuple\n-      hashing.  It stores group id in <code>reg8[0..15]</code> and member id in\n-      <code>reg8[16..31]</code>. This step is skipped with a priority-10300\n-      rule if the traffic going out the ECMP route is reply traffic, and the\n-      ECMP route was configured to use symmetric replies. Instead, the stored\n-      values in conntrack is used to choose the destination. The\n-      <code>ct_label.ecmp_reply_eth</code> tells the destination MAC address to\n-      which the packet should be sent. The <code>ct_mark.ecmp_reply_port</code>\n-      tells the logical router port on which the packet should be sent. These\n-      values saved to the conntrack fields when the initial ingress traffic is\n-      received over the ECMP route and committed to conntrack.\n-      If <code>REGBIT_KNOWN_ECMP_NH</code> is set, the priority-10300\n-      flows in this stage set the <code>outport</code>, while the\n-      <code>eth.dst</code> is set by flows at the ARP/ND Resolution stage.\n-    </p>\n-\n-    <p>\n-      This table contains the following logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          Priority-10550 flow that drops IPv6 Router Solicitation/Advertisement\n-          packets that were not processed in previous tables.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-10550 flows that drop IGMP and MLD packets with source MAC\n-          address owned by the router.  These are used to prevent looping\n-          statically forwarded IGMP and MLD packets for which TTL is not\n-          decremented (it is always 1).\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-10500 flows that match IP multicast traffic destined to\n-          groups registered on any of the attached switches and sets\n-          <code>outport</code> to the associated multicast group that will\n-          eventually flood the traffic to all interested attached logical\n-          switches. The flows also decrement TTL.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-10460 flows that match IGMP and MLD control packets,\n-          set <code>outport</code> to the <code>MC_STATIC</code>\n-          multicast group, which <code>ovn-northd</code>\n-          populates with the logical ports that have\n-          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n-          <code>:mcast_flood='true'</code>. If no router ports are configured\n-          to flood multicast traffic the packets are dropped.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-10450 flow that matches unregistered IP multicast traffic\n-          decrements TTL and sets <code>outport</code> to the\n-          <code>MC_STATIC</code> multicast group, which <code>ovn-northd</code>\n-          populates with the logical ports that have\n-          <ref column=\"options\" table=\"Logical_Router_Port\"/>\n-          <code>:mcast_flood='true'</code>. If no router ports are configured\n-          to flood multicast traffic the packets are dropped.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          IPv4 routing table.  For each route to IPv4 network <var>N</var> with\n-          netmask <var>M</var>, on router port <var>P</var> with IP address\n-          <var>A</var> and Ethernet\n-          address <var>E</var>, a logical flow with match <code>ip4.dst ==\n-          <var>N</var>/<var>M</var></code>, whose priority is the number of\n-          1-bits in <var>M</var>, has the following actions:\n-        </p>\n-\n-        <pre>\n-ip.ttl--;\n-reg8[0..15] = 0;\n-reg0 = <var>G</var>;\n-reg1 = <var>A</var>;\n-eth.src = <var>E</var>;\n-outport = <var>P</var>;\n-flags.loopback = 1;\n-next;\n-        </pre>\n-\n-        <p>\n-          (Ingress table 1 already verified that <code>ip.ttl--;</code> will\n-          not yield a TTL exceeded error.)\n-        </p>\n-\n-        <p>\n-          If the route has a gateway, <var>G</var> is the gateway IP address.\n-          Instead, if the route is from a configured static route, <var>G</var>\n-          is the next hop IP address.  Else it is <code>ip4.dst</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          IPv6 routing table.  For each route to IPv6 network\n-          <var>N</var> with netmask <var>M</var>, on router port\n-          <var>P</var> with IP address <var>A</var> and Ethernet address\n-          <var>E</var>, a logical flow with match in CIDR notation\n-          <code>ip6.dst == <var>N</var>/<var>M</var></code>,\n-          whose priority is the integer value of <var>M</var>, has the\n-          following actions:\n-        </p>\n-\n-        <pre>\n-ip.ttl--;\n-reg8[0..15] = 0;\n-xxreg0 = <var>G</var>;\n-xxreg1 = <var>A</var>;\n-eth.src = <var>E</var>;\n-outport = inport;\n-flags.loopback = 1;\n-next;\n-        </pre>\n-\n-        <p>\n-          (Ingress table 1 already verified that <code>ip.ttl--;</code> will\n-          not yield a TTL exceeded error.)\n-        </p>\n-\n-        <p>\n-          If the route has a gateway, <var>G</var> is the gateway IP address.\n-          Instead, if the route is from a configured static route, <var>G</var>\n-          is the next hop IP address.  Else it is <code>ip6.dst</code>.\n-        </p>\n-\n-        <p>\n-          If the address <var>A</var> is in the link-local scope, the\n-          route will be limited to sending on the ingress port.\n-        </p>\n-\n-        <p>\n-          For each static route the <code>reg7 == id &amp;&amp;</code> is\n-          prefixed in logical flow match portion.  For routes with\n-          <code>route_table</code> value set a unique non-zero id is used.\n-          For routes within <code>&lt;main&gt;</code> route table (no route\n-          table set), this id value is 0.\n-        </p>\n-        <p>\n-          For each <var>connected</var> route (route to the LRP's subnet CIDR)\n-          the logical flow match portion has no\n-          <code>reg7 == id &amp;&amp;</code> prefix to have route to LRP's\n-          subnets in all routing tables.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For ECMP routes, they are grouped by policy and prefix.  An unique id\n-          (non-zero) is assigned to each group, and each member is also\n-          assigned an unique id (non-zero) within each group.\n-        </p>\n-\n-        <p>\n-          For each IPv4/IPv6 ECMP group with group id <var>GID</var> and member\n-          ids <var>MID1</var>, <var>MID2</var>, ..., a logical flow with match\n-          in CIDR notation <code>ip4.dst == <var>N</var>/<var>M</var></code>,\n-          or <code>ip6.dst == <var>N</var>/<var>M</var></code>, whose priority\n-          is the integer value of <var>M</var>, has the following actions:\n-        </p>\n-\n-        <pre>\n-ip.ttl--;\n-flags.loopback = 1;\n-reg8[0..15] = <var>GID</var>;\n-reg8[16..31] = select(<var>MID1</var>, <var>MID2</var>, ...);\n-        </pre>\n-        <p>\n-          However, when there is only one route in an ECMP group, group actions\n-          will be:\n-        </p>\n-\n-        <pre>\n-ip.ttl--;\n-flags.loopback = 1;\n-reg8[0..15] = <var>GID</var>;\n-reg8[16..31] = <var>MID1</var>);\n-        </pre>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow that matches all packets not already handled\n-        (match <code>1</code>) and drops them (action <code>drop;</code>).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 17: IP_ROUTING_ECMP</h3>\n-\n-    <p>\n-      This table implements the second part of IP routing for ECMP routes\n-      following the previous table.  If a packet matched a ECMP group in the\n-      previous table, this table matches the group id and member id stored\n-      from the previous table, setting <code>reg0</code>\n-      (or <code>xxreg0</code> for IPv6) to the next-hop IP address\n-      (leaving <code>ip4.dst</code> or <code>ip6.dst</code>, the\n-      packet's final destination, unchanged) and advances to the next\n-      table for ARP resolution.  It also sets <code>reg1</code> (or\n-      <code>xxreg1</code>) to the IP address owned by the selected router\n-      port (ingress table <code>ARP Request</code> will generate an ARP\n-      request, if needed, with <code>reg0</code> as the target protocol\n-      address and <code>reg1</code> as the source protocol address).\n-    </p>\n-\n-    <p>\n-      This processing is skipped for reply traffic being sent out of an ECMP\n-      route if the route was configured to use symmetric replies.\n-    </p>\n-\n-    <p>\n-      This table contains the following logical flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-150 flow that matches <code>reg8[0..15] == 0</code>\n-          with action <code>next;</code> directly bypasses packets of non-ECMP\n-          routes.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each member with ID <var>MID</var> in each ECMP group with ID\n-          <var>GID</var>, a priority-100 flow with match\n-          <code>reg8[0..15] == <var>GID</var> &amp;&amp; reg8[16..31] == <var>MID</var></code>\n-          has following actions:\n-        </p>\n-\n-        <pre>\n-[xx]reg0 = <var>G</var>;\n-[xx]reg1 = <var>A</var>;\n-eth.src = <var>E</var>;\n-outport = <var>P</var>;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow that matches all packets not already handled\n-        (match <code>1</code>) and drops them (action <code>drop;</code>).\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 18: Router policies</h3>\n-    <p>\n-      This table adds flows for the logical router policies configured\n-      on the logical router. Please see the\n-      <code>OVN_Northbound</code> database <code>Logical_Router_Policy</code>\n-      table documentation in <code>ovn-nb</code> for supported actions.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each router policy configured on the logical router, a\n-          logical flow is added with specified priority, match and\n-          actions.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the policy action is <code>reroute</code> with 2 or more nexthops\n-          defined, then the logical flow is added with the following actions:\n-        </p>\n-\n-         <pre>\n-reg8[0..15] = <var>GID</var>;\n-reg8[16..31] = select(1,..n);\n-        </pre>\n-\n-        <p>\n-          where <var>GID</var> is the ECMP group id generated by\n-          <code>ovn-northd</code> for this policy and <var>n</var>\n-          is the number of nexthops. <code>select</code> action\n-          selects one of the nexthop member id, stores it in the register\n-          <code>reg8[16..31]</code> and advances the packet to the\n-          next stage.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the policy action is <code>reroute</code> with just one nexhop,\n-          then the logical flow is added with the following actions:\n-        </p>\n-\n-         <pre>\n-[xx]reg0 = <var>H</var>;\n-eth.src = <var>E</var>;\n-outport = <var>P</var>;\n-reg8[0..15] = 0;\n-flags.loopback = 1;\n-next;\n-        </pre>\n-\n-        <p>\n-          where <var>H</var> is the <code>nexthop </code> defined in the\n-          router policy, <var>E</var> is the ethernet address of the\n-          logical router port from which the <code>nexthop</code> is\n-          reachable and <var>P</var> is the logical router port from\n-          which the <code>nexthop</code> is reachable.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If a router policy has the option <code>pkt_mark=<var>m</var></code>\n-          set and if the action is <code>not</code> drop, then the action also\n-          includes <code>pkt.mark = <var>m</var></code> to mark the packet\n-          with the marker <var>m</var>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 19: ECMP handling for router policies</h3>\n-    <p>\n-      This table handles the ECMP for the router policies configured\n-      with multiple nexthops.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-150 flow is added to advance the packet to the next stage\n-          if the ECMP group id register <code>reg8[0..15]</code> is 0.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each ECMP reroute router policy with multiple nexthops,\n-          a priority-100 flow is added for each nexthop <var>H</var>\n-          with the match <code>reg8[0..15] == <var>GID</var> &amp;&amp;\n-          reg8[16..31] == <var>M</var></code> where <var>GID</var>\n-          is the router policy group id generated by <code>ovn-northd</code>\n-          and <var>M</var> is the member id of the nexthop <var>H</var>\n-          generated by <code>ovn-northd</code>. The following actions are added\n-          to the flow:\n-        </p>\n-\n-        <pre>\n-[xx]reg0 = <var>H</var>;\n-eth.src = <var>E</var>;\n-outport = <var>P</var>\n-\"flags.loopback = 1; \"\n-\"next;\"\n-        </pre>\n-\n-        <p>\n-          where <var>H</var> is the <code>nexthop </code> defined in the\n-          router policy, <var>E</var> is the ethernet address of the\n-          logical router port from which the <code>nexthop</code> is\n-          reachable and <var>P</var> is the logical router port from\n-          which the <code>nexthop</code> is reachable.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow that matches all packets not already handled\n-        (match <code>1</code>) and drops them (action <code>drop;</code>).\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 20: DHCP Relay Response Check</h3>\n-    <p>\n-      This stage process the DHCP response packets coming from the DHCP server.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-         A priority 100 logical flow is added for each logical router port\n-         configured with DHCP relay that matches <code>ip4.src</code> is\n-         DHCP server ip and <code>ip4.dst</code> is lrp IP and\n-         <code>ip4.frag == 0</code> and <code>udp.src == 67</code> and\n-         <code>udp.dst == 67</code> and applies <code>dhcp_relay_resp_chk\n-         </code> action. Original destination ip is stored in reg2.\n-        </p>\n-\n-      <pre>\n-        reg9[8] = dhcp_relay_resp_chk(<var>lrp_ip</var>,\n-                                      <var>dhcp_server_ip</var>);next\n-      </pre>\n-\n-      <p>\n-        if action is successful then, dest mac and dest IP addresses are\n-        updated in the packet and stores 1 into reg9[8] else stores 0 into\n-        reg9[8].\n-      </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advance to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 21: DHCP Relay Response</h3>\n-    <p>\n-      This stage process the DHCP response packets on which\n-      <code>dhcp_relay_resp_chk</code> action is applied in the previous stage.\n-    </p>\n-    <ul>\n-      <li>\n-        <p>\n-          A priority 100 logical flow is added for each logical router port\n-          configured with DHCP relay that matches <code>ip4.src</code> is\n-          DHCP server ip and <code>reg2</code> is lrp IP and\n-          <code>udp.src == 67</code> and <code>udp.dst == 67</code>\n-          and <code>reg9[8] == 1</code> and applies following actions. If\n-          <code>reg9[8]</code> is set to 1 then,\n-          <code>dhcp_relay_resp_chk</code> was successful.\n-        </p>\n-\n-        <pre>\n-ip4.src = <var>lrp ip</var>;\n-udp.dst = 68;\n-outport = <var>lrp port</var>;\n-output;\n-        </pre>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority 1 logical flow is added for the logical router port\n-          on which DHCP relay is enabled that matches <code>ip4.src</code>\n-          is DHCP server ip and <code>reg2</code> is lrp IP and\n-          <code>udp.src == 67</code> and <code>udp.dst == 67</code>\n-          and <code>reg9[8] == 0</code> and drops the packet. If\n-          <code>reg9[8]</code> is set to 0 then,\n-          <code>dhcp_relay_resp_chk</code> was unsuccessful.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 flow that matches all packets to advance to the next\n-        table.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 22: ARP/ND Resolution</h3>\n-\n-    <p>\n-      Any packet that reaches this table is an IP packet whose next-hop\n-      IPv4 address is in <code>reg0</code> or IPv6 address is in\n-      <code>xxreg0</code>.  (<code>ip4.dst</code> or\n-      <code>ip6.dst</code> contains the final destination.)  This table\n-      resolves the IP address in <code>reg0</code> (or\n-      <code>xxreg0</code>) into an output port in <code>outport</code>\n-      and an Ethernet address in <code>eth.dst</code>, using the\n-      following flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-500 flow that matches IP multicast traffic that was\n-          allowed in the routing pipeline. For this kind of traffic the\n-          <code>outport</code> was already set so the flow just advances to\n-          the next table.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Priority-200 flows that match ECMP reply traffic for the routes\n-          configured to use symmetric replies, with actions\n-          <code>push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[32..79]; pop(xxreg1); next;</code>.\n-          <code>xxreg1</code> is used here to avoid masked access to ct_label,\n-          to make the flow HW-offloading friendly.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Static MAC bindings.  MAC bindings can be known statically based on\n-          data in the <code>OVN_Northbound</code> database.  For router ports\n-          connected to logical switches, MAC bindings can be known statically\n-          from the <code>addresses</code> column in the\n-          <code>Logical_Switch_Port</code> table. (Note: the flow is not\n-          installed for IPs of logical switch ports of type\n-          <code>virtual</code>, and dynamic MAC binding is used for those IPs\n-          instead, so that virtual parent failover does not depend on <code>\n-          ovn-northd</code>, to achieve better failover performance.) For\n-          router ports connected to other logical routers, MAC bindings can be\n-          known statically from the <code>mac</code> and <code>networks</code>\n-          column in the <code>Logical_Router_Port</code> table.  (Note: the\n-          flow is NOT installed for the IP addresses that belong to a neighbor\n-          logical router port if the current router has the\n-          <code>options:dynamic_neigh_routers</code> set to <code>true</code>)\n-        </p>\n-\n-        <p>\n-          For each IPv4 address <var>A</var> whose host is known to have\n-          Ethernet address <var>E</var> on router port <var>P</var>, a\n-          priority-100 flow with match <code>outport === <var>P</var>\n-          &amp;&amp; reg0 == <var>A</var></code> has actions\n-          <code>eth.dst = <var>E</var>; next;</code>.\n-        </p>\n-\n-        <p>\n-          For each IPv6 address <var>A</var> whose host is known to have\n-          Ethernet address <var>E</var> on router port <var>P</var>, a\n-          priority-100 flow with match <code>outport === <var>P</var>\n-          &amp;&amp; xxreg0 == <var>A</var></code> has actions\n-          <code>eth.dst = <var>E</var>; next;</code>.\n-        </p>\n-\n-        <p>\n-          For each logical router port with an IPv4 address <var>A</var> and\n-          a mac address of <var>E</var> that is reachable via a different\n-          logical router port <var>P</var>, a priority-100 flow with\n-          match <code>outport === <var>P</var> &amp;&amp; reg0 ==\n-          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;\n-          next;</code>.\n-        </p>\n-\n-        <p>\n-          For each logical router port with an IPv6 address <var>A</var> and\n-          a mac address of <var>E</var> that is reachable via a different\n-          logical router port <var>P</var>, a priority-100 flow with\n-          match <code>outport === <var>P</var> &amp;&amp; xxreg0 ==\n-          <var>A</var></code> has actions <code>eth.dst = <var>E</var>;\n-          next;</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Static MAC bindings from NAT entries.  MAC bindings can also be known\n-          for the entries in the <code>NAT</code> table. Below flows are\n-          programmed for distributed logical routers i.e with a distributed\n-          router port.\n-        </p>\n-\n-        <p>\n-          For each row in the <code>NAT</code> table with IPv4 address\n-          <var>A</var> in the <ref column=\"external_ip\"\n-          table=\"NAT\" db=\"OVN_Northbound\"/> column of\n-          <ref table=\"NAT\" db=\"OVN_Northbound\"/> table, below two flows are\n-          programmed:\n-        </p>\n-\n-        <p>\n-          A priority-100 flow with the match <code>outport == <var>P</var>\n-          &amp;&amp; reg0 == <var>A</var></code> has actions <code>eth.dst =\n-          <var>E</var>; next;</code>, where <code>P</code> is the distributed\n-          logical router port, <var>E</var> is the Ethernet address if set in\n-          the <ref column=\"external_mac\" table=\"NAT\" db=\"OVN_Northbound\"/>\n-          column of <ref table=\"NAT\" db=\"OVN_Northbound\"/> table for of type\n-          <code>dnat_and_snat</code>, otherwise the Ethernet address of the\n-          distributed logical router port. Note that if the\n-          <ref column=\"external_ip\" table=\"NAT\" db=\"OVN_Northbound\"/> is not\n-          within a subnet on the owning logical router, then OVN will only\n-          create ARP resolution flows if the <ref column=\"options:add_route\"/>\n-          is set to <code>true</code>. Otherwise, no ARP resolution flows\n-          will be added.\n-        </p>\n-\n-        <p>\n-          Corresponding to the above flow, a priority-150 flow with the match\n-          <code>inport == <var>P</var> &amp;&amp; outport == <var>P</var>\n-          &amp;&amp; ip4.dst == <var>A</var></code> has actions\n-          <code>drop;</code> to exclude packets that have gone through\n-          DNAT/unSNAT stage but failed to convert the destination, to avoid\n-          loop.\n-        </p>\n-\n-        <p>\n-          For IPv6 NAT entries, same flows are added, but using the register\n-          <code>xxreg0</code> and field <code>ip6</code> for the match.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the router datapath runs a port with <code>redirect-type</code>\n-          set to <code>bridged</code>, for each distributed NAT rule with IP\n-          <var>A</var> in the\n-          <ref column=\"logical_ip\" table=\"NAT\" db=\"OVN_Northbound\"/> column\n-          and logical port <var>P</var> in the\n-          <ref column=\"logical_port\" table=\"NAT\" db=\"OVN_Northbound\"/> column\n-          of <ref table=\"NAT\" db=\"OVN_Northbound\"/> table, a priority-90 flow\n-          with the match <code>outport == <var>Q</var> &amp;&amp; ip.src ===\n-          <var>A</var> &amp;&amp; is_chassis_resident(<var>P</var>)</code>,\n-          where <code>Q</code> is the distributed logical router port and\n-          action <code>get_arp(outport, reg0); next;</code> for IPv4 and\n-          <code>get_nd(outport, xxreg0); next;</code> for IPv6.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Traffic with IP destination an address owned by the router should be\n-          dropped. Such traffic is normally dropped in ingress table\n-          <code>IP Input</code> except for IPs that are also shared with SNAT\n-          rules. However, if there was no unSNAT operation that happened\n-          successfully until this point in the pipeline and the destination IP\n-          of the packet is still a router owned IP, the packets can be safely\n-          dropped.\n-        </p>\n-\n-        <p>\n-          A priority-2 logical flow with match <code>ip4.dst = {..}</code>\n-          matches on traffic destined to router owned IPv4 addresses which are\n-          also SNAT IPs. This flow has action <code>drop;</code>.\n-        </p>\n-\n-        <p>\n-          A priority-2 logical flow with match <code>ip6.dst = {..}</code>\n-          matches on traffic destined to router owned IPv6 addresses which are\n-          also SNAT IPs. This flow has action <code>drop;</code>.\n-        </p>\n-\n-        <p>\n-          A priority-0 logical that flow matches all packets not already\n-          handled (match <code>1</code>) and drops them\n-          (action <code>drop;</code>).\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          Dynamic MAC bindings.  These flows resolve MAC-to-IP bindings\n-          that have become known dynamically through ARP or neighbor\n-          discovery.  (The ingress table <code>ARP Request</code> will\n-          issue an ARP or neighbor solicitation request for cases where\n-          the binding is not yet known.)\n-        </p>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>ip4</code> has actions\n-          <code>get_arp(outport, reg0); next;</code>.\n-        </p>\n-\n-        <p>\n-          A priority-0 logical flow with match <code>ip6</code> has actions\n-          <code>get_nd(outport, xxreg0); next;</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For a distributed gateway LRP with <code>redirect-type</code>\n-          set to <code>bridged</code>, a priority-50 flow will match\n-          <code>outport == \"ROUTER_PORT\" and !is_chassis_resident\n-          (\"cr-ROUTER_PORT\")</code> has actions <code>eth.dst = <var>E</var>;\n-          next;</code>, where <var>E</var> is the ethernet address of the\n-          logical router port.\n-        </p>\n-      </li>\n-\n-    </ul>\n-\n-       <h3>Ingress Table 23: Check packet length</h3>\n-\n-    <p>\n-      For distributed logical routers or gateway routers with gateway\n-      port configured with <code>options:gateway_mtu</code> to a valid\n-      integer value, this table adds a priority-50 logical flow with\n-      the match <code>outport == <var>GW_PORT</var></code> where\n-      <var>GW_PORT</var> is the gateway router port and applies the\n-      actions <code>check_pkt_larger</code> and <code>ct_state_save</code>\n-      and then advances the packet to the next table.\n-    </p>\n-\n-    <pre>\n-REGBIT_PKT_LARGER = check_pkt_larger(<var>L</var>);\n-REG_CT_STATE = ct_state_save();\n-next;\n-    </pre>\n-\n-    <p>\n-      where <var>L</var> is the packet length to check for. If the packet\n-      is larger than <var>L</var>, it stores 1 in the register bit\n-      <code>REGBIT_PKT_LARGER</code>. The value of\n-      <var>L</var> is taken from <ref column=\"options:gateway_mtu\"\n-      table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> column of\n-      <ref table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> row.\n-    </p>\n-\n-    <p>\n-      If the port is also configured with\n-      <code>options:gateway_mtu_bypass</code> then another flow is\n-      added, with priority-55, to bypass the <code>check_pkt_larger</code>\n-      flow.\n-    </p>\n-\n-    <p>\n-      This table adds one priority-0 fallback flow that matches all packets\n-      and advances to the next table.\n-    </p>\n-\n-       <h3>Ingress Table 24: Handle larger packets</h3>\n-\n-    <p>\n-      For distributed logical routers or gateway routers with gateway port\n-      configured with <code>options:gateway_mtu</code> to a valid integer\n-      value, this table adds the following priority-150 logical flow for each\n-      logical router port with the match <code>inport == <var>LRP</var>\n-      &amp;&amp; outport == <var>GW_PORT</var> &amp;&amp; REGBIT_PKT_LARGER\n-      &amp;&amp; !REGBIT_EGRESS_LOOPBACK</code>, where <var>LRP</var> is the\n-      logical router port and <var>GW_PORT</var> is the gateway port and\n-      applies the following action for ipv4 and ipv6 respectively:\n-    </p>\n-\n-    <pre>\n-icmp4 {\n-    icmp4.type = 3; /* Destination Unreachable. */\n-    icmp4.code = 4;  /* Frag Needed and DF was Set. */\n-    icmp4.frag_mtu = <var>M</var>;\n-    eth.dst = <var>E</var>;\n-    ip4.dst = ip4.src;\n-    ip4.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER = 0;\n-    next(pipeline=ingress, table=0);\n-};\n-\n-icmp6 {\n-    icmp6.type = 2;\n-    icmp6.code = 0;\n-    icmp6.frag_mtu = <var>M</var>;\n-    eth.dst = <var>E</var>;\n-    ip6.dst = ip6.src;\n-    ip6.src = <var>I</var>;\n-    ip.ttl = 255;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    REGBIT_PKT_LARGER = 0;\n-    next(pipeline=ingress, table=0);\n-};\n-    </pre>\n-\n-    <ul>\n-      <li>\n-        Where <var>M</var> is the (fragment MTU - 58) whose value is taken from\n-        <ref column=\"options:gateway_mtu\" table=\"Logical_Router_Port\"\n-        db=\"OVN_Northbound\"/> column of\n-        <ref table=\"Logical_Router_Port\" db=\"OVN_Northbound\"/> row.\n-      </li>\n-\n-      <li>\n-        <var>E</var> is the Ethernet address of the logical router port.\n-      </li>\n-\n-      <li>\n-        <var>I</var> is the IPv4/IPv6 address of the logical router port.\n-      </li>\n-    </ul>\n-\n-    <p>\n-      This table adds one priority-0 fallback flow that matches all packets\n-      and advances to the next table.\n-    </p>\n-\n-       <h3>Ingress Table 25: Gateway Redirect</h3>\n-\n-    <p>\n-      For distributed logical routers where one or more of the logical router\n-      ports specifies a gateway chassis, this table redirects\n-      certain packets to the distributed gateway port instances on the\n-      gateway chassises.  This table has the following flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        For all the configured load balancing rules that include an IPv4\n-        address <var>VIP</var>, and a list of IPv4 backend addresses\n-        <var>B0</var>, <var>B1</var> .. <var>Bn</var> defined for the\n-        <var>VIP</var> a priority-200 flow is added that matches <code>\n-        ip4 &amp;&amp; (ip4.src == <var>B0</var> || ip4.src == <var>B1</var>\n-        || ... || ip4.src == <var>Bn</var>)</code> with an action <code>\n-        outport = <var>CR</var>; next;</code> where <var>CR</var> is the\n-        <code>chassisredirect</code> port representing the instance of the\n-        logical router distributed gateway port on the gateway chassis.\n-        If the backend IPv4 address <var>Bx</var> is also configured with\n-        L4 port <var>PORT</var> of protocol <var>P</var>, then the match\n-        also includes <code>P.src</code> == <var>PORT</var>.\n-        Similar flows are added for IPv6.\n-      </li>\n-\n-      <li>\n-        For each NAT rule in the OVN Northbound database that can\n-        be handled in a distributed manner, a priority-100 logical\n-        flow with match <code>ip4.src == <var>B</var> &amp;&amp;\n-        outport == <var>GW</var></code> &amp;&amp;\n-        is_chassis_resident(<var>P</var>), where <var>GW</var> is\n-        the distributed gateway port specified in the\n-        NAT rule and <var>P</var> is the NAT logical port. IP traffic\n-        matching the above rule will be managed locally setting\n-        <code>reg1</code> to <var>C</var> and\n-        <code>eth.src</code> to <var>D</var>, where <var>C</var> is NAT\n-        external ip and <var>D</var> is NAT external mac.\n-      </li>\n-\n-      <li>\n-        For each <code>dnat_and_snat</code> NAT rule with\n-        <code>stateless=true</code> and <code>allowed_ext_ips</code>\n-        configured, a priority-75 flow is programmed with match\n-        <code>ip4.dst == <var>B</var></code> and action\n-        <code>outport = <var>CR</var>; next;</code> where <var>B</var>\n-        is the NAT rule external IP and <var>CR</var> is the\n-        <code>chassisredirect</code> port representing the instance\n-        of the logical router distributed gateway port on the\n-        gateway chassis. Moreover a priority-70 flow is programmed\n-        with same match and action <code>drop;</code>.\n-        For each <code>dnat_and_snat</code> NAT rule with\n-        <code>stateless=true</code> and <code>exempted_ext_ips</code>\n-        configured, a priority-75 flow is programmed with match\n-        <code>ip4.dst == <var>B</var></code> and action\n-        <code>drop;</code> where <var>B</var> is the NAT rule\n-        external IP.\n-        A similar flow is added for IPv6 traffic.\n-      </li>\n-\n-      <li>\n-        For each NAT rule in the OVN Northbound database that can\n-        be handled in a distributed manner, a priority-80 logical flow\n-        with drop action if the NAT logical port is a virtual port not\n-        claimed by any chassis yet.\n-      </li>\n-\n-      <li>\n-        A priority-50 logical flow with match\n-        <code>outport == <var>GW</var></code> has actions\n-        <code>outport = <var>CR</var>; next;</code>, where\n-        <var>GW</var> is the logical router distributed gateway\n-        port and <var>CR</var> is the <code>chassisredirect</code>\n-        port representing the instance of the logical router\n-        distributed gateway port on the\n-        gateway chassis.\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 26: Network ID</h3>\n-\n-    <p>\n-      This table contains flows that set <code>flags.network_id</code> for\n-      IP packets:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          A priority-110 flow with match:\n-          <ul>\n-            <li>\n-              for IPv4: <code>outport == <var>P</var> &amp;&amp;\n-              REG_NEXT_HOP_IPV4 == <var>I</var>/<var>C</var> &amp;&amp;\n-              ip4</code>\n-            </li>\n-            <li>\n-              for IPv6: <code>outport == <var>P</var> &amp;&amp;\n-              REG_NEXT_HOP_IPV6 == <var>I</var>/<var>C</var> &amp;&amp;\n-              ip6</code>\n-            </li>\n-          </ul>\n-        </p>\n-\n-        <p>\n-          and actions <code>flags.network_id = <var>N</var>; next;</code>.\n-          Where <var>P</var> is the outport, <var>I</var>/<var>C</var> is a\n-          network CIDR of the port <var>P</var>, and <var>N</var> is the\n-          network id (index). There is one flow like this per router port's\n-          network.\n-        </p>\n-\n-        <p>\n-        <code>flags.network_id</code> is 4 bits, and thus only 16 networks can\n-        be indexed. If the number of networks is greater than 16, networks 17\n-        and up will have the actions <code>flags.network_id = 0; next;</code>\n-        and only the lexicographically first IP will be considered for SNAT for\n-        those networks.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A lower priority-105 flow with match <code>1</code> and actions\n-        <code>flags.network_id = 0; next;</code>. This is for the case that the\n-        next-hop doesn't belong to any of the port networks, so\n-        <code>flags.network_id</code> should be set to zero.\n-      </li>\n-\n-      <li>\n-        Catch-all: A priority-0 flow with match <code>1</code> has\n-        actions <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-       <h3>Ingress Table 27: ARP Request</h3>\n-\n-    <p>\n-      In the common case where the Ethernet destination has been resolved, this\n-      table advances the packet to the next table.  Otherwise, it composes and\n-      sends an ARP or IPv6 Neighbor Solicitation request.  It holds the\n-      following flows:\n-    </p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          Unknown MAC address.  A priority-100 flow for IPv4 packets with match\n-          <code>eth.dst == 00:00:00:00:00:00</code> has the following actions:\n-        </p>\n-\n-        <pre>\n-arp {\n-    eth.dst = ff:ff:ff:ff:ff:ff;\n-    arp.spa = reg1;\n-    arp.tpa = reg0;\n-    arp.op = 1;  /* ARP request. */\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          Unknown MAC address.  For each IPv6 static route associated with the\n-          router with the nexthop IP: <var>G</var>, a priority-200 flow\n-          for IPv6 packets with match\n-          <code>eth.dst == 00:00:00:00:00:00 &amp;&amp;\n-          xxreg0 == <var>G</var></code>\n-          with the following actions is added:\n-        </p>\n-\n-        <pre>\n-nd_ns {\n-    eth.dst = <var>E</var>;\n-    ip6.dst = <var>I</var>\n-    nd.target = <var>G</var>;\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          Where <var>E</var> is the multicast mac derived from the Gateway IP,\n-          <var>I</var> is the solicited-node multicast address corresponding\n-          to the target address <var>G</var>.\n-        </p>\n-\n-        <p>\n-          Unknown MAC address.  A priority-100 flow for IPv6 packets with match\n-          <code>eth.dst == 00:00:00:00:00:00</code> has the following actions:\n-        </p>\n-\n-        <pre>\n-nd_ns {\n-    nd.target = xxreg0;\n-    output;\n-};\n-        </pre>\n-\n-        <p>\n-          (Ingress table <code>IP Routing</code> initialized <code>reg1</code>\n-          with the IP address owned by <code>outport</code> and\n-          <code>(xx)reg0</code> with the next-hop IP address)\n-        </p>\n-\n-        <p>\n-          The IP packet that triggers the ARP/IPv6 NS request is dropped.\n-        </p>\n-      </li>\n-\n-      <li>\n-        Known MAC address.  A priority-0 flow with match <code>1</code> has\n-        actions <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Ingress Table 28: ECMP symmetric reply processing for egress</h3>\n-    <p>\n-      This table contains logical flows that commit IP traffic forwarded by\n-      ECMP symmetric reply static routes in the \"route direction\", that is,\n-      for sessions initiated from behind such routes.  These flows can be hit\n-      only on gateway routers, the only type of routers that supports ECMP\n-      symmetric reply routes.  As the egress port of the traffic needs to be\n-      stored in conntrack for these sessions, one logical flow is added for\n-      each logical router port.\n-    </p>\n-\n-    <h3>Egress Table 0: Check DNAT local </h3>\n-\n-    <p>\n-      This table checks if the packet needs to be DNATed in the router ingress\n-      table <code>lr_in_dnat</code> after it is SNATed  and looped back\n-      to the ingress pipeline.  This check is done only for routers configured\n-      with distributed gateway ports and NAT entries.  This check is done\n-      so that SNAT and DNAT is done in different zones instead of a common\n-      zone.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>REGBIT_DST_NAT_IP_LOCAL = 0; next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 1: UNDNAT</h3>\n-\n-    <p>\n-      This is for already established connections' reverse traffic.\n-      i.e., DNAT has already been done in ingress pipeline and now the\n-      packet has entered the egress pipeline as part of a reply.  This traffic\n-      is unDNATed here.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 1: UNDNAT on Gateway Routers</h3>\n-\n-    <ul>\n-      <li>\n-        For IPv6 Neighbor Discovery or Router Solicitation/Advertisement\n-        traffic, a priority-100 flow with action <code>next;</code>.\n-      </li>\n-\n-      <li>\n-        For all IP packets, a priority-50 flow with an action\n-        <code>flags.loopback = 1; ct_dnat;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 1: UNDNAT on Distributed Routers</h3>\n-    <ul>\n-      <li>\n-        <p>\n-          For all the configured load balancing rules for a router with gateway\n-          port in <code>OVN_Northbound</code> database that includes an IPv4\n-          address <code>VIP</code>, for every backend IPv4 address <var>B</var>\n-          defined for the <code>VIP</code> a priority-120 flow is programmed on\n-          gateway chassis that matches\n-          <code>ip &amp;&amp; ip4.src == <var>B</var> &amp;&amp;\n-          outport == <var>GW</var></code>, where <var>GW</var> is the logical\n-          router gateway port with an action <code>ct_dnat;</code>.\n-          If the backend IPv4 address <var>B</var> is also configured with\n-          L4 port <var>PORT</var> of protocol <var>P</var>, then the\n-          match also includes <code>P.src</code> == <var>PORT</var>.  These\n-          flows are not added for load balancers with IPv6 <var>VIPs</var>.\n-        </p>\n-\n-        <p>\n-          If the router is configured to force SNAT  any load-balanced packets,\n-          above action will be replaced by\n-          <code>flags.force_snat_for_lb = 1; ct_dnat;</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each configuration in the OVN Northbound database that asks\n-          to change the destination IP address of a packet from an IP\n-          address of <var>A</var> to <var>B</var>, a priority-100 flow\n-          matches <code>ip &amp;&amp; ip4.src == <var>B</var>\n-          &amp;&amp; outport == <var>GW</var></code>, where <var>GW</var>\n-          is the logical router gateway port, with an action\n-          <code>ct_dnat;</code>. If the NAT rule is of type\n-          dnat_and_snat and has <code>stateless=true</code> in the\n-          options, then the action would be <code>next;</code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule cannot be handled in a distributed manner, then\n-          the priority-100 flow above is only programmed on the\n-          gateway chassis with the action <code>ct_dnat</code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule can be handled in a distributed manner, then\n-          there is an additional action\n-          <code>eth.src = <var>EA</var>;</code>, where <var>EA</var>\n-          is the ethernet address associated with the IP address\n-          <var>A</var> in the NAT rule.  This allows upstream MAC\n-          learning to point to the correct chassis.\n-        </p>\n-      </li>\n-\n-    </ul>\n-\n-    <h3>Egress Table 2: Post UNDNAT</h3>\n-\n-    <p>\n-      <ul>\n-        <li>\n-          A priority-70 logical flow is added that initiates CT state for\n-          traffic that is configured to be SNATed on Distributed routers.\n-          This allows the next table, <code>lr_out_snat</code>, to\n-          effectively match on various CT states.\n-        </li>\n-\n-        <li>\n-          A priority-50 logical flow is added that commits any untracked flows\n-          from the previous table <code>lr_out_undnat</code> for Gateway\n-          routers.  This flow matches on <code>ct.new &amp;&amp; ip</code>\n-          with action <code>ct_commit { } ; next; </code>.\n-        </li>\n-\n-        <li>\n-          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-          the following flows are configured matching on <code>ip &amp;&amp;\n-          (!ct.trk || !ct.rpl) &amp;&amp; flags.unsnat_not_tracked == 1</code>\n-          with  an action <code>ct_next(snat);</code> and <code>ip &amp;&amp;\n-          flags.unsnat_new == 1</code> with an action <code>next;</code>. There\n-          is extra match when there is configured DGP\n-          <code>outport == DGP &amp;&amp; is_chassis_resident(CHASSIS)</code>.\n-        </li>\n-\n-        <li>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-        </li>\n-\n-      </ul>\n-    </p>\n-\n-    <h3>Egress Table 3: SNAT</h3>\n-\n-    <p>\n-      Packets that are configured to be SNATed get their source IP address\n-      changed based on the configuration in the OVN Northbound database.\n-    </p>\n-\n-    <ul>\n-      <li>\n-        A priority-120 flow to advance the IPv6 Neighbor solicitation packet\n-        to next table to skip SNAT. In the case where ovn-controller injects\n-        an IPv6 Neighbor Solicitation packet (for <code>nd_ns</code> action)\n-        we don't want the packet to go through conntrack.\n-      </li>\n-    </ul>\n-\n-    <p>Egress Table 3: SNAT on Gateway Routers</p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          If the Gateway router in the OVN Northbound database has been\n-          configured to force SNAT a packet (that has been previously DNATted)\n-          to <var>B</var>, a priority-100 flow matches\n-          <code>flags.force_snat_for_dnat == 1 &amp;&amp; ip</code> with an\n-          action <code>ct_snat(<var>B</var>);</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If a load balancer configured to skip snat has been applied to\n-          the Gateway router pipeline, a priority-120 flow matches\n-          <code>flags.skip_snat_for_lb == 1 &amp;&amp; ip</code> with an\n-          action <code>next;</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the Gateway router in the OVN Northbound database has been\n-          configured to force SNAT a packet (that has been previously\n-          load-balanced) using router IP (i.e <ref column=\"options\"\n-          table=\"Logical_Router\"/>:lb_force_snat_ip=router_ip), then for\n-          each logical router port <var>P</var> attached to the Gateway\n-          router, and for each network configured for this port, a priority-110\n-          flow matches <code>flags.force_snat_for_lb == 1</code> &amp;&amp;\n-          <code>ip4</code> &amp;&amp;\n-          <code>flags.network_id == <var>N</var></code> &amp;&amp;\n-          <code>outport == <var>P</var></code>, where <var>N</var> is the\n-          network index, with an action <code>ct_snat(<var>R</var>);</code>\n-          where <var>R</var> is the IP configured on the router port. A similar\n-          flow is created for IPv6, with <code>ip6</code> instead of\n-          <code>ip4</code>. <var>N</var>, the network index, will be 0 for\n-          networks 17 and up.\n-        </p>\n-\n-        <p>\n-          If the logical router port <var>P</var> is configured with multiple\n-          IPv4 and multiple IPv6 addresses, the IPv4 and IPv6 address within\n-          the same network as the next-hop will be chosen as <var>R</var> for\n-          SNAT. However, if there are more than 16 networks configured, the\n-          lexicographically first IP will be considered for SNAT for networks\n-          17 and up.\n-        </p>\n-      </li>\n-      <li>\n-        <p>\n-          A priority-105 flow matches the old behavior for if northd is\n-          upgraded before controller and <code>flags.network_id</code> is not\n-          recognized. It is only added if there's at least one network\n-          configured (excluding LLA for IPv6). It matches on:\n-          <code>flags.force_snat_for_lb == 1</code> &amp;&amp; <code>ip4</code>\n-          &amp;&amp; <code>outport == <var>P</var></code>, with action:\n-          <code>ct_snat(<var>R</var>)</code>.\n-          <var>R</var> is the lexicographically first IP address configured.\n-          There is a similar flow for IPv6 with <code>ip6</code> instead of\n-          <code>ip4</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the Gateway router in the OVN Northbound database has been\n-          configured to force SNAT a packet (that has been previously\n-          load-balanced) to <var>B</var>, a priority-100 flow matches\n-          <code>flags.force_snat_for_lb == 1 &amp;&amp; ip</code> with an\n-          action <code>ct_snat(<var>B</var>);</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the source IP address of a packet from an IP address of\n-          <var>A</var> or to change the source IP address of a packet that\n-          belongs to network <var>A</var> to <var>B</var>, a flow matches\n-          <code>ip &amp;&amp; ip4.src == <var>A</var> &amp;&amp;\n-          (!ct.trk || !ct.rpl)</code> with an action\n-          <code>ct_snat(<var>B</var>);</code>.  The priority of the flow\n-          is calculated based on the mask of <var>A</var>, with matches\n-          having larger masks getting higher priorities. If the NAT rule is\n-          of type dnat_and_snat and has <code>stateless=true</code> in the\n-          options, then the action would be <code>ip4/6.src=\n-          (<var>B</var>)</code>.\n-        </p>\n-\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the source IP address of a packet from an IP address of\n-          <var>A</var> or to change the source IP address of a packet that\n-          belongs to network <var>A</var> to <var>B</var>, match <var>M</var>\n-          and priority <var>P</var>, a flow matches <code>ip &amp;&amp;\n-          ip4.src == <var>A</var> &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp;\n-          (<var>M</var>)</code> with an action <code>ct_snat(<var>B</var>);\n-          </code>.  The priority of the flow is calculated based as\n-          <code>300 + <var>P</var></code>.  If the NAT rule is of type\n-          dnat_and_snat and has <code>stateless=true</code> in the options,\n-          then the action would be <code>ip4/6.src=(<var>B</var>)</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n-          there is an additional match <code>ip4.dst == <var>allowed_ext_ips\n-          </var></code>. Similarly, for IPV6, match would be <code>ip6.dst ==\n-          <var>allowed_ext_ips</var></code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the NAT rule has <code>exempted_ext_ips</code> set, then\n-          there is an additional flow configured at the priority + 1 of\n-          corresponding NAT rule. The flow matches if destination ip\n-          is an <code>exempted_ext_ip</code> and the action is <code>next;\n-          </code>. This flow is used to bypass the ct_snat action for a packet\n-          which is destinted to <code>exempted_ext_ips</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-          the following two flows are configured matching on <code> ip\n-          &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp;\n-          flags.unsnat_new == 1</code> and\n-          <code>ip &amp;&amp; ct.new &amp;&amp; flags.unsnat_not_tracked == 1\n-          </code> both with an action <code>ct_commit_to_zone(snat);</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        <p>\n-          A priority-0 logical flow with match <code>1</code> has actions\n-          <code>next;</code>.\n-        </p>\n-      </li>\n-    </ul>\n-\n-    <p>Egress Table 3: SNAT on Distributed Routers</p>\n-\n-    <ul>\n-      <li>\n-        <p>\n-          For each configuration in the OVN Northbound database, that asks\n-          to change the source IP address of a packet from an IP address of\n-          <var>A</var> or to change the source IP address of a packet that\n-          belongs to network <var>A</var> to <var>B</var>, two flows are\n-          added.  The priority <var>P</var> of these flows are calculated\n-          based on the mask of <var>A</var>, with matches having larger\n-          masks getting higher priorities.\n-        </p>\n-\n-        <p>\n-          If the NAT rule cannot be handled in a distributed manner, then\n-          the below flows are only programmed on the gateway chassis increasing\n-          flow priority by 128 in order to be run first.\n-        </p>\n-\n-        <ul>\n-          <li>\n-            The first flow is added with the calculated priority <var>P</var>\n-            and match <code>ip &amp;&amp; ip4.src == <var>A</var> &amp;&amp;\n-            outport == <var>GW</var></code>, where <var>GW</var> is the\n-            logical router gateway port, with an action\n-            <code>ct_snat(<var>B</var>);</code> to SNATed in the\n-            common zone.  If the NAT rule is of type dnat_and_snat and has\n-            <code>stateless=true</code> in the options, then the action\n-            would be <code>ip4/6.src=(<var>B</var>)</code>.\n-          </li>\n-        </ul>\n-\n-        <p>\n-          If the NAT rule can be handled in a distributed manner, then\n-          there is an additional action (for both the flows)\n-          <code>eth.src = <var>EA</var>;</code>, where <var>EA</var>\n-          is the ethernet address associated with the IP address\n-          <var>A</var> in the NAT rule.  This allows upstream MAC\n-          learning to point to the correct chassis.\n-        </p>\n-\n-        <p>\n-          If the NAT rule has <code>allowed_ext_ips</code> configured, then\n-          there is an additional match <code>ip4.dst == <var>allowed_ext_ips\n-          </var></code>. Similarly, for IPV6, match would be <code>ip6.dst ==\n-          <var>allowed_ext_ips</var></code>.\n-        </p>\n-\n-        <p>\n-          If the NAT rule has <code>exempted_ext_ips</code> set, then\n-          there is an additional flow configured at the priority\n-          <code><var>P</var> + 2 </code> of\n-          corresponding NAT rule. The flow matches if destination ip\n-          is an <code>exempted_ext_ip</code> and the action is <code>next;\n-          </code>. This flow is used to bypass the ct_snat action for a flow\n-          which is destinted to <code>exempted_ext_ips</code>.\n-        </p>\n-\n-      </li>\n-\n-      <li>\n-        An additional flow is added for traffic that goes in opposite\n-        direction (i.e. it enters a network with configured SNAT). Where the\n-        flow above matched on <code>ip4.src == <var>A</var> &amp;&amp; outport\n-        == <var>GW</var></code>, this flow matches on <code> ip4.dst ==\n-        <var>A</var> &amp;&amp; inport == <var>GW</var></code>. A CT state is\n-        initiated for this traffic so that the following table, <code>\n-        lr_out_post_snat</code>, can identify whether the traffic flow was\n-        initiated from the internal or external network.\n-      </li>\n-\n-      <li>\n-        <p>\n-          If the <code>options:ct-commit-all</code> is set to <code>true</code>\n-          the following two flows are configured matching on <code>ip\n-          &amp;&amp; (!ct.trk || !ct.rpl) &amp;&amp; flags.unsnat_new == 1\n-          &amp;&amp; outport == DGP &amp;&amp; is_chassis_resident(CHASSIS)\n-          </code> and <code>ip &amp;&amp; ct.new &amp;&amp;\n-          flags.unsnat_not_tracked == 1 &amp;&amp; outport == DGP &amp;&amp;\n-          is_chassis_resident(CHASSIS)</code>both  with an action\n-          <code>ct_commit_to_zone(snat);</code>.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 4: Post SNAT</h3>\n-\n-    <p>\n-      Packets reaching this table are processed according to the flows below:\n-      <ul>\n-        <li>\n-          Traffic that goes directly into a network configured with SNAT on\n-          Distributed routers, and was initiated from an external network (i.e.\n-          it matches <code>ct.new</code>), is committed to the SNAT CT zone.\n-          This ensures that replies returning from the SNATed network do not\n-          have their source address translated. For details about match rules\n-          and priority see section \"Egress Table 3: SNAT on Distributed\n-          Routers\".\n-        </li>\n-\n-        <li>\n-          A priority-0 logical flow that matches all packets not already\n-          handled (match <code>1</code>) and action <code>next;</code>.\n-        </li>\n-      </ul>\n-    </p>\n-\n-    <h3>Egress Table 5: Egress Loopback</h3>\n-\n-    <p>\n-      For distributed logical routers where one of the logical router\n-      ports specifies a gateway chassis.\n-    </p>\n-\n-    <p>\n-      While UNDNAT and SNAT processing have already occurred by this\n-      point, this traffic needs to be forced through egress loopback on\n-      this distributed gateway port instance, in order for UNSNAT and\n-      DNAT processing to be applied, and also for IP routing and ARP\n-      resolution after all of the NAT processing, so that the packet can\n-      be forwarded to the destination.\n-    </p>\n-\n     <p>\n-      This table has the following flows:\n+      For a detailed description of the logical flow tables that\n+      <code>ovn-northd</code> populates in the\n+      <code>OVN_Southbound</code> database, including logical switch\n+      and router datapath pipelines and drop sampling behavior, see\n+      <code>ovn-logical-flows</code>(7).\n     </p>\n \n-    <ul>\n-      <li>\n-        <p>\n-          For each NAT rule in the OVN Northbound database on a\n-          distributed router, a priority-100 logical flow with match\n-          <code>ip4.dst == <var>E</var> &amp;&amp;\n-          outport == <var>GW</var> &amp;&amp;\n-          is_chassis_resident(<var>P</var>)</code>, where <var>E</var> is the\n-          external IP address specified in the NAT rule, <var>GW</var>\n-          is the distributed gateway port corresponding to the NAT rule\n-          (specified or inferred).\n-          For dnat_and_snat NAT rule, <var>P</var> is the logical port\n-          specified in the NAT rule.\n-          If <ref column=\"logical_port\"\n-          table=\"NAT\" db=\"OVN_Northbound\"/> column of\n-          <ref table=\"NAT\" db=\"OVN_Northbound\"/> table is NOT set, then\n-          <var>P</var> is the <code>chassisredirect port</code> of\n-          <var>GW</var> with the following actions:\n-        </p>\n-\n-        <pre>\n-clone {\n-    ct_clear;\n-    inport = outport;\n-    outport = \"\";\n-    flags = 0;\n-    flags.loopback = 1;\n-    reg0 = 0;\n-    reg1 = 0;\n-    ...\n-    reg9 = 0;\n-    REGBIT_EGRESS_LOOPBACK = 1;\n-    next(pipeline=ingress, table=0);\n-};\n-        </pre>\n-\n-        <p>\n-          <code>flags.loopback</code> is set since in_port is unchanged\n-          and the packet may return back to that port after NAT processing.\n-          <code>REGBIT_EGRESS_LOOPBACK</code> is set to indicate that\n-          egress loopback has occurred, in order to skip the source IP\n-          address check against the router address.\n-        </p>\n-      </li>\n-\n-      <li>\n-        A priority-0 logical flow with match <code>1</code> has actions\n-        <code>next;</code>.\n-      </li>\n-    </ul>\n-\n-    <h3>Egress Table 6: Delivery</h3>\n-\n-    <p>\n-      Packets that reach this table are ready for delivery.  It contains:\n-      <ul>\n-        <li>\n-          Priority-110 logical flows that match IP multicast packets on each\n-          enabled logical router port and modify the Ethernet source address\n-          of the packets to the Ethernet address of the port and then execute\n-          action <code>output;</code>.\n-        </li>\n-        <li>\n-          Priority-100 logical flows that match packets on each enabled\n-          logical router port, with action <code>output;</code>.\n-        </li>\n-        <li>\n-          A priority-0 logical flow that matches all packets not already\n-          handled (match <code>1</code>) and drops them\n-          (action <code>drop;</code>).\n-        </li>\n-      </ul>\n-    </p>\n-\n-    <h1>Drop sampling</h1>\n-\n-    <p>\n-      As described in the previous section, there are several places where\n-      ovn-northd might decided to drop a packet by explicitly creating a\n-      <code>Logical_Flow</code> with the <code>drop;</code> action.\n-    </p>\n-\n-    <p>\n-      When debug drop-sampling has been cofigured in the OVN Northbound\n-      database, the ovn-northd will replace all the <code>drop;</code>\n-      actions with a <code>sample(priority=65535, collector_set=<var>id</var>,\n-      obs_domain=<var>obs_id</var>, obs_point=@cookie)</code> action, where:\n-      <ul>\n-        <li>\n-        <var>id</var> is the value the <code>debug_drop_collector_set</code>\n-        option configured in the OVN Northbound.\n-        </li>\n-        <li>\n-        <var>obs_id</var> has it's 8 most significant bits equal to the value\n-        of the <code>debug_drop_domain_id</code> option in the OVN Northbound\n-        and it's 24 least significant bits equal to the datapath's tunnel key.\n-        </li>\n-      </ul>\n-    </p>\n \n </manpage>\n","prefixes":["ovs-dev","3/5"]}