Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2229778/?format=api
{ "id": 2229778, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229778/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-6-mmichels@redhat.com/", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/1.1/projects/68/?format=api", "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-6-mmichels@redhat.com>", "date": "2026-04-28T17:45:05", "name": "[ovs-dev,5/5] northd: Convert ovn-logical-flows(7) from XML to RST.", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "77ef7065e7f5078d569b3b823a151cfabd7454e9", "submitter": { "id": 71978, "url": "http://patchwork.ozlabs.org/api/1.1/people/71978/?format=api", "name": "Mark Michelson", "email": "mmichels@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-6-mmichels@redhat.com/mbox/", "series": [ { "id": 501914, "url": "http://patchwork.ozlabs.org/api/1.1/series/501914/?format=api", "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/2229778/comments/", "check": "fail", "checks": "http://patchwork.ozlabs.org/api/patches/2229778/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=BXaQATdw;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp3.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=BXaQATdw", "smtp4.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "smtp4.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=BXaQATdw" ], "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\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 4g4ntD0MBPz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 03:46:28 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id A1C62610FD;\n\tTue, 28 Apr 2026 17:46:26 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id PUtiTkadjHv7; Tue, 28 Apr 2026 17:46:22 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp3.osuosl.org (Postfix) with ESMTPS id 984B560DB7;\n\tTue, 28 Apr 2026 17:46:22 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 6CB36C04FB;\n\tTue, 28 Apr 2026 17:46:22 +0000 (UTC)", "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 4525CC04FA\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:46:21 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp4.osuosl.org (Postfix) with ESMTP id B078740649\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:34 +0000 (UTC)", "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id RXrtUIe2G8_s for <dev@openvswitch.org>;\n Tue, 28 Apr 2026 17:45:27 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp4.osuosl.org (Postfix) with ESMTPS id C9D404097E\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:23 +0000 (UTC)", "from mx-prod-mc-05.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-380--3i_7c5jMS2t5KLvpEusWw-1; Tue,\n 28 Apr 2026 13:45:16 -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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 402CF195608F\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:15 +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 BB51119560AB\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:14 +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 smtp3.osuosl.org 984B560DB7", "OpenDKIM Filter v2.11.0 smtp4.osuosl.org C9D404097E" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=mmichels@redhat.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp4.osuosl.org C9D404097E", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777398322;\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=wK5BdEsrE7Ft8lYGMxiwphIZYB9kDklmb+mfVlrhpmE=;\n b=BXaQATdwO5rlsTo+apgHaSgrnc4wMvSZxhiu9avLTEMw1472QE6pET8mPtAB6569HplCSL\n wQbLvt7xN6/0d1YSHS2H9axEonF3cAZ9Z1MU6UIlhYBpT9/4mWMeYxUc16NVTsrNXh6G6A\n Iqsx/qFp/oPVl20/g3q27+PtsR8T9OY=", "X-MC-Unique": "-3i_7c5jMS2t5KLvpEusWw-1", "X-Mimecast-MFC-AGG-ID": "-3i_7c5jMS2t5KLvpEusWw_1777398315", "To": "dev@openvswitch.org", "Date": "Tue, 28 Apr 2026 13:45:05 -0400", "Message-ID": "<20260428174509.145440-6-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": "EUJCPT5NC6ZTphCTzy1TQJpGvrQtYFUIjL1985hon8w_1777398315", "X-Mimecast-Originator": "redhat.com", "Subject": "[ovs-dev] [PATCH ovn 5/5] northd: Convert ovn-logical-flows(7) from\n XML to RST.", "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": "Replace ovn-logical-flows.7.xml with ovn-logical-flows.7.rst, using\nrst2man to generate the manpage. Update automake.mk to reference the\nRST file and add an explicit rst2man build rule. Fix the document\nstructure to use rst2man's title/subtitle/docinfo format so the NAME\nsection renders correctly without duplication.\n\nThe rationale for this change is that RST is more compact, and easier\nfor humans to read and write than XML. ovn-northd is frequently updated\nto add new logical flows, so updating an RST document is much easier\nthan updating an XML document.\n\nThe build rule added in northd/automake.mk is necessary since rst2man\ngenerates \".ft C\" for code blocks and inline literals, indicating to use\nthe Courier font. But not all nroff and troff implementations have the\nCourier font available (including mine). The build rule changes this to\nuse \".ft B\" instead, for bold font. This actually matches what was done\nin the XML manpage already.\n\nAssisted-by: Claude Code (Claude Opus 4.6)\nSigned-off-by: Mark Michelson <mmichels@redhat.com>\n---\n Documentation/intro/install/general.rst | 5 +\n northd/automake.mk | 5 +-\n northd/ovn-logical-flows.7.rst | 4311 ++++++++++++++++\n northd/ovn-logical-flows.7.xml | 6080 -----------------------\n rhel/ovn-fedora.spec.in | 1 +\n 5 files changed, 4321 insertions(+), 6081 deletions(-)\n create mode 100644 northd/ovn-logical-flows.7.rst\n delete mode 100644 northd/ovn-logical-flows.7.xml", "diff": "diff --git a/Documentation/intro/install/general.rst b/Documentation/intro/install/general.rst\nindex b5dd403d7..1f955bd93 100644\n--- a/Documentation/intro/install/general.rst\n+++ b/Documentation/intro/install/general.rst\n@@ -117,6 +117,11 @@ other than plain text, only if you have the following:\n \n - dot from graphviz (http://www.graphviz.org/).\n \n+Certain OVN manpages are built from reStructuredText documents and\n+require the following:\n+\n+- rst2man.\n+\n If you are going to extensively modify OVN, consider installing the\n following to obtain better warnings:\n \ndiff --git a/northd/automake.mk b/northd/automake.mk\nindex 47142a5b0..d6a1656cf 100644\n--- a/northd/automake.mk\n+++ b/northd/automake.mk\n@@ -72,5 +72,8 @@ 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+EXTRA_DIST += northd/ovn-logical-flows.7.rst\n CLEANFILES += northd/ovn-logical-flows.7\n+\n+northd/ovn-logical-flows.7: northd/ovn-logical-flows.7.rst\n+\t$(AM_V_GEN)rst2man $< > $@.tmp && sed 's/^\\.ft C/.ft B/' $@.tmp > $@ && rm $@.tmp\ndiff --git a/northd/ovn-logical-flows.7.rst b/northd/ovn-logical-flows.7.rst\nnew file mode 100644\nindex 000000000..62900a4be\n--- /dev/null\n+++ b/northd/ovn-logical-flows.7.rst\n@@ -0,0 +1,4311 @@\n+=================\n+ovn-logical-flows\n+=================\n+\n+--------------------------------------\n+OVN logical flow table reference\n+--------------------------------------\n+\n+:Manual section: 7\n+:Manual group: Open Virtual Network\n+\n+Description\n+-----------\n+\n+This document describes the logical flow tables that\n+``ovn-northd``\\(8) populates in the ``OVN_Southbound`` database.\n+It covers both logical switch and logical router datapath pipelines,\n+as well as drop sampling behavior.\n+\n+Logical Switch Datapaths\n+------------------------\n+\n+Ingress Table 0: Admission Control and Ingress Port Security check\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Ingress table 0 contains these logical flows:\n+\n+- Priority 100 flows to drop packets with VLAN tags or multicast\n+ Ethernet source addresses.\n+\n+- For each disabled logical port, a priority 100 flow is added which\n+ matches on all packets and applies the action\n+ ``REGBIT_PORT_SEC_DROP\" = 1; next;\"`` so that the packets are\n+ dropped in the next stage.\n+\n+- For each logical port that's defined as a target of routing protocol\n+ redirecting (via ``routing-protocol-redirect`` option set on\n+ Logical Router Port), a filter is set in place that disallows\n+ following traffic exiting this port:\n+\n+ - ARP replies\n+\n+ - IPv6 Neighbor Discovery - Router Advertisements\n+\n+ - IPv6 Neighbor Discovery - Neighbor Advertisements\n+\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+ ``REGBIT_PORT_SEC_DROP\" = 1; next;\"``.\n+\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 ``REGBIT_EXT_ARP`` register is set for all ARP requests\n+ originating from physical ports with priority 75 flow.\n+\n+- For each (enabled) vtep logical port, a priority 70 flow is added which\n+ matches on all packets and applies the action\n+ ``next(pipeline=ingress, table=S_SWITCH_IN_L3_LKUP) = 1;``\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+\n+- For each enabled logical port configured with qdisc queue id in the\n+ ``options:qdisc_queue_id`` column of ``Logical_Switch_Port``,\n+ a priority 70 flow is added which matches on all packets and applies\n+ the action\n+ ``set_queue(id); REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;\"``.\n+\n+- A priority 1 flow is added which matches on all packets for all the\n+ logical ports and applies the action\n+ ``REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;`` to\n+ evaluate the port security. The action ``check_in_port_sec``\n+ applies the port security rules defined in the ``port_security``\n+ column of ``Logical_Switch_Port`` table.\n+\n+Ingress Table 1: Ingress Port Security - Apply\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For each logical switch port *P* 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 ``eth.src == D && outport == P && flags.tunnel_rx == 1``\n+where *D* is the peer logical router port *RP* mac address,\n+swaps inport and outport and applies the action ``next``.\n+\n+For each logical switch port *P* 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 ``eth.dst == D && flags.tunnel_rx == 1``\n+where *D* is the peer logical router port *RP* mac address, swaps inport\n+and outport and applies the action ``next(pipeline=S_SWITCH_IN_L2_LKUP)``.\n+\n+For each logical switch port *P* a priority-110 flow that\n+matches 'recirculated' icmp{4,6} error 'packet too big' and\n+``eth.src == D && outport == P && !is_chassis_resident(\"P\") && flags.tunnel_rx == 1``\n+where *D* is the logical switch port mac address,\n+swaps inport and outport and applies the action ``next``.\n+\n+This table adds a priority-105 flow that matches 'recirculated' icmp{4,6}\n+error 'packet too big' to drop the packet.\n+\n+This table drops the packets if the port security check failed\n+in the previous stage i.e the register bit\n+``REGBIT_PORT_SEC_DROP`` is set to 1.\n+\n+Ingress table 1 contains these logical flows:\n+\n+- A priority-50 fallback flow that drops the packet if the register\n+ bit ``REGBIT_PORT_SEC_DROP`` is set to 1.\n+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+- Priority 75: Allows ``REGBIT_EXT_ARP`` packets only on gateway\n+ chassis and chassis with distributed NAT entries.\n+ Priority 70: Drops ``REGBIT_EXT_ARP`` packets on non-gateway\n+ chassis (complements the priority 75 flow).\n+\n+Ingress Table 2: Mirror\n+~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Overlay remote mirror table contains the following\n+logical flows:\n+\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+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\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+\n+Ingress Table 3: Lookup MAC address learning table\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table looks up the MAC learning table of the logical switch\n+datapath to check if the ``port-mac`` 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 ``switch`` have implicit\n+'unknown' addresses and so they are also eligible for MAC learning.\n+\n+- For each such VIF logical port *p* whose port security\n+ is disabled and 'unknown' address set following flow\n+ is added.\n+\n+ - Priority 100 flow with the match\n+ ``inport == p`` and action\n+ ``reg0[11] = lookup_fdb(inport, eth.src); next;``\n+\n+- For each such localnet logical port *p* following flow\n+ is added.\n+\n+ - Priority 100 flow with the match\n+ ``inport == p`` and action\n+ ``flags.localnet = 1;``\n+ ``reg0[11] = lookup_fdb(inport, eth.src); next;``\n+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 4: Learn MAC of 'unknown' ports.\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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 ``lookup_fdb`` 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+\n+- For each such VIF logical port *p* whose port security is\n+ disabled and 'unknown' address set and localnet port following flow\n+ is added.\n+\n+ - Priority 100 flow with the match\n+ ``inport == p && reg0[11] == 0`` and\n+ action ``put_fdb(inport, eth.src); next;`` which stores\n+ the ``port-mac`` in the mac learning table of the\n+ logical switch datapath and advances the packet to the next table.\n+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 5: ``from-lport`` Pre-ACLs\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table prepares flows for possible stateful ACL processing in\n+ingress table ``ACLs``. 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 ``reg0[0] = 1; next;``) for table\n+``Pre-stateful`` to send IP packets to the connection tracker\n+before eventually advancing to ingress table ``ACLs``. 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+``options:enable_router_port_acl`` column of\n+``Logical_Switch_Port``. 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+``REGBIT_ACL_STATELESS`` is set for traffic matching stateless\n+ACL flows.\n+\n+This table also has a priority-110 flow with the match\n+``eth.dst == E`` for all logical switch\n+datapaths to move traffic to the next table. Where *E*\n+is the service monitor mac defined in the\n+``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+Ingress Table 6: Pre-LB\n+~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table prepares flows for possible stateful load balancing processing\n+in ingress table ``LB`` and ``Stateful``. 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+``REGBIT_ACL_STATELESS`` is set, to the next table. If load\n+balancing rules with virtual IP addresses (and ports) are configured in\n+``OVN_Northbound`` database for a logical switch datapath, a\n+priority-100 flow is added with the match ``ip`` to match on IP\n+packets and sets the action ``reg0[2] = 1; next;`` to act as a\n+hint for table ``Pre-stateful`` 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 ``Stateful``.\n+If controller_event has been enabled and load balancing rules with\n+empty backends have been added in ``OVN_Northbound``, a 130 flow\n+is added to trigger ovn-controller events whenever the chassis receives a\n+packet for that particular VIP. If ``event-elb`` meter has been\n+previously created, it will be associated to the empty_lb logical flow\n+\n+Prior to ``OVN 20.09`` we were setting the\n+``reg0[0] = 1`` 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 ``allow-related`` action.\n+To understand the issue lets a take a TCP load balancer -\n+``10.0.0.10:80=10.0.0.3:80``. 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+\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+\n+This table also has priority-120 flows that punt all IGMP/MLD packets to\n+``ovn-controller`` if the switch is an interconnect switch\n+with multicast snooping enabled.\n+\n+This table also has a priority-110 flow with the match\n+``eth.dst == E`` for all logical switch\n+datapaths to move traffic to the next table. Where *E*\n+is the service monitor mac defined in the\n+``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+This table also has a priority-110 flow with the match\n+``inport == I`` for all logical switch\n+datapaths to move traffic to the next table. Where *I*\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+\n+Ingress Table 7: Pre-stateful\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- Priority-120 flows that send the packets to connection tracker using\n+ ``ct_lb_mark;`` 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+ ``reg1`` and ``reg2``. For IPv6 traffic the flows\n+ also load the original destination IP and transport port in\n+ registers ``xxreg1`` and ``reg2``.\n+\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 ``reg0[2] == 1``) by using the\n+ ``ct_lb_mark;`` action.\n+\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+\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 ``reg0[0] == 1``) by using the\n+ ``ct_next;`` action.\n+\n+Ingress Table 8: ``from-lport`` ACL hints\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table consists of logical flows that set hints\n+(``reg0`` 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+\n+- ``reg0[7]``: the packet might match an\n+ ``allow-related`` ACL and might have to commit the\n+ connection to conntrack.\n+\n+- ``reg0[8]``: the packet might match an\n+ ``allow-related`` ACL but there will be no need to commit\n+ the connection to conntrack because it already exists.\n+\n+- ``reg0[9]``: the packet might match a\n+ ``drop/reject``.\n+\n+- ``reg0[10]``: the packet might match a\n+ ``drop/reject`` ACL but the connection was previously\n+ allowed so it might have to be committed again with\n+ ``ct_label=1/1``.\n+\n+The table contains the following flows:\n+\n+- A priority-65535 flow to advance to the next table if the logical\n+ switch has ``no`` ACLs configured, otherwise a\n+ priority-0 flow to advance to the next table.\n+\n+- A priority-7 flow that matches on packets that initiate a new session.\n+ This flow sets ``reg0[7]`` and ``reg0[9]`` and\n+ then advances to the next table.\n+\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 ``reg0[7]`` and\n+ ``reg0[9]`` and then advances to the next table.\n+\n+- A priority-5 flow that matches untracked packets. This flow sets\n+ ``reg0[8]`` and ``reg0[9]`` and then advances to\n+ the next table.\n+\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 ``reg0[8]`` and\n+ ``reg0[10]`` and then advances to the next table.\n+\n+- A priority-3 flow that matches on packets that are in not part of\n+ established sessions. This flow sets ``reg0[9]`` and then\n+ advances to the next table.\n+\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 ``reg0[9]`` and then advances to the next\n+ table.\n+\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 ``reg0[10]`` and then advances to the next\n+ table.\n+\n+Ingress table 9: ``from-lport`` ACL evaluation before LB\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Logical flows in this table closely reproduce those in the\n+``ACL`` table in the ``OVN_Northbound`` database\n+for the ``from-lport`` direction without the option\n+``apply-after-lb`` set or set to ``false``.\n+The ``priority`` values from the ``ACL`` 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+\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 ``reg8[16]``. The drop bit is\n+ ``reg8[17]``. 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 ``reg8[16]`` 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+\n+- If the ``tier`` 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+ ``reg8[30..31]``.\n+\n+- ``allow`` 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 ``allow`` ACLs set the\n+ allow bit to one and in addition perform ``ct_commit;`` (which\n+ acts as a hint for future tables to commit the connection to\n+ conntrack). In case the ``ACL`` has a label then\n+ ``reg3`` is loaded with the label value and\n+ ``reg0[13]`` bit is set to 1 (which acts as a hint for the\n+ next tables to commit the label to conntrack).\n+\n+- ``allow-related`` ACLs translate into logical flows that set\n+ the allow bit and additionally have ``ct_commit { ct_label=0/1; };\n+ next;`` actions for new connections and ``reg0[1] = 1;\n+ next;`` for existing connections. In case the ``ACL``\n+ has a label then ``reg3`` is loaded with the label value and\n+ ``reg0[13]`` bit is set to 1 (which acts as a hint for the\n+ next tables to commit the label to conntrack).\n+\n+- For ``allow`` and ``allow-related`` ACL, an\n+ additonal set of registers get set in case the ACL has the column\n+ ``network_function_group`` set to the *id* of one\n+ of the entities in ``Network_Function_Group`` table. The\n+ *id* is an internally generated unique identifier for a\n+ ``Network_Function_Group`` entity. The flow sets\n+ ``reg8[21] = 1`` (to indicate need for packet redirection),\n+ ``reg8[22] = 1`` (to indicate this is a request packet) and\n+ ``reg0[22..29] = id``. These registers are later\n+ used in the ``Network Function`` table.\n+\n+- ``allow-stateless`` ACLs translate into logical flows that set\n+ the allow bit and advance to the next table.\n+\n+- ``reject`` ACLs translate into logical flows with that set the\n+ reject bit and advance to the next table.\n+\n+- ``pass`` ACLs translate into logical flows that do not set the\n+ allow, drop, or reject bit and advance to the next table.\n+\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 ``ct_commit { ct_label=1/1; };``\n+ action. Setting ``ct_label`` marks a connection as one that\n+ was previously allowed, but should no longer be allowed due to a policy\n+ change.\n+\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 ``no``\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 ``options:default_acl_drop`` column of the ``NB_Global``\n+table.\n+\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+\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+\n+- If ``options:default_acl_drop`` column of ``NB_Global``\n+ is ``false`` 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+ ``reg0[1] = 1; next;``). 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+\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 ``reg0[1] = 1;\n+ next;``). 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+\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 ``ct_mark.blocked`` 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, ``ct_mark.blocked`` will get set and packets in the\n+ reply direction will no longer be allowed, either. This flow also\n+ clears the register bits ``reg0[9]`` and\n+ ``reg0[10]`` and sets register bit ``reg0[17]``.\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+\n+- The priority-65532 flows that allow response and related traffic, also\n+ set ``reg8[21] = ct_label.nf``, which gets checked in\n+ the ``Network Function`` table.\n+\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 ``ct_mark.blocked`` 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+\n+- A priority-65532 flow that sets the drop bit for all traffic marked by\n+ the connection tracker as invalid.\n+\n+- A priority-65532 flow that sets the drop bit for all traffic in the\n+ reply direction with ``ct_mark.blocked`` 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+\n+If the logical datapath has any ACL or a load balancer with VIP\n+configured, the following flow will also be added:\n+\n+- A priority 34000 logical flow is added for each logical switch datapath\n+ with the match ``eth.dst = E`` to allow the service\n+ monitor reply packet destined to ``ovn-controller``\n+ that sets the allow bit, where *E* is the\n+ service monitor mac defined in the\n+ ``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+Ingress Table 10: ``from-lport`` ACL sampling\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Logical flows in this table sample traffic matched by\n+``from-lport`` ACLs with sampling enabled.\n+\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+\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 ``sample()`` action and then advances\n+ the packet to the next table.\n+\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 ``sample()`` action and then advances\n+ the packet to the next table.\n+\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 ``sample()`` 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+\n+Ingress Table 11: ``from-lport`` ACL action\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- If no ACLs are configured, then a priority 0 flow is installed that\n+ matches everything and advances to the next table.\n+\n+- A priority 1000 flow is installed that will advance the packet to the\n+ next table if the allow bit is set.\n+\n+- A priority 1000 flow is installed that will run the ``drop;``\n+ action if the drop bit is set.\n+\n+- A priority 1000 flow is installed that will run the ``tcp_reset\n+ { output <-> inport; next(pipeline=egress,table=5);}``\n+ action for TCP connections, ``icmp4/icmp6`` action\n+ for UDP connections, and ``sctp_abort {output <-> inport;\n+ next(pipeline=egress,table=5);}`` action for SCTP associations.\n+\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+\n+Ingress Table 12: ``from-lport`` QoS\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Logical flows in this table closely reproduce those in the\n+``QoS`` table with the ``action`` or\n+``bandwidth`` column set in the\n+``OVN_Northbound`` database for the\n+``from-lport`` direction.\n+\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+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 13: Connection Tracking Field Extraction\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table extracts connection tracking fields for new connections\n+to be used by subsequent load balancing stages.\n+\n+- A priority-100 flow matches ``ct.new && ip`` and\n+ extracts connection tracking protocol and destination port information\n+ into registers ``reg1[16..23]`` (protocol) and\n+ ``reg1[0..15]`` (destination port) using the actions\n+ ``reg1[16..23] = ct_proto(); reg1[0..15] = ct_tp_dst(); next;``.\n+\n+- A priority-0 flow matches all packets and advances to the next table.\n+\n+Ingress Table 14: Load balancing affinity check\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Load balancing affinity check table contains the following\n+logical flows:\n+\n+- For all the configured load balancing rules for a switch in\n+ ``OVN_Northbound`` database where a positive affinity timeout\n+ is specified in ``options`` column, that includes a L4 port\n+ *PORT* of protocol *P* and IP address *VIP*,\n+ a priority-100 flow is added. For IPv4 *VIPs*, the flow\n+ matches ``ct.new && ip && ip4.dst == VIP && reg1[16..23] == PROTO_NUM && reg1[0..15] == PORT``.\n+ For IPv6 *VIPs*, the flow matches\n+ ``ct.new && ip && ip6.dst == VIP && reg1[16..23] == PROTO_NUM && reg1[0..15] == PORT``.\n+ The flow's action is ``reg9[6] = chk_lb_aff(); next;``.\n+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\n+Ingress Table 15: LB\n+~~~~~~~~~~~~~~~~~~~~~\n+\n+- For all the configured load balancing rules for a switch in\n+ ``OVN_Northbound`` database where a positive affinity timeout\n+ is specified in ``options`` column, that includes a L4 port\n+ *PORT* of protocol *P* and IP address *VIP*,\n+ a priority-150 flow is added. For IPv4 *VIPs*, the flow\n+ matches ``reg9[6] == 1 && ct.new && ip && ip4.dst == VIP && P.dst == PORT``.\n+ For IPv6 *VIPs*, the flow matches\n+ ``reg9[6] == 1 && ct.new && ip && ip6.dst == VIP && P && P.dst == PORT``.\n+ The flow's action is ``ct_lb_mark(args)``, where\n+ *args* contains comma separated IP addresses (and optional\n+ port numbers) to load balance to. The address family of the IP\n+ addresses of *args* is the same as the address family\n+ of *VIP*.\n+\n+- For all the configured load balancing rules for a switch in\n+ ``OVN_Northbound`` database that includes a L4 port\n+ *PORT* of protocol *P* and IP address\n+ *VIP*, a priority-120 flow is added. For IPv4 *VIPs*,\n+ the flow matches ``ct.new && ip && ip4.dst == VIP && reg1[16..23] == PROTO_NUM && reg1[0..15] == PORT``.\n+ For IPv6 *VIPs*,\n+ the flow matches ``ct.new && ip && ip6.dst == VIP && reg1[16..23] == PROTO_NUM && reg1[0..15] == PORT``.\n+ The flow's action is\n+ ``ct_lb_mark(args)``, where *args* contains comma separated IP addresses\n+ (and optional port numbers) to load balance to. The address family of\n+ the IP addresses of *args* is the same as the address family\n+ of *VIP*. If health check is enabled, then *args*\n+ will only contain those endpoints whose service monitor status entry\n+ in ``OVN_Southbound`` db is either ``online`` or\n+ empty. For IPv4 traffic the flow also loads the original destination\n+ IP and transport port in registers ``reg1`` and\n+ ``reg2``. For IPv6 traffic the flow also loads the original\n+ destination IP and transport port in registers ``xxreg1`` and\n+ ``reg2``.\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 ``install_ls_lb_from_router`` variable in\n+ ``NB_Global`` ``options`` is set to true.\n+\n+- For all the configured load balancing rules for a switch in\n+ ``OVN_Northbound`` database that includes just an IP address\n+ *VIP* to match on, OVN adds a priority-110 flow. For IPv4\n+ *VIPs*, the flow matches ``ct.new && ip && ip4.dst == VIP``.\n+ For IPv6 *VIPs*,\n+ the flow matches ``ct.new && ip && ip6.dst == VIP``.\n+ The action on this flow is\n+ ``ct_lb_mark(args)``, where *args* contains comma\n+ separated IP addresses of the same address family as *VIP*.\n+ For IPv4 traffic the flow also loads the original destination\n+ IP and transport port in registers ``reg1`` and\n+ ``reg2``. For IPv6 traffic the flow also loads the original\n+ destination IP and transport port in registers ``xxreg1`` and\n+ ``reg2``.\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 ``install_ls_lb_from_router`` variable in\n+ ``NB_Global`` ``options`` is set to true.\n+\n+- If the load balancer is created with ``--reject`` 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 ``--reject`` option will disable\n+ empty_lb SB controller event for this load balancer.\n+\n+Ingress Table 16: Load balancing affinity learn\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Load balancing affinity learn table contains the following\n+logical flows:\n+\n+- For all the configured load balancing rules for a switch in\n+ ``OVN_Northbound`` database where a positive affinity timeout\n+ *T* is specified in ``options`` column, that includes\n+ a L4 port *PORT* of protocol *P* and IP address\n+ *VIP*, a priority-100 flow is added. For IPv4 *VIPs*,\n+ the flow matches\n+ ``reg9[6] == 0 && ct.new && ip && ip4.dst == VIP && P.dst == PORT``.\n+ For IPv6 *VIPs*, the flow matches\n+ ``ct.new && ip && ip6.dst == VIP && P && P.dst == PORT``.\n+ The flow's action is\n+ ``commit_lb_aff(vip = VIP:PORT, backend = backend ip:backend port, proto = P, timeout = T);``.\n+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\n+Ingress Table 17: Pre-Hairpin\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- If the logical switch has load balancer(s) configured, then a\n+ priority-100 flow is added with the match\n+ ``ip && ct.trk`` 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+ ``reg0[6] = chk_lb_hairpin();`` and\n+ ``reg0[12] = chk_lb_hairpin_reply();`` and advances the packet\n+ to the next table.\n+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Ingress Table 18: Nat-Hairpin\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- If the logical switch has load balancer(s) configured, then a\n+ priority-100 flow is added with the match\n+ ``ip && ct.new && ct.trk && reg0[6] == 1`` which hairpins the\n+ traffic by NATting source IP to the load balancer VIP by executing\n+ the action ``ct_snat_to_vip`` and advances the packet to the\n+ next table.\n+\n+- If the logical switch has load balancer(s) configured, then a\n+ priority-100 flow is added with the match\n+ ``ip && ct.est && ct.trk && reg0[6] == 1`` which hairpins the\n+ traffic by NATting source IP to the load balancer VIP by executing\n+ the action ``ct_snat`` and advances the packet to the next\n+ table.\n+\n+- If the logical switch has load balancer(s) configured, then a\n+ priority-90 flow is added with the match\n+ ``ip && reg0[12] == 1`` 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 ``ct_snat`` and advances the\n+ packet to the next table.\n+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Ingress Table 19: Hairpin\n+~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- If logical switch has attached logical switch port of *vtep*\n+ type, then for each distributed gateway router port *RP*\n+ attached to this logical switch and has chassis redirect port\n+ *cr-RP*, a priority-2000 flow is added with the match::\n+\n+ reg0[14] == 1 && is_chassis_resident(cr-RP)\n+\n+ and action ``next;``.\n+\n+ ``reg0[14]`` register bit is set in the ingress L2 port\n+ security check table for traffic received from HW VTEP (ramp) ports.\n+\n+- If logical switch has attached logical switch port of *vtep*\n+ type, then a priority-1000 flow that matches on\n+ ``reg0[14]`` 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+\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+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Ingress table 20: ``from-lport`` ACL evaluation after LB\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Logical flows in this table closely reproduce those in the\n+``ACL eval`` table in the ``OVN_Northbound`` database\n+for the ``from-lport`` direction with the option\n+``apply-after-lb`` set to ``true``.\n+The ``priority`` values from the ``ACL`` 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 ``reg8[16]`` for\n+``allow-type`` ACLs, ``reg8[17]`` for ``drop``\n+ACLs, and ``reg8[17]`` for ``reject`` 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+\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+\n+- ``allow`` 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 ``allow`` ACLs also run\n+ ``ct_commit; next;`` (which acts as a hint for an upcoming\n+ table to commit the connection to conntrack). In case the\n+ ``ACL`` has a label then ``reg3`` is loaded with the\n+ label value and ``reg0[13]`` bit is set to 1 (which acts as a\n+ hint for the next tables to commit the label to conntrack).\n+\n+- ``allow-related`` apply-after-lb ACLs translate into logical\n+ flows that set the allow bit and run the\n+ ``ct_commit {ct_label=0/1; }; next;`` actions for new\n+ connections and ``reg0[1] = 1; next;`` for existing\n+ connections. In case the ``ACL`` has a label then\n+ ``reg3`` is loaded with the label value and\n+ ``reg0[13]`` bit is set to 1 (which acts as a hint for the\n+ next tables to commit the label to conntrack).\n+\n+- ``allow-stateless`` apply-after-lb ACLs translate into logical\n+ flows that set the allow bit and advance to the next table.\n+\n+- ``reject`` apply-after-lb ACLs translate into logical\n+ flows that set the reject bit and advance to the next table.\n+\n+- ``pass`` 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+\n+- Other apply-after-lb ACLs set the drop bit for new or untracked\n+ connections and ``ct_commit { ct_label=1/1; }`` for known\n+ connections. Setting ``ct_label`` marks a connection\n+ as one that was previously allowed, but should no longer be\n+ allowed due to a policy change.\n+\n+- One priority-65532 flow matching packets with ``reg0[17]``\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+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 21: ``from-lport`` ACL sampling after LB\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Logical flows in this table sample traffic matched by\n+``from-lport`` ACLs (evaluation after LB) with sampling enabled.\n+\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+\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 ``sample()`` action and then advances\n+ the packet to the next table.\n+\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 ``sample()`` action and then advances\n+ the packet to the next table.\n+\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 ``sample()`` 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+\n+Ingress Table 22: ``from-lport`` ACL action after LB\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- If no ACLs are configured, then a priority 0 flow is installed that\n+ matches everything and advances to the next table.\n+\n+- A priority 1000 flow is installed that will advance the packet to the\n+ next table if the allow bit is set.\n+\n+- A priority 1000 flow is installed that will run the ``drop;``\n+ action if the drop bit is set.\n+\n+- A priority 1000 flow is installed that will run the ``tcp_reset\n+ { output <-> inport; next(pipeline=egress,table=5);}``\n+ action for TCP connections, ``icmp4/icmp6`` action\n+ for UDP connections, and ``sctp_abort {output <-> inport;\n+ next(pipeline=egress,table=5);}`` action for SCTP associations.\n+\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+\n+Ingress Table 23: Pre Network Function\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This stage selects the active network function from a\n+``Network_Function_Group`` based on the network function group\n+ID set by the ACL eval stage earlier. This stage is applicable for\n+request packets of ``from-lport`` ACLs\n+(``reg8[22] == 1``). Response packets for\n+``to-lport`` ACLs bypass this stage and use\n+``ct_label.nf_id`` directly in the Network Function table.\n+\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 ``Network_Function_Health_Check``. This\n+stage selects one of the healthy network functions. If none are healthy,\n+the behavior follows the ``fallback`` column configured in the\n+``Network_Function_Group`` table. If health monitoring is not\n+configured, any one from the group is selected.\n+\n+When a request packet matches a ``from-lport`` ACL with\n+``network_function_group`` set, the ACL eval stage sets\n+``reg8[21] = 1`` (NF enabled), ``reg8[22] = 1``\n+(request direction), and ``reg0[22..29]`` to the network\n+function group ID. This table then selects the active network function\n+from the group and overwrites ``reg0[22..29]`` with the\n+specific ``id`` of a ``Network_Function`` 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+\n+- For each network_function_group *id* with an active network\n+ function, a priority-99 flow matches\n+ ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id`` and\n+ sets ``reg0[22..29] = nf_id; next;`` where\n+ *nf_id* is the ID of the active network function. This\n+ prepares request packets that matched a ``from-lport`` ACL\n+ with network_function_group for redirection in the subsequent Network\n+ Function table.\n+\n+- For each network function group with *id* that has\n+ ``fallback`` set to ``fail-open``, a priority-10 flow\n+ matches ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id``\n+ and sets ``reg8[21] = 0; reg0[22..29] = 0; next;``. This\n+ clears both the NF enabled bit and the NF group ID, allowing packets\n+ to continue processing through the pipeline without network function\n+ redirection when no active network function is available (fail-open\n+ behavior).\n+\n+- A priority-1 flow matches ``reg8[21] == 1 && reg8[22] == 1``\n+ and sets ``reg0[22..29] = 0; next;``. This is a\n+ catch-all flow for network function groups with ``fallback``\n+ set to ``fail-close`` (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+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Ingress Table 24: Stateful\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- A priority 100 flow is added which commits the packet to the conntrack\n+ and sets the most significant 32-bits of ``ct_label`` with the\n+ ``reg3`` value based on the hint provided by previous tables\n+ (with a match for ``reg0[1] == 1 && reg0[13] == 1``).\n+ This is used by the ``ACLs`` with label to commit the label\n+ value to conntrack.\n+\n+- For ``ACLs`` without label, a second priority-100 flow commits\n+ packets to connection tracker using ``ct_commit; next;``\n+ action based on a hint provided by the previous tables (with a match\n+ for ``reg0[1] == 1 && reg0[13] == 0``).\n+\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: ``reg8[21] == 1`` (packet matched an ACL with\n+ ``network_function_group`` set)\n+ Action: ``ct_label.nf = 1; ct_label.nf_id = reg0[22..29];``\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+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Ingress Table 25: Network Function\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table implements packet redirection to network functions. When a\n+packet matches an ACL with ``network_function_group`` column\n+set to the ``id`` of a ``Network_Function_Group``\n+table entry, the ACL eval stage sets ``reg8[21] = 1`` (NF\n+enabled), ``reg8[22] = 1`` (request direction), and\n+``reg0[22..29]`` to the network function group ID. The Pre\n+Network Function stage then selects the active network function from the\n+group and overwrites ``reg0[22..29]`` with the specific\n+``id`` of a ``Network_Function`` table entry. This\n+table uses that NF ID to redirect packets to the appropriate network\n+function port.\n+\n+This table handles request packets for ``from-lport`` ACLs\n+and response packets for ``to-lport`` ACLs. For\n+``from-lport`` ACLs, request packets are redirected to the\n+network function's ``inport``, and corresponding\n+response/related packets are handled in the egress pipeline. For\n+``to-lport`` 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+``ct_label.nf_id`` during request processing.\n+\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+\n+- For each network_function port *P*, a priority-100 flow is\n+ added that matches ``inport == P`` 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+ ``reg5[16..31] = ct_label.tun_if_id``. 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 ``Stateful`` table.\n+\n+- For each active network function with *id* that is referenced\n+ in a network function group, a priority-99 flow matches\n+ ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id`` and\n+ sets ``outport=P; output;`` where *P* is the\n+ ``inport`` of that network function. This redirects request\n+ packets for flows matching ``from-lport`` ACLs with\n+ network_function_group to the specific network function selected by\n+ the Pre Network Function stage.\n+\n+- For each active network function with *id* that is referenced\n+ in a network function group, a priority-99 rule matches\n+ ``reg8[21] == 1 && reg8[22] == 0 && ct_label.nf_id == id``\n+ and takes identical action as\n+ above. This redirects response and related packets for\n+ ``to-lport`` ACLs to the same network function that handled\n+ the request, using the NF ID stored in the connection tracking label.\n+\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+\n+- One priority-100 rule to skip redirection of multicast packets that hit\n+ a network_function ACL. Match on ``reg8[21] == 1 && eth.mcast``\n+ and action is to advance to the next table.\n+\n+- One priority-1 rule that checks ``reg8[21] == 1``, 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+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 26: ARP/ND responder\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\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+\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+\n+Note that ARP requests received from ``localnet`` 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+\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+\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 ``localnet`` advances directly to the next table.\n+ ARP requests sent to ``localnet`` 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+ ``router`` 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+\n+- If inport ``V`` is of type ``virtual`` adds a\n+ priority-100 logical flows for each *P* configured in the\n+ ``options:virtual-parents`` column with the match::\n+\n+ inport == P && && ((arp.op == 1 && arp.spa == VIP && arp.tpa == VIP) || (arp.op == 2 && arp.spa == VIP))\n+ inport == P && && ((nd_ns && ip6.dst == {VIP, NS_MULTICAST_ADDR} && nd.target == VIP) || (nd_na && nd.target == VIP))\n+\n+ and applies the action::\n+\n+ bind_vport(V, inport);\n+\n+ and advances the packet to the next table.\n+\n+ Where *VIP* is the virtual ip configured in the column\n+ ``options:virtual-ip`` and\n+ NS_MULTICAST_ADDR is solicited-node multicast address corresponding\n+ to the VIP.\n+\n+- Priority-50 flows that match only broadcast ARP requests to each\n+ known IPv4 address *A* of every logical switch port, and\n+ respond with ARP replies directly with corresponding Ethernet\n+ address *E*::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ arp.op = 2; /* ARP reply. */\n+ arp.tha = arp.sha;\n+ arp.sha = E;\n+ arp.tpa = arp.spa;\n+ arp.spa = A;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+\n+ These flows are omitted for logical ports (other than router ports or\n+ ``localport`` ports) that are down (unless\n+ ``ignore_lsp_down`` is configured as true in ``options``\n+ column of ``NB_Global`` table of the ``Northbound``\n+ database), for logical ports of type ``virtual``, for\n+ logical ports with 'unknown' address set, for logical ports with\n+ the ``options:disable_arp_nd_rsp=true`` and for logical\n+ ports of a logical switch configured with\n+ ``other_config:vlan-passthru=true``.\n+\n+ The above ARP responder flows are added for the list of IPv4 addresses\n+ if defined in ``options:arp_proxy`` column of\n+ ``Logical_Switch_Port`` table for logical switch ports of\n+ type ``router``.\n+\n+- Priority-50 flows that match IPv6 ND neighbor solicitations to\n+ each known IP address *A* (and *A*'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 *E*::\n+\n+ nd_na {\n+ eth.src = E;\n+ ip6.src = A;\n+ nd.target = A;\n+ nd.tll = E;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\n+ Priority-50 flows that match IPv6 ND neighbor solicitations to\n+ each known IP address *A* (and *A*'s\n+ solicited node address) of logical switch port of type router, and\n+ respond with neighbor advertisements directly with\n+ corresponding Ethernet address *E*::\n+\n+ nd_na_router {\n+ eth.src = E;\n+ ip6.src = A;\n+ nd.target = A;\n+ nd.tll = E;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\n+ These flows are omitted for logical ports (other than router ports or\n+ ``localport`` ports) that are down (unless\n+ ``ignore_lsp_down`` is configured as true in ``options``\n+ column of ``NB_Global`` table of the ``Northbound``\n+ database), for logical ports of type ``virtual`` and for\n+ logical ports with 'unknown' address set.\n+\n+ The above NDP responder flows are added for the list of\n+ IPv6 addresses if defined in ``options:arp_proxy`` column of\n+ ``Logical_Switch_Port`` table for logical switch ports of\n+ type ``router``.\n+\n+- Priority-100 flows with match criteria like the ARP and ND flows\n+ above, except that they only match packets from the\n+ ``inport`` that owns the IP addresses in question, with\n+ action ``next;``. 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+\n+ In place of ``next;``, it would be reasonable to use\n+ ``drop;`` 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+\n+- For each *SVC_MON_SRC_IP* defined in the value of\n+ the ``ip_port_mappings:ENDPOINT_IP`` column of\n+ ``Load_Balancer`` table, priority-110\n+ logical flow is added with the match\n+ ``arp.tpa == SVC_MON_SRC_IP && && arp.op == 1`` and applies\n+ the action::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ arp.op = 2; /* ARP reply. */\n+ arp.tha = arp.sha;\n+ arp.sha = E;\n+ arp.tpa = arp.spa;\n+ arp.spa = A;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+\n+ where *E* is the service monitor source mac defined in\n+ the ``options:svc_monitor_mac`` column in the ``NB_Global``\n+ 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+\n+ *SVC_MON_SRC_IP* is used as the source ip in the\n+ service monitor IPv4 packets for the load balancer endpoint IP\n+ health checks.\n+\n+ These flows are required if an ARP request is sent for the IP\n+ *SVC_MON_SRC_IP*.\n+\n+ For IPv6 the similar flow is added with the following action::\n+\n+ nd_na {\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip6.src = A;\n+ nd.target = A;\n+ nd.tll = E;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\n+- For each *VIP* configured in the table\n+ ``Forwarding_Group``\n+ a priority-50 logical flow is added with the match\n+ ``arp.tpa == vip && && arp.op == 1`` and applies the action::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ arp.op = 2; /* ARP reply. */\n+ arp.tha = arp.sha;\n+ arp.sha = E;\n+ arp.tpa = arp.spa;\n+ arp.spa = A;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+\n+ where *E* is the forwarding group's mac defined in\n+ the ``vmac`` column of ``Forwarding_Group``.\n+\n+ *A* 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+\n+ These flows are required to respond to an ARP request if an ARP\n+ request is sent for the IP *vip*.\n+\n+- One priority-0 fallback flow that matches all packets and advances to\n+ the next table.\n+\n+Ingress Table 27: DHCP option processing\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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 ``external``.\n+\n+- A priority-100 logical flow is added for these logical ports\n+ which matches the IPv4 packet with ``udp.src`` = 68 and\n+ ``udp.dst`` = 67 and applies the action\n+ ``put_dhcp_opts`` and advances the packet to the next table.\n+ ::\n+\n+ reg0[3] = put_dhcp_opts(offer_ip = ip, options...);\n+ next;\n+\n+ For DHCPDISCOVER and DHCPREQUEST, this transforms the packet into a\n+ DHCP reply, adds the DHCP offer IP *ip* 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+\n+- A priority-100 logical flow is added for these logical ports\n+ which matches the IPv6 packet with ``udp.src`` = 546 and\n+ ``udp.dst`` = 547 and applies the action\n+ ``put_dhcpv6_opts`` and advances the packet to the next\n+ table.\n+ ::\n+\n+ reg0[3] = put_dhcpv6_opts(ia_addr = ip, options...);\n+ next;\n+\n+ For DHCPv6 Solicit/Request/Confirm packets, this transforms the\n+ packet into a DHCPv6 Advertise/Reply, adds the DHCPv6 offer IP\n+ *ip* 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+\n+- A priority-0 flow that matches all packets to advances to table 16.\n+\n+Ingress Table 28: DHCP responses\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table implements DHCP responder for the DHCP replies generated by\n+the previous table.\n+\n+- A priority 100 logical flow is added for the logical ports configured\n+ with DHCPv4 options which matches IPv4 packets with ``udp.src == 68\n+ && udp.dst == 67 && reg0[3] == 1`` and\n+ responds back to the ``inport`` after applying these\n+ actions. If ``reg0[3]`` is set to 1, it means that the\n+ action ``put_dhcp_opts`` was successful.\n+ ::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip4.src = S;\n+ udp.src = 67;\n+ udp.dst = 68;\n+ outport = P;\n+ flags.loopback = 1;\n+ output;\n+\n+ where *E* is the server MAC address and *S* is the\n+ server IPv4 address defined in the DHCPv4 options. Note that\n+ ``ip4.dst`` field is handled by ``put_dhcp_opts``.\n+\n+ (This terminates ingress packet processing; the packet does not go\n+ to the next ingress table.)\n+\n+- A priority 100 logical flow is added for the logical ports configured\n+ with DHCPv6 options which matches IPv6 packets with ``udp.src == 546\n+ && udp.dst == 547 && reg0[3] == 1`` and\n+ responds back to the ``inport`` after applying these\n+ actions. If ``reg0[3]`` is set to 1, it means that the\n+ action ``put_dhcpv6_opts`` was successful.\n+ ::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip6.dst = A;\n+ ip6.src = S;\n+ udp.src = 547;\n+ udp.dst = 546;\n+ outport = P;\n+ flags.loopback = 1;\n+ output;\n+\n+ where *E* is the server MAC address and *S* is the\n+ server IPv6 LLA address generated from the ``server_id``\n+ defined in the DHCPv6 options and *A* is\n+ the IPv6 address defined in the logical port's addresses column.\n+\n+ (This terminates packet processing; the packet does not go on the\n+ next ingress table.)\n+\n+- A priority-0 flow that matches all packets to advances to table 17.\n+\n+Ingress Table 29 DNS Lookup\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table looks up and resolves the DNS names to the corresponding\n+configured IP address(es).\n+\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 ``udp.dst`` = 53 and applies the action\n+ ``dns_lookup`` and advances the packet to the next table.\n+ ::\n+\n+ reg0[4] = dns_lookup(); next;\n+\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+\n+Ingress Table 30 DNS Responses\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table implements DNS responder for the DNS replies generated by\n+the previous table.\n+\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 ``udp.dst = 53 && reg0[4] == 1``\n+ and responds back to the ``inport`` after applying these\n+ actions. If ``reg0[4]`` is set to 1, it means that the\n+ action ``dns_lookup`` was successful.\n+ ::\n+\n+ eth.dst <-> eth.src;\n+ ip4.src <-> ip4.dst;\n+ udp.dst = udp.src;\n+ udp.src = 53;\n+ outport = P;\n+ flags.loopback = 1;\n+ output;\n+\n+ (This terminates ingress packet processing; the packet does not go\n+ to the next ingress table.)\n+\n+Ingress table 31 External ports\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Traffic from the ``external`` logical ports enter the ingress\n+datapath pipeline via the ``localnet`` port. This table adds the\n+below logical flows to handle the traffic from these ports.\n+\n+- A priority-100 flow is added for each ``external`` 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 ``inport`` of the ``external`` logical port\n+ and the valid ``eth.src`` address(es) of the\n+ ``external`` logical port.\n+\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+\n+ A priority-100 flow is added for each ``external`` logical\n+ port which doesn't reside on a chassis to drop any packet destined\n+ to the router mac - with the match\n+ ``inport == external && eth.src == E && eth.dst == R && !is_chassis_resident(\"external\")``\n+ where *E* is the external port mac and *R* is the\n+ router port mac.\n+\n+- A priority-0 flow that matches all packets to advances to table 20.\n+\n+Ingress Table 32 Destination Lookup\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table implements switching behavior. It contains these logical\n+flows:\n+\n+- A priority-110 flow with the match\n+ ``eth.src == E`` for all logical switch\n+ datapaths and applies the action ``handle_svc_check(inport)``.\n+ Where *E* is the service monitor mac defined in the\n+ ``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+- A priority-100 flow that punts all IGMP/MLD packets to\n+ ``ovn-controller`` if multicast snooping is enabled on the\n+ logical switch.\n+\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+\n+- A priority-100 flow that matches ``reg8[23] == 1`` and does\n+ ``output`` action. This ensures that packets that got injected\n+ back into this table from egress table ``Network Function``\n+ (after it set the ``outport`` for packet redirection) get\n+ forwarded without any further processing.\n+\n+- For any logical port that's defined as a target of routing protocol\n+ redirecting (via ``routing-protocol-redirect`` option set on\n+ Logical Router Port), we redirect the traffic related to protocols\n+ specified in ``routing-protocols`` option. It's acoomplished\n+ with following priority-100 flows:\n+\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+\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+\n+ In addition to this, we add priority-100 rules that\n+ ``clone`` 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+\n+- Priority-90 flows for transit switches that forward registered\n+ IP multicast traffic to their corresponding multicast group , which\n+ ``ovn-northd`` creates based on learnt\n+ ``IGMP_Group`` entries.\n+\n+- Priority-90 flows that forward registered IP multicast traffic to\n+ their corresponding multicast group, which ``ovn-northd``\n+ creates based on learnt ``IGMP_Group``\n+ entries. The flows also forward packets to the\n+ ``MC_MROUTER_FLOOD`` multicast group, which\n+ ``ovn-nortdh`` populates with all the logical ports that\n+ are connected to logical routers with\n+ ``options``:mcast_relay='true'.\n+\n+- A priority-85 flow that forwards all IP multicast traffic destined to\n+ 224.0.0.X to the ``MC_FLOOD_L2`` multicast group, which\n+ ``ovn-northd`` populates with all non-router logical ports.\n+\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 ``MC_FLOOD`` multicast\n+ group, which ``ovn-northd`` populates with all enabled\n+ logical ports.\n+\n+- A priority-80 flow that forwards all unregistered IP multicast traffic\n+ to the ``MC_STATIC`` multicast group, which\n+ ``ovn-northd`` populates with all the logical ports that\n+ have ``options``\n+ ``:mcast_flood='true'``. The flow also forwards\n+ unregistered IP multicast traffic to the ``MC_MROUTER_FLOOD``\n+ multicast group, which ``ovn-northd`` populates with all the\n+ logical ports connected to logical routers that have\n+ ``options``\n+ ``:mcast_relay='true'``.\n+\n+- A priority-80 flow that drops all unregistered IP multicast traffic\n+ if ``other_config``\n+ ``:mcast_snoop='true'`` and\n+ ``other_config``\n+ ``:mcast_flood_unregistered='false'`` and the switch is\n+ not connected to a logical router that has\n+ ``options``\n+ ``:mcast_relay='true'`` and the switch doesn't have any\n+ logical port with ``options``\n+ ``:mcast_flood='true'``.\n+\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+ ``MC_FLOOD_L2`` multicast group which contains all non-router\n+ logical ports.\n+\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 ``MC_FLOOD_L2`` which contains all\n+ non-router logical ports.\n+\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 ``eth.dst`` to the\n+ ``MC_FLOOD`` 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+\n+- A priority-72 flow that outputs all ARP requests and ND NS (Neighbor\n+ Solicitation) packets with an Ethernet broadcast or multicast\n+ ``eth.dst`` to the ``MC_FLOOD_L2`` multicast group\n+ if ``other_config:broadcast-arps-to-all-routers=false``.\n+\n+- A priority-71 flow that outputs all ARP packets with an Ethernet\n+ broadcast or multicast ``eth.dst`` to the\n+ ``MC_FLOOD`` multicast group.\n+\n+- A priority-71 flow that outputs all IP packets with an Ethernet\n+ broadcast or multicast ``eth.dst`` to the\n+ ``MC_FLOOD_L2`` multicast group, which contains only\n+ non-router logical ports. If any connected router has\n+ ``options:mcast_relay=true``, the packet is also cloned to\n+ the ``MC_MROUTER_FLOOD`` multicast group (which contains\n+ only the router ports with relay enabled). If any port has\n+ ``options:mcast_flood=true``, it is also cloned to the\n+ ``MC_STATIC`` multicast group. This prevents IP multicast\n+ from being unnecessarily forwarded to routers that would drop it.\n+\n+- A priority-70 flow that outputs all packets with an Ethernet broadcast\n+ or multicast ``eth.dst`` to the ``MC_FLOOD_L2``\n+ multicast group.\n+\n+- One priority-50 flow that matches each known Ethernet address against\n+ ``eth.dst``. Action of this flow outputs the packet to the\n+ single associated output port if it is enabled. ``drop;``\n+ action is applied if LSP is disabled. If the logical switch port\n+ of type VIF has the option ``options:pkt_clone_type``\n+ is set to the value ``mc_unknown``, then the packet is\n+ also forwarded to the ``MC_UNKNOWN`` multicast group.\n+\n+ The above flow is not added if the logical switch port is of type\n+ VIF, has ``unknown`` as one of its address and has the\n+ option ``options:force_fdb_lookup`` set to true.\n+\n+ For the Ethernet address on a logical switch port of type\n+ ``router``, when that logical switch port's\n+ ``addresses`` column is set to ``router`` and\n+ the connected logical router port has a gateway chassis:\n+\n+ - The flow for the connected logical router port's Ethernet\n+ address is only programmed on the gateway chassis.\n+\n+ - If the logical router has rules specified in\n+ ``nat`` with\n+ ``external_mac``, then\n+ those addresses are also used to populate the switch's destination\n+ lookup on the chassis where\n+ ``logical_port`` is\n+ resident.\n+\n+ For the Ethernet address on a logical switch port of type\n+ ``router``, when that logical switch port's\n+ ``addresses`` column is set to ``router`` and\n+ the connected logical router port specifies a\n+ ``reside-on-redirect-chassis`` and the logical router\n+ to which the connected logical router port belongs to has a\n+ distributed gateway LRP:\n+\n+ - The flow for the connected logical router port's Ethernet\n+ address is only programmed on the gateway chassis.\n+\n+ For each forwarding group configured on the logical switch datapath,\n+ a priority-50 flow that matches on ``eth.dst == VIP``\n+ with an action of ``fwd_group(childports=args)``,\n+ where *args* contains comma separated\n+ logical switch child ports to load balance to.\n+ If ``liveness`` is enabled, then action also includes\n+ ``liveness=true``.\n+\n+- One priority-0 fallback flow that matches all packets with the\n+ action ``outport = get_fdb(eth.dst); next;``. The action\n+ ``get_fdb`` gets the port for the ``eth.dst``\n+ in the MAC learning table of the logical switch datapath. If there\n+ is no entry for ``eth.dst`` in the MAC learning table,\n+ then it stores ``none`` in the ``outport``.\n+\n+Ingress Table 33 Destination unknown\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- Priority 50 flow with the match ``outport == P``\n+ is added for each disabled Logical Switch Port ``P``. This\n+ flow has action ``drop;``.\n+\n+- If the logical switch has logical ports with 'unknown' addresses set,\n+ then the below logical flow is added\n+\n+ - Priority 50 flow with the match ``outport == \"none\"`` then\n+ outputs them to the ``MC_UNKNOWN`` multicast group, which\n+ ``ovn-northd`` 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+ ``ovn-northd`` omits this multicast group and logical\n+ flow.\n+\n+ If the logical switch has no logical ports with 'unknown' address\n+ set, then the below logical flow is added\n+\n+ - Priority 50 flow with the match ``outport == none``\n+ and drops the packets.\n+\n+- One priority-0 fallback flow that outputs the packet to the egress\n+ stage with the outport learnt from ``get_fdb`` action.\n+\n+Egress Table 0: Lookup MAC address learning table\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``Lookup MAC address learning table``\n+with the difference that MAC address learning lookup is only\n+happening for ports with type ``remote`` 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+\n+Egress Table 1: Learn MAC of 'unknown' ports.\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``Learn MAC of 'unknown' ports``\n+with the difference that MAC address learning is only happening\n+for ports with type ``remote`` 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+\n+Egress Table 2: ``to-lport`` Pre-ACLs\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``Pre-ACLs`` except for\n+``to-lport`` traffic.\n+\n+This table also has a priority-110 flow with the match\n+``eth.src == E`` for all logical switch\n+datapaths to move traffic to the next table. Where *E*\n+is the service monitor mac defined in the\n+``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+This table also has a priority-110 flow with the match\n+``outport == I`` for all logical switch\n+datapaths to move traffic to the next table. Where *I*\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+\n+This table also has a priority-110 flow for each network_function\n+``inport`` *P* that matches ``inport == P``.\n+The action is to skip all the egress tables up to\n+the ``Network Function`` table and advance the packet directly\n+to the table after that. This is for the case where packet redirection\n+happens in egress ``Network Function`` 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+\n+Egress Table 3: Pre-LB\n+~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table is similar to ingress table ``Pre-LB``. 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 ``ip`` and action of ``reg0[2] = 1; next;``\n+to act as a hint for table ``Pre-stateful`` 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+\n+This table also has a priority-110 flow with the match\n+``eth.src == E`` for all logical switch\n+datapaths to move traffic to the next table. Where *E*\n+is the service monitor mac defined in the\n+``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+\n+This table also has a priority-110 flow with the match\n+``outport == I`` 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 *I*\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+\n+When ``enable-stateless-acl-with-lb`` is enabled,\n+additional priority-115 flow is added to match traffic with\n+``REGBIT_ACL_STATELESS`` set and pass connection tracking.\n+\n+Egress Table 4: Pre-stateful\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``Pre-stateful``. This table\n+adds the below 3 logical flows.\n+\n+- A Priority-120 flow that send the packets to connection tracker using\n+ ``ct_lb_mark;`` 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 ``reg0[2] == 1``. If the packet was not DNATted earlier,\n+ then ``ct_lb_mark`` functions like ``ct_next``.\n+\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 ``reg0[0] == 1``) by using the\n+ ``ct_next;`` action.\n+\n+- A priority-0 flow that matches all packets to advance to the next\n+ table.\n+\n+Egress Table 5: ``from-lport`` ACL hints\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``ACL hints``.\n+\n+Egress Table 6: ``to-lport`` ACL evaluation\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``ACL eval`` except for\n+``to-lport`` ACLs. As a reminder, these flows use the\n+following register bits to indicate their verdicts.\n+``Allow-type`` ACLs set ``reg8[16]``, ``drop``\n+ACLs set ``reg8[17]``, and ``reject`` ACLs set\n+``reg8[18]``.\n+\n+Also like with ingress ACLs, egress ACLs can have network_function_group\n+*id* and in that case the flow will set ``reg8[21] = 1;\n+reg8[22] = 1; reg0[22..29] = id``. These registers are used\n+in the ``Network Function`` table.\n+\n+Also like with ingress ACLs, egress ACLs can have a configured\n+``tier``. 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+``reg8[30..31]``.\n+\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+\n+In addition, the following flows are added.\n+\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\n+ has DHCPv6 options defined to allow the DHCPv6 reply packet from the\n+ ``Ingress Table 26: DHCP responses``. This is indicated by\n+ setting the allow bit.\n+\n+- A priority 34000 logical flow is added for each logical switch datapath\n+ configured with DNS records with the match ``udp.dst = 53``\n+ to allow the DNS reply packet from the\n+ ``Ingress Table 28: DNS responses``. This is indicated by\n+ setting the allow bit.\n+\n+- A priority 34000 logical flow is added for each logical switch datapath\n+ with the match ``eth.src = E`` to allow the service\n+ monitor request packet generated by ``ovn-controller``\n+ with the action ``next``, where *E* is the\n+ service monitor mac defined in the\n+ ``options:svc_monitor_mac`` column of ``NB_Global`` table.\n+ This is indicated by setting the allow bit.\n+\n+Egress Table 7: ``to-lport`` ACL sampling\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``ACL sampling``.\n+\n+Egress Table 8: ``to-lport`` ACL action\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``ACL action``.\n+\n+Egress Table 9: Mirror\n+~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Overlay remote mirror table contains the following\n+logical flows:\n+\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+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\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+\n+Egress Table 10: ``to-lport`` QoS\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``QoS`` except\n+they apply to ``to-lport`` QoS rules.\n+\n+Egress Table 11: Pre Network Function\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This stage selects the active network function from a\n+``Network_Function_Group`` based on the network function group\n+ID set by the ACL eval stage earlier. This stage is applicable for\n+request packets of ``to-lport`` ACLs\n+(``reg8[22] == 1``). Response packets for\n+``from-lport`` ACLs bypass this stage and use\n+``ct_label.nf_id`` directly in the Network Function table.\n+\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 ``Network_Function_Health_Check``. This\n+stage selects one of the healthy network functions. If none are healthy,\n+the behavior follows the ``fallback`` column configured in the\n+``Network_Function_Group`` table. If health monitoring is not\n+configured, any one from the group is selected.\n+\n+When a request packet matches a ``to-lport`` ACL with\n+``network_function_group`` set, the ACL eval stage sets\n+``reg8[21] = 1`` (NF enabled), ``reg8[22] = 1``\n+(request direction), and ``reg0[22..29]`` to the network\n+function group ID. This table then selects the active network function\n+from the group and overwrites ``reg0[22..29]`` with the\n+specific ``id`` of a ``Network_Function`` 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+\n+- For each network function group with *id* that has an active\n+ network function, a priority-99 flow matches\n+ ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id``\n+ and sets ``reg0[22..29] = nf_id; next;`` where\n+ *nf_id* is the ``id`` of the active\n+ ``Network_Function`` selected from the group. This prepares\n+ request packets that matched a ``to-lport`` ACL with\n+ network_function_group for redirection in the subsequent Network\n+ Function table.\n+\n+- For each network function group with *id* that has\n+ ``fallback`` set to ``fail-open``, a priority-10 flow\n+ matches ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id``\n+ and sets ``reg8[21] = 0; reg0[22..29] = 0; next;``. This\n+ clears both the NF enabled bit and the NF group ID, allowing packets\n+ to continue processing through the pipeline without network function\n+ redirection when no active network function is available (fail-open\n+ behavior).\n+\n+- A priority-1 flow matches ``reg8[21] == 1 && reg8[22] == 1``\n+ and sets ``reg0[22..29] = 0; next;``. This is a\n+ catch-all flow for network function groups with ``fallback``\n+ set to ``fail-close`` (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+\n+- A priority-0 flow that simply moves traffic to the next table.\n+\n+Egress Table 12: Stateful\n+~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to ingress table ``Stateful`` except that\n+there are no rules added for load balancing new connections.\n+When ``enable-stateless-acl-with-lb`` is enabled, new\n+stateless connections bypass connection tracking.\n+\n+- A priority 120 flow is added for each network function port\n+ *P* that is identical to the priority 100 flow except for\n+ additional match ``outport == P`` and additional\n+ action ``ct_label.tun_if_id = reg5[16..31]``. 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+\n+Egress Table 13: Network Function\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table handles request packets for ``to-lport`` ACLs\n+and response packets for ``from-lport`` ACLs. For\n+``to-lport`` ACLs, request packets are redirected to the\n+network function's ``outport``, and corresponding\n+response/related packets are handled in the ingress pipeline. For\n+``from-lport`` 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+``ct_label.nf_id`` during request processing.\n+\n+- Similar to ingress ``Network Function`` 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+\n+- For each active network function with *id* that is\n+ referenced in a network function group, a priority-99 flow matches\n+ ``reg8[21] == 1 && reg8[22] == 1 && reg0[22..29] == id`` and\n+ sets\n+ ``outport=P; reg8[23] = 1; next(pipeline=ingress, table=T)``\n+ where *P* is the\n+ ``outport`` of that network function and *T* is\n+ the ingress table ``Destination Lookup``. This redirects\n+ request packets matching ``to-lport`` 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 ``reg8[23]``.\n+\n+- For each active network function with *id* that is referenced\n+ in a network function group, a priority-99 rule matches\n+ ``reg8[21] == 1 && reg8[22] == 0 && ct_label.nf_id == id``\n+ and takes identical action as\n+ above. This redirects response and related packets for\n+ ``from-lport`` ACLs to the same network function that handled\n+ the request, using the NF ID stored in the connection tracking label.\n+\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+\n+- One priority-100 multicast match flow same as\n+ ingress ``Network Function``.\n+\n+- One priority-1 flow same as ingress ``Network Function``.\n+\n+- One priority-0 flow same as ingress ``Network Function``.\n+\n+Egress Table 14: Egress Port Security - check\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to the port security logic in table\n+``Ingress Port Security check`` except that action\n+``check_out_port_sec`` is used to check the port security\n+rules. This table adds the below logical flows.\n+\n+- A priority 100 flow which matches on the multicast traffic and applies\n+ the action ``REGBIT_PORT_SEC_DROP\" = 0; next;\"`` to skip\n+ the out port security checks.\n+\n+- A priority 0 logical flow is added which matches on all the packets\n+ and applies the action\n+ ``REGBIT_PORT_SEC_DROP\" = check_out_port_sec(); next;\"``.\n+ The action ``check_out_port_sec`` applies the port security\n+ rules based on the addresses defined in the\n+ ``port_security`` column of ``Logical_Switch_Port``\n+ table before delivering the packet to the ``outport``.\n+\n+Egress Table 15: Egress Port Security - Apply\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This is similar to the ingress port security logic in ingress table\n+``A Ingress Port Security - Apply``. This table drops the\n+packets if the port security check failed in the previous stage i.e\n+the register bit ``REGBIT_PORT_SEC_DROP`` is set to 1.\n+\n+The following flows are added.\n+\n+- For each port configured with egress qos in the\n+ ``options:qdisc_queue_id`` column of ``Logical_Switch_Port``,\n+ running a localnet port on the same logical\n+ switch, a priority 110 flow is added which matches on the localnet\n+ ``outport`` and on the port ``inport`` and\n+ applies the action ``set_queue(id); output;\"``.\n+\n+- For each localnet port configured with egress qos in the\n+ ``options:qdisc_queue_id`` column of ``Logical_Switch_Port``,\n+ a priority 100 flow is added which\n+ matches on the localnet ``outport`` and applies the action\n+ ``set_queue(id); output;\"``.\n+\n+ Please remember to mark the corresponding physical interface with\n+ ``ovn-egress-iface`` set to true in\n+ ``external_ids`` of ``Interface``.\n+\n+- A priority-50 flow that drops the packet if the register\n+ bit ``REGBIT_PORT_SEC_DROP`` is set to 1.\n+\n+- A priority-0 flow that outputs the packet to the ``outport``.\n+\n+Logical Router Datapaths\n+------------------------\n+\n+Logical router datapaths will only exist for ``Logical_Router``\n+rows in the OVN Northbound database\n+that do not have ``enabled`` set to ``false``\n+\n+Ingress Table 0: L2 Admission Control\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- Priority-100 flows to drop packets with VLAN tags or multicast Ethernet\n+ source addresses.\n+\n+- For each enabled router port *P* with Ethernet address\n+ *E*, a priority-50 flow that matches ``inport == P && (eth.mcast || eth.dst == E``),\n+ stores the router port ethernet address\n+ and advances to next table, with action\n+ ``xreg0[0..47]=E; next;``.\n+\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+ ``eth.dst == E`` is only programmed on\n+ the gateway port instance on the gateway chassis.\n+ If LRP's logical switch has attached LSP of ``vtep`` type,\n+ the ``is_chassis_resident()`` part is not added to lflow to\n+ allow traffic originated from logical switch to reach LR services\n+ (LBs, NAT).\n+\n+ For each gateway port *GW* on a distributed logical router\n+ a priority-120 flow that matches 'recirculated' icmp{4,6} error\n+ 'packet too big' and ``eth.dst == D && !is_chassis_resident(cr-GW)``\n+ where *D*\n+ is the gateway port mac address and *cr-GW* is the chassis\n+ resident port of *GW*, swap inport and outport and stores\n+ *GW* as inport.\n+\n+ This table adds a priority-105 flow that matches 'recirculated'\n+ icmp{4,6} error 'packet too big' to drop the packet.\n+\n+ For unicast L2 traffic on a distributed logical router or for\n+ gateway router where the port is configured with\n+ ``options:gateway_mtu`` the action of the above flow\n+ is modified adding ``check_pkt_larger`` in order to mark\n+ the packet setting ``REGBIT_PKT_LARGER`` if the size is\n+ greater than the MTU.\n+\n+ If the port is also configured with\n+ ``options:gateway_mtu_bypass`` then another flow is\n+ added, with priority-55, to bypass the ``check_pkt_larger``\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+\n+- For each ``dnat_and_snat`` NAT rule on a distributed\n+ router that specifies an external Ethernet address *E*,\n+ a priority-50 flow that matches ``inport == GW && eth.dst == E``,\n+ where *GW*\n+ is the logical router distributed gateway port corresponding to the\n+ NAT rule (specified or inferred), with action\n+ ``xreg0[0..47]=E; next;``.\n+\n+ This flow is only programmed on the gateway port instance on\n+ the chassis where the ``logical_port`` specified in\n+ the NAT rule resides.\n+\n+- A priority-0 logical flow that matches all packets not already handled\n+ (match ``1``) and drops them (action ``drop;``).\n+\n+Other packets are implicitly dropped.\n+\n+Ingress Table 1: Neighbor lookup\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For ARP and IPv6 Neighbor Discovery packets, this table looks into the\n+``MAC_Binding`` records to determine\n+if OVN needs to learn the mac bindings. Following flows are added:\n+\n+- For each router port *P* that owns IP address *A*,\n+ which belongs to subnet *S* with prefix length *L*,\n+ if the option ``always_learn_from_arp_request`` is\n+ ``true`` for this router, a priority-100 flow is added which\n+ matches ``inport == P && arp.spa == S/L && arp.op == 1``\n+ (ARP request) with the following actions::\n+\n+ reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+ next;\n+\n+ If the option ``always_learn_from_arp_request`` is\n+ ``false``, the following two flows are added.\n+\n+ A priority-110 flow is added which matches ``inport == P && arp.spa == S/L && arp.tpa == A && arp.op == 1``\n+ (ARP request) with the following actions::\n+\n+ reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+ reg9[3] = 1;\n+ next;\n+\n+ A priority-100 flow is added which matches ``inport == P && arp.spa == S/L && arp.op == 1``\n+ (ARP request) with the following actions::\n+\n+ reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+ reg9[3] = lookup_arp_ip(inport, arp.spa);\n+ next;\n+\n+ If the logical router port *P* is a distributed gateway\n+ router port, additional match\n+ ``is_chassis_resident(cr-P)`` is added for all\n+ these flows.\n+\n+- A priority-100 flow which matches on ARP reply packets and applies\n+ the actions if the option ``always_learn_from_arp_request``\n+ is ``true``::\n+\n+ reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+ next;\n+\n+ If the option ``always_learn_from_arp_request``\n+ is ``false``, the above actions will be::\n+\n+ reg9[2] = lookup_arp(inport, arp.spa, arp.sha);\n+ reg9[3] = 1;\n+ next;\n+\n+- A priority-100 flow which matches on IPv6 Neighbor Discovery\n+ advertisement packet and applies the actions if the option\n+ ``always_learn_from_arp_request`` is ``true``::\n+\n+ reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n+ next;\n+\n+ If the option ``always_learn_from_arp_request``\n+ is ``false``, the above actions will be::\n+\n+ reg9[2] = lookup_nd(inport, nd.target, nd.tll);\n+ reg9[3] = 1;\n+ next;\n+\n+- A priority-100 flow which matches on IPv6 Neighbor Discovery\n+ solicitation packet and applies the actions if the option\n+ ``always_learn_from_arp_request`` is ``true``::\n+\n+ reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n+ next;\n+\n+ If the option ``always_learn_from_arp_request``\n+ is ``false``, the above actions will be::\n+\n+ reg9[2] = lookup_nd(inport, ip6.src, nd.sll);\n+ reg9[3] = lookup_nd_ip(inport, ip6.src);\n+ next;\n+\n+- A priority-0 fallback flow that matches all packets and applies\n+ the action ``reg9[2] = 1; next;``\n+ advancing the packet to the next table.\n+\n+Ingress Table 2: Neighbor learning\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+reg9[2] will be ``1`` if the ``lookup_arp/lookup_nd``\n+in the previous table was successful or skipped, meaning no need\n+to learn mac binding from the packet.\n+\n+reg9[3] will be ``1`` if the\n+``lookup_arp_ip/lookup_nd_ip`` 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+\n+- A priority-100 flow with the match ``reg9[2] == 1 || reg9[3] ==\n+ 0`` and advances the packet to the next table as there is no need\n+ to learn the neighbor.\n+\n+- A priority-95 flow with the match ``nd_ns && (ip6.src == 0 || nd.sll == 0)``\n+ and applies the action ``next;``\n+\n+- A priority-90 flow with the match ``arp`` and\n+ applies the action\n+ ``put_arp(inport, arp.spa, arp.sha); next;``\n+\n+- A priority-95 flow with the match ``nd_na && nd.tll == 0``\n+ and applies the action\n+ ``put_nd(inport, nd.target, eth.src); next;``\n+\n+- A priority-90 flow with the match ``nd_na`` and\n+ applies the action\n+ ``put_nd(inport, nd.target, nd.tll); next;``\n+\n+- A priority-90 flow with the match ``nd_ns`` and\n+ applies the action\n+ ``put_nd(inport, ip6.src, nd.sll); next;``\n+\n+- A priority-0 logical flow that matches all packets not already handled\n+ (match ``1``) and drops them (action ``drop;``).\n+\n+Ingress Table 3: IP Input\n+~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- For each ``dnat_and_snat`` NAT rule on a distributed\n+ logical routers or gateway routers with gateway port\n+ configured with ``options:gateway_mtu`` to a valid integer\n+ value *M*, a priority-160 flow with the match\n+ ``inport == LRP && REGBIT_PKT_LARGER && REGBIT_EGRESS_LOOPBACK == 0``,\n+ where *LRP* is the logical router port and applies the\n+ following action for ipv4 and ipv6 respectively::\n+\n+ icmp4_error {\n+ icmp4.type = 3; /* Destination Unreachable. */\n+ icmp4.code = 4; /* Frag Needed and DF was Set. */\n+ icmp4.frag_mtu = M;\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip4.dst = ip4.src;\n+ ip4.src = I;\n+ ip.ttl = 255;\n+ REGBIT_EGRESS_LOOPBACK = 1;\n+ REGBIT_PKT_LARGER 0;\n+ outport = LRP;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\n+ icmp6_error {\n+ icmp6.type = 2;\n+ icmp6.code = 0;\n+ icmp6.frag_mtu = M;\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip6.dst = ip6.src;\n+ ip6.src = I;\n+ ip.ttl = 255;\n+ REGBIT_EGRESS_LOOPBACK = 1;\n+ REGBIT_PKT_LARGER 0;\n+ outport = LRP;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\n+ where *E* and *I* are the NAT rule external mac\n+ and IP respectively.\n+\n+- For distributed logical routers or gateway routers with gateway port\n+ configured with ``options:gateway_mtu`` to a valid integer\n+ value, a priority-150 flow with the match\n+ ``inport == LRP && REGBIT_PKT_LARGER && REGBIT_EGRESS_LOOPBACK == 0``,\n+ where *LRP* is the logical router port and applies the\n+ following action for ipv4 and ipv6 respectively::\n+\n+ icmp4_error {\n+ icmp4.type = 3; /* Destination Unreachable. */\n+ icmp4.code = 4; /* Frag Needed and DF was Set. */\n+ icmp4.frag_mtu = M;\n+ eth.dst = E;\n+ ip4.dst = ip4.src;\n+ ip4.src = I;\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 = M;\n+ eth.dst = E;\n+ ip6.dst = ip6.src;\n+ ip6.src = I;\n+ ip.ttl = 255;\n+ REGBIT_EGRESS_LOOPBACK = 1;\n+ REGBIT_PKT_LARGER 0;\n+ next(pipeline=ingress, table=0);\n+ };\n+\n+- For each NAT entry of a distributed logical router (with\n+ distributed gateway router port(s)) of type ``snat``,\n+ a priority-120 flow with the match ``inport == P && ip4.src == A``\n+ advances the packet to the next pipeline, where *P* is the\n+ distributed logical router port corresponding to the NAT entry\n+ (specified or inferred) and *A* is the ``external_ip`` set\n+ in the NAT entry. If *A* is an IPv6 address, then\n+ ``ip6.src`` is used for the match.\n+\n+ The above flow is required to handle the routing of the East/west NAT\n+ traffic.\n+\n+- For each BFD port the two following priority-110 flows are added\n+ to manage BFD traffic:\n+\n+ - if ``ip4.src`` or ``ip6.src`` is any IP\n+ address owned by the router port and ``udp.dst == 3784``,\n+ the packet is advanced to the next pipeline stage.\n+\n+ - if ``ip4.dst`` or ``ip6.dst`` is any IP\n+ address owned by the router port and ``udp.dst == 3784``,\n+ the ``handle_bfd_msg`` action is executed.\n+\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+ - if ``inport`` is lrp and ``ip4.src == 0.0.0.0``\n+ and ``ip4.dst == 255.255.255.255`` and\n+ ``ip4.frag == 0`` and ``udp.src == 68``\n+ and ``udp.dst == 67``, the ``dhcp_relay_req_chk``\n+ action is executed.\n+ ::\n+\n+ reg9[7] = dhcp_relay_req_chk(lrp_ip, dhcp_server_ip);next\n+\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+\n+ - if ``ip4.src`` is DHCP server ip and ``ip4.dst``\n+ is lrp IP and ``udp.src == 67`` and\n+ ``udp.dst == 67``, the packet is advanced to the next\n+ pipeline stage.\n+\n+- L3 admission control: Priority-120 flows allows IGMP and MLD packets\n+ if the router has logical ports that have\n+ ``options``:mcast_flood='true'.\n+\n+- L3 admission control: A priority-100 flow drops packets that match\n+ any of the following:\n+\n+ - ``ip4.src[28..31] == 0xe`` (multicast source)\n+\n+ - ``ip4.src == 255.255.255.255`` (broadcast source)\n+\n+ - ``ip4.src == 127.0.0.0/8 || ip4.dst == 127.0.0.0/8``\n+ (localhost source or destination)\n+\n+ - ``ip4.src == 0.0.0.0/8 || ip4.dst == 0.0.0.0/8`` (zero\n+ network source or destination)\n+\n+ - ``ip4.src`` or ``ip6.src`` is any IP\n+ address owned by the router, unless the packet was recirculated\n+ due to egress loopback as indicated by\n+ ``REGBIT_EGRESS_LOOPBACK``.\n+\n+ - ``ip4.src`` is the broadcast address of any IP network\n+ known to the router.\n+\n+- A priority-100 flow parses DHCPv6 replies from IPv6 prefix\n+ delegation routers (``udp.src == 547 && udp.dst == 546``).\n+ The ``handle_dhcpv6_reply`` is used to send IPv6 prefix\n+ delegation messages to the delegation router.\n+\n+- For each load balancer applied to this logical router configured\n+ with ``VIP`` template, a priority-100 flow matching\n+ ``ip4.dst`` or ``ip6.dst`` with the configured\n+ load balancer ``VIP`` and action ``next;``.\n+ These flows avoid dropping the packet if the ``VIP`` is\n+ set to one of the router IPs.\n+\n+- ICMP echo reply. These flows reply to ICMP echo requests received\n+ for the router's IP address. Let *A* be an IP address\n+ owned by a router port. Then, for each *A* that is\n+ an IPv4 address, a priority-90 flow matches on\n+ ``ip4.dst == A`` and\n+ ``icmp4.type == 8 && icmp4.code == 0``\n+ (ICMP echo request). For each *A* that is an IPv6\n+ address, a priority-90 flow matches on\n+ ``ip6.dst == A`` and\n+ ``icmp6.type == 128 && icmp6.code == 0``\n+ (ICMPv6 echo request). The port of the router that receives the\n+ echo request does not matter. Also, the ``ip.ttl`` 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+\n+ ip4.dst <-> ip4.src;\n+ ip.ttl = 255;\n+ icmp4.type = 0;\n+ flags.loopback = 1;\n+ next;\n+\n+ Flows for ICMPv6 echo requests use the following actions::\n+\n+ ip6.dst <-> ip6.src;\n+ ip.ttl = 255;\n+ icmp6.type = 129;\n+ flags.loopback = 1;\n+ next;\n+\n+- Reply to ARP requests.\n+\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 *P* that owns IP address *A*,\n+ which belongs to subnet *S* with prefix length *L*,\n+ and Ethernet address *E*, a priority-90 flow matches\n+ ``inport == P && arp.spa == S/L && arp.op == 1 && arp.tpa == A``\n+ (ARP request) with the following actions::\n+\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 = A;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+\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+\n+ For the logical router port with the option\n+ ``reside-on-redirect-chassis`` 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+\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+\n+ For each router port *P* that\n+ owns IPv6 address *A*, solicited node address *S*,\n+ and Ethernet address *E*, a priority-90 flow matches\n+ ``inport == P && nd_ns && ip6.dst == {A, E} && nd.target == A``\n+ with the following actions::\n+\n+ nd_na_router {\n+ eth.src = xreg0[0..47];\n+ ip6.src = A;\n+ nd.target = A;\n+ nd.tll = xreg0[0..47];\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+ };\n+\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+\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+\n+ IPv4: For a configured NAT (both DNAT and SNAT) IP address or a\n+ load balancer IPv4 VIP *A*, for each router port\n+ *P* with Ethernet address *E*, a priority-90 flow\n+ matches ``arp.op == 1 && arp.tpa == A``\n+ (ARP request) with the following actions::\n+\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+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+\n+ IPv4: For a configured load balancer IPv4 VIP, a similar flow is\n+ added with the additional match ``inport == P``\n+ if the VIP is reachable from any logical router port of the logical\n+ router.\n+\n+ If the router port *P* is a distributed gateway router\n+ port, then the ``is_chassis_resident(P)`` is\n+ also added in the match condition for the load balancer IPv4\n+ VIP *A*.\n+\n+ IPv6: For a configured NAT (both DNAT and SNAT) IP address or a\n+ load balancer IPv6 VIP *A* (if the VIP is reachable from any\n+ logical router port of the logical router), solicited node address\n+ *S*, for each router port *P* with\n+ Ethernet address *E*, a priority-90 flow matches\n+ ``inport == P && nd_ns && ip6.dst == {A, S} && nd.target == A``\n+ with the following actions::\n+\n+ eth.dst = eth.src;\n+ nd_na {\n+ eth.src = xreg0[0..47];\n+ nd.tll = xreg0[0..47];\n+ ip6.src = A;\n+ nd.target = A;\n+ outport = inport;\n+ flags.loopback = 1;\n+ output;\n+ }\n+\n+ If the router port *P* is a distributed gateway router\n+ port, then the ``is_chassis_resident(P)``\n+ is also added in the match condition for the load balancer IPv6\n+ VIP *A*.\n+\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+\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+\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 ``logical_port`` specified in the\n+ NAT rule resides.\n+\n+ Some of the actions are different for this case, using the\n+ ``external_mac`` specified in the NAT rule rather\n+ than the gateway port's Ethernet address *E*::\n+\n+ eth.src = external_mac;\n+ arp.sha = external_mac;\n+\n+ or in the case of IPv6 neighbor solicition::\n+\n+ eth.src = external_mac;\n+ nd.tll = external_mac;\n+\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+\n+- Priority-85 flows which drops the ARP and IPv6 Neighbor Discovery\n+ packets.\n+\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+\n+- A priority-83 flow explicitly drops IPv6 multicast traffic that is\n+ destined to reserved multicast groups.\n+\n+- A priority-82 flow allows IP multicast traffic if\n+ ``options``:mcast_relay='true',\n+ otherwise drops it.\n+\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+\n+ These flows should not match IP fragments with nonzero offset.\n+\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+\n+ These flows should not match IP fragments with nonzero offset.\n+\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+\n+ These flows should not match IP fragments with nonzero offset.\n+\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+ *A* owned by the router, a priority-60 flow matches\n+ ``ip4.dst == A`` or\n+ ``ip6.dst == A``\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+\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+\n+- Drop Ethernet local broadcast. A priority-50 flow with match\n+ ``eth.bcast`` drops traffic destined to the local Ethernet\n+ broadcast address. By definition this traffic should not be forwarded.\n+\n+- Avoid ICMP time exceeded for multicast. A priority-32 flow with match\n+ ``ip.ttl == {0, 1} && !ip.later_frag && (ip4.mcast || ip6.mcast)``\n+ and actions ``drop;`` drops\n+ multicast packets whose TTL has expired without sending ICMP time\n+ exceeded.\n+\n+- ICMP time exceeded. For each router port *P*, whose IP\n+ address is *A*, a priority-31 flow with match\n+ ``inport == P && ip.ttl == {0, 1} && !ip.later_frag``\n+ 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+\n+ icmp4 {\n+ icmp4.type = 11; /* Time exceeded. */\n+ icmp4.code = 0; /* TTL exceeded in transit. */\n+ ip4.dst = ip4.src;\n+ ip4.src = A;\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 = A;\n+ ip.ttl = 254;\n+ next;\n+ };\n+\n+- TTL discard. A priority-30 flow with match ``ip.ttl == {0, 1}``\n+ and actions ``drop;`` drops other packets whose TTL\n+ has expired, that should not receive a ICMP error reply (i.e. fragments\n+ with nonzero offset).\n+\n+- Next table. A priority-0 flows match all packets that aren't already\n+ handled and uses actions ``next;`` to feed them to the next\n+ table.\n+\n+\n+Ingress Table 4: DHCP Relay Request\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This stage process the DHCP request packets on which\n+``dhcp_relay_req_chk`` action is applied in the IP input stage.\n+\n+- A priority-100 logical flow is added for each logical router port\n+ configured with DHCP relay that matches ``inport`` is lrp\n+ and ``ip4.src == 0.0.0.0`` and\n+ ``ip4.dst == 255.255.255.255`` and ``udp.src == 68``\n+ and ``udp.dst == 67`` and ``reg9[7] == 1``\n+ and applies following actions. If ``reg9[7]`` is set to 1\n+ then, ``dhcp_relay_req_chk`` action was successful.\n+ ::\n+\n+ ip4.src=lrp ip;\n+ ip4.dst=dhcp server ip;\n+ udp.src = 67;\n+ next;\n+\n+- A priority-1 logical flow is added for each logical router port\n+ configured with DHCP relay that matches ``inport`` is lrp\n+ and ``ip4.src == 0.0.0.0`` and\n+ ``ip4.dst == 255.255.255.255`` and ``udp.src == 68``\n+ and ``udp.dst == 67`` and ``reg9[7] == 0``\n+ and drops the packet. If ``reg9[7]`` is set to 0 then,\n+ ``dhcp_relay_req_chk`` action was unsuccessful.\n+\n+- A priority-0 flow that matches all packets to advance to the next\n+ table.\n+\n+Ingress Table 5: UNSNAT\n+~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+Ingress Table 5: UNSNAT on Gateway and Distributed Routers\n+\n+- If the Router (Gateway or Distributed) is configured with\n+ load balancers, then below lflows are added:\n+\n+ For each IPv4 address *A* defined as load balancer\n+ VIP with the protocol *P* (and the protocol port\n+ *T* if defined) is also present as an\n+ ``external_ip`` in the NAT table,\n+ a priority-120 logical flow is added with the match\n+ ``ip4 && ip4.dst == A && P`` with the action ``next;`` to\n+ advance the packet to the next table. If the load balancer\n+ has protocol port ``B`` defined, then the match also has\n+ ``P.dst == B``.\n+\n+ The above flows are also added for IPv6 load balancers.\n+\n+Ingress Table 5: UNSNAT on Gateway Routers\n+\n+- If the Gateway router has been configured to force SNAT any\n+ previously DNATted packets to *B*, a priority-110 flow\n+ matches ``ip && ip4.dst == B`` or\n+ ``ip && ip6.dst == B``\n+ with an action ``ct_snat;``.\n+\n+ If the Gateway router is configured with\n+ ``lb_force_snat_ip=router_ip`` then for every logical router\n+ port *P* attached to the Gateway router with the router ip\n+ *B*, a priority-110 flow is added with the match\n+ ``inport == P && ip4.dst == B`` or ``inport == P && ip6.dst == B``\n+ with an action ``ct_snat;``.\n+\n+ If the Gateway router has been configured to force SNAT any\n+ previously load-balanced packets to *B*, a priority-100 flow\n+ matches ``ip && ip4.dst == B`` or\n+ ``ip && ip6.dst == B``\n+ with an action ``ct_snat;``.\n+\n+ For each NAT configuration in the OVN Northbound database, that asks\n+ to change the source IP address of a packet from *A* to\n+ *B*, a priority-90 flow matches\n+ ``ip && ip4.dst == B`` or\n+ ``ip && ip6.dst == B``\n+ with an action ``ct_snat;``. If the NAT rule is of type\n+ dnat_and_snat and has ``stateless=true`` in the\n+ options, then the action would be ``next;``.\n+\n+ A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 5: UNSNAT on Distributed Routers\n+\n+- For each configuration in the OVN Northbound database, that asks\n+ to change the source IP address of a packet from *A* to\n+ *B*, two priority-100 flows are added.\n+\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+\n+ - The first flow matches ``ip && ip4.dst == B && inport == GW``\n+ or ``ip && ip6.dst == B && inport == GW``\n+ where *GW* is the distributed gateway port\n+ corresponding to the NAT rule (specified or inferred), with an\n+ action ``ct_snat;`` to unSNAT in the common\n+ zone. If the NAT rule is of type dnat_and_snat and has\n+ ``stateless=true`` in the options, then the action\n+ would be ``next;``.\n+\n+ If the NAT entry is of type ``snat``, then there is an\n+ additional match ``is_chassis_resident(cr-GW)``\n+ where *cr-GW* is the chassis resident port of\n+ *GW*.\n+\n+ A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 6: POST USNAT\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+If the ``options:ct-commit-all`` is set to ``true`` the\n+following two flows are configured matching on ``ip && ct.new``\n+with an action ``flags.unsnat_new = 1; next;``\n+and ``ip && !ct.trk`` with an action\n+``flags.unsnat_not_tracked = 1; next;`` 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+``inport == DGP && is_chassis_resident(CHASSIS)``.\n+\n+Ingress Table 7: DEFRAG\n+~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+For all load balancing rules that are configured in\n+``OVN_Northbound`` database for a Gateway router,\n+a priority-100 flow is added for each configured virtual IP address\n+*VIP*. For IPv4 *VIPs* the flow matches\n+``ip && ip4.dst == VIP``. For IPv6\n+*VIPs*, the flow matches ``ip && ip6.dst == VIP``.\n+The flow applies the action ``ct_dnat;``\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+\n+If ECMP routes with symmetric reply are configured in the\n+``OVN_Northbound`` 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+``chk_ecmp_nh_mac(); ct_next`` or\n+``chk_ecmp_nh(); ct_next`` to send IP packets to table\n+``76`` or to table ``77`` 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+\n+If load balancing rules are configured in ``OVN_Northbound``\n+database for a Gateway router, a priority 50 flow that matches\n+``icmp || icmp6`` with an action of ``ct_dnat;``,\n+this allows potentially related ICMP traffic to pass through CT.\n+\n+If the ``options:ct-commit-all`` is set to ``true``\n+the following flow is configured matching on ``ip && (!ct.trk || !ct.rpl)``\n+with an action ``ct_next(dnat);``.\n+There is extra match when the LR is configured as DGP\n+``inport == DGP && is_chassis_resident(CHASSIS)``.\n+\n+Ingress Table 8: Connection tracking field extraction\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- For all new connections (``ct.new``), a priority-100 flow\n+ extracts the connection tracking protocol and destination port\n+ information into registers::\n+\n+ reg1[16..23] = ct_proto();\n+ reg1[0..15] = ct_tp_dst();\n+ next;\n+\n+ This stores the connection tracking destination port in\n+ ``REG_CT_TP_DST`` (reg1[0..15]) and the protocol\n+ in ``REG_CT_PROTO`` (reg1[16..23]).\n+\n+- A priority-0 flow that matches all packets and advances to the\n+ next table with action ``next;``.\n+\n+Ingress Table 9: Load balancing affinity check\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Load balancing affinity check table contains the following\n+logical flows:\n+\n+- For all the configured load balancing rules for a logical router where\n+ a positive affinity timeout is specified in ``options``\n+ column, that includes a L4 port *PORT* of protocol\n+ *P* and IPv4 or IPv6 address *VIP*, a priority-100\n+ flow that matches on\n+ ``ct.new && ip && ip.dst == VIP && REG_CT_PROTO == P_NUM && REG_CT_TP_DST == PORT``\n+ (``xxreg0 == VIP`` in the IPv6 case) with an action of\n+ ``reg0 = ip.dst; reg9[16..31] = P.dst; reg9[6] = chk_lb_aff(); next;``\n+ (``xxreg0 == ip6.dst`` in the IPv6 case), where *P_NUM* is\n+ the protocol number (6 for TCP, 17 for UDP, 132 for SCTP).\n+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\n+Ingress Table 10: DNAT\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+Ingress Table 8: Load balancing DNAT rules\n+\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 *VIPs*.\n+\n+- For all the configured load balancing rules for a logical router where\n+ a positive affinity timeout is specified in ``options``\n+ column, that includes a L4 port *PORT* of protocol\n+ *P* and IPv4 or IPv6 address *VIP*, a priority-150\n+ flow that matches on\n+ ``reg9[6] == 1 && ct.new && ip && ip.dst == VIP && REG_CT_PROTO == P_NUM && REG_CT_TP_DST == PORT``\n+ with an action of\n+ ``ct_lb_mark(args)``, where *args*\n+ contains comma separated IP addresses (and optional port numbers)\n+ to load balance to, and *P_NUM* is the protocol number\n+ (6 for TCP, 17 for UDP, 132 for SCTP). The address family of the IP\n+ addresses of *args* is the same as the address family of\n+ *VIP*.\n+\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 ``OVN_Northbound`` 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 ``event-elb`` meter has been previously created, it will be\n+ associated to the empty_lb logical flow\n+\n+- For all the configured load balancing rules for a Gateway router or\n+ Router with gateway port in ``OVN_Northbound`` database that\n+ includes a L4 port *PORT* of protocol *P* and IPv4\n+ or IPv6 address *VIP*, a priority-120 flow that matches on\n+ ``ct.new && !ct.rel && ip && ip.dst == VIP && REG_CT_PROTO == P_NUM && REG_CT_TP_DST == PORT``\n+ with an action of\n+ ``ct_lb_mark(args)``, where *args* contains\n+ comma separated IPv4 or IPv6 addresses (and optional port numbers) to\n+ load balance to, and *P_NUM* 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+ ``flags.force_snat_for_lb = 1; ct_lb_mark(args; force_snat);``.\n+ If the load balancing rule is configured with ``skip_snat``\n+ set to true, the above action will be replaced by\n+ ``flags.skip_snat_for_lb = 1; ct_lb_mark(args; skip_snat);``.\n+ If health check is enabled, then\n+ *args* will only contain those endpoints whose service\n+ monitor status entry in ``OVN_Southbound`` db is\n+ either ``online`` or empty.\n+\n+- For all the configured load balancing rules for a router in\n+ ``OVN_Northbound`` database that includes just an IP address\n+ *VIP* to match on, a priority-110 flow that matches on\n+ ``ct.new && !ct.rel && ip4 && ip.dst == VIP``\n+ with an action of\n+ ``ct_lb_mark(args)``, where *args* 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 ``flags.force_snat_for_lb = 1; ct_lb_mark(args; force_snat);``.\n+ If the load balancing rule is configured with ``skip_snat``\n+ set to true, the above action will be replaced by\n+ ``flags.skip_snat_for_lb = 1; ct_lb_mark(args; skip_snat);``.\n+\n+ The previous table ``lr_in_defrag`` sets the register\n+ ``reg0`` (or ``xxreg0`` for IPv6) and does\n+ ``ct_dnat``. Hence for established traffic, this\n+ table just advances the packet to the next stage.\n+\n+- If the load balancer is created with ``--reject`` 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 ``--reject`` option will disable\n+ empty_lb SB controller event for this load balancer.\n+\n+- For the related traffic, a priority 50 flow that matches\n+ ``ct.rel && !ct.est && !ct.new``\n+ with an action of ``ct_commit_nat;``, if the router\n+ has load balancer assigned to it. Along with two priority 70 flows\n+ that match ``skip_snat`` and ``force_snat``\n+ flags, setting the ``flags.force_snat_for_lb = 1`` or\n+ ``flags.skip_snat_for_lb = 1`` accordingly.\n+\n+- For the established traffic, a priority 50 flow that matches\n+ ``ct.est && !ct.rel && !ct.new && ct_mark.natted``\n+ with an action of ``next;``,\n+ if the router has load balancer assigned to it. Along with two\n+ priority 70 flows that match ``skip_snat`` and\n+ ``force_snat`` flags, setting the\n+ ``flags.force_snat_for_lb = 1`` or\n+ ``flags.skip_snat_for_lb = 1`` accordingly.\n+\n+Ingress Table 9: DNAT on Gateway Routers\n+\n+- For each configuration in the OVN Northbound database, that asks\n+ to change the destination IP address of a packet from *A* to\n+ *B*, a priority-100 flow matches ``ip && ip4.dst == A``\n+ or ``ip && ip6.dst == A`` with an action\n+ ``flags.loopback = 1; ct_dnat(B);``. If the\n+ Gateway router is configured to force SNAT any DNATed packet,\n+ the above action will be replaced by\n+ ``flags.force_snat_for_dnat = 1; flags.loopback = 1; ct_dnat(B);``.\n+ If the NAT rule is of type dnat_and_snat and has\n+ ``stateless=true`` in the options, then the action would be\n+ ``ip4/6.dst=(B)``.\n+\n+ If the NAT rule has ``allowed_ext_ips`` configured, then\n+ there is an additional match ``ip4.src == allowed_ext_ips``.\n+ Similarly, for IPV6, match would be\n+ ``ip6.src == allowed_ext_ips``.\n+\n+ If the NAT rule has ``exempted_ext_ips`` set, then\n+ there is an additional flow configured at priority 101.\n+ The flow matches if source ip is an ``exempted_ext_ip``\n+ and the action is ``next;``. This flow is used to\n+ bypass the ct_dnat action for a packet originating from\n+ ``exempted_ext_ips``.\n+\n+ For each configuration in the OVN Northbound database, that asks\n+ to change the destination IP address of a packet from *A*\n+ to *B*, match *M* and priority *P*,\n+ a logical flow that matches ``ip && ip4.dst == A``\n+ or ``ip && ip6.dst == A && (M)`` with an action\n+ ``flags.loopback = 1; ct_dnat(B);``.\n+ The priority of the flow is calculated based as\n+ ``300 + P``. If the Gateway router is\n+ configured to force SNAT any DNATed packet, the above action will\n+ be replaced by ``flags.force_snat_for_dnat = 1; flags.loopback = 1; ct_dnat(B);``.\n+ If the NAT rule is of type dnat_and_snat and has\n+ ``stateless=true`` in the options, then the action would be\n+ ``ip4/6.dst=(B)``.\n+\n+- If the ``options:ct-commit-all`` is set to ``true``\n+ the following flow is configured matching on ``ip && ct.new``\n+ with an action ``ct_commit_to_zone(dnat);``.\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 9: DNAT on Distributed Routers\n+\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+\n+- For each configuration in the OVN Northbound database, that asks\n+ to change the destination IP address of a packet from *A* to\n+ *B*, a priority-100 flow matches\n+ ``ip && ip4.dst == B && inport == GW``,\n+ where *GW* is the logical router gateway port corresponding\n+ to the NAT rule (specified or inferred), with an action\n+ ``ct_dnat(B);``. The match will include\n+ ``ip6.dst == B`` in the IPv6 case.\n+ If the NAT rule is of type dnat_and_snat and has\n+ ``stateless=true`` in the options, then the action\n+ would be ``ip4/6.dst=(B)``.\n+\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+\n+ If the NAT rule has ``allowed_ext_ips`` configured, then\n+ there is an additional match ``ip4.src == allowed_ext_ips``.\n+ Similarly, for IPV6, match would be\n+ ``ip6.src == allowed_ext_ips``.\n+\n+ If the NAT rule has ``exempted_ext_ips`` set, then\n+ there is an additional flow configured at priority 101.\n+ The flow matches if source ip is an ``exempted_ext_ip``\n+ and the action is ``next;``. This flow is used to\n+ bypass the ct_dnat action for a packet originating from\n+ ``exempted_ext_ips``.\n+\n+ If the ``options:ct-commit-all`` is set to ``true``\n+ the following flow is configured matching on\n+ ``ip && ct.new && inport == DGP && is_chassis_resident(CHASSIS)``\n+ with an action ``ct_commit_to_zone(dnat);``.\n+\n+ A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 11: Load balancing affinity learn\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Load balancing affinity learn table contains the following\n+logical flows:\n+\n+- For all the configured load balancing rules for a logical router where\n+ a positive affinity timeout *T* is specified in ``options``\n+ column, that includes a L4 port *PORT* of protocol\n+ *P* and IPv4 or IPv6 address *VIP*, a priority-100\n+ flow that matches on\n+ ``reg9[6] == 0 && ct.new && ip && reg0 == VIP && P && reg9[16..31] == PORT``\n+ (``xxreg0 == VIP`` in the IPv6 case) with an action of\n+ ``commit_lb_aff(vip = VIP:PORT, backend = backend ip:backend port, proto = P, timeout = T);``.\n+\n+- A priority 0 flow is added which matches on all packets and applies\n+ the action ``next;``.\n+\n+Ingress Table 12: ECMP symmetric reply processing\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- If ECMP routes with symmetric reply are configured in the\n+ ``OVN_Northbound`` 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\n+ ``ct_commit { ct_label.ecmp_reply_eth = eth.src; ct_mark.ecmp_reply_port = K;}; commit_ecmp_nh(); next;``\n+ to commit the connection and storing ``eth.src`` and\n+ the ECMP reply port binding tunnel key *K* in the\n+ ``ct_label`` and the traffic pattern to table\n+ ``76`` or ``77``.\n+\n+Ingress Table 13: IPv6 ND RA option processing\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+ ``put_nd_ra_opts`` and advances the packet to the next\n+ table.\n+ ::\n+\n+ reg0[5] = put_nd_ra_opts(options);next;\n+\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+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 14: IPv6 ND RA responder\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table implements IPv6 ND RA responder for the IPv6 ND RA replies\n+generated by the previous table.\n+\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 ``reg0[5] == 1`` and responds back to the\n+ ``inport`` after applying these actions.\n+ If ``reg0[5]`` is set to 1, it means that the action\n+ ``put_nd_ra_opts`` was successful.\n+ ::\n+\n+ eth.dst = eth.src;\n+ eth.src = E;\n+ ip6.dst = ip6.src;\n+ ip6.src = I;\n+ outport = P;\n+ flags.loopback = 1;\n+ output;\n+\n+ where *E* is the MAC address and *I* is the IPv6\n+ link local address of the logical router port.\n+\n+ (This terminates packet processing in ingress pipeline; the packet\n+ does not go to the next ingress table.)\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 15: IP Routing Pre\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+If a packet arrived at this table from Logical Router Port *P*\n+which has ``options:route_table`` value set, a logical flow with\n+match ``inport == \"P\"`` 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 (*<main>* route table),\n+register 7 value is set to 0.\n+\n+This table contains the following logical flows:\n+\n+- Priority-100 flow with match ``inport == \"LRP_NAME\"`` value\n+ and action, which set route table identifier in reg7.\n+\n+ A priority-0 logical flow with match ``1`` has actions\n+ ``reg7 = 0; next;``.\n+\n+Ingress Table 16: IP Routing\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+A packet that arrives at this table is an IP packet that should be\n+routed to the address in ``ip4.dst`` or\n+``ip6.dst``. This table implements IP routing, setting\n+``reg0`` (or ``xxreg0`` for IPv6) to the next-hop IP\n+address (leaving ``ip4.dst`` or ``ip6.dst``, the\n+packet's final destination, unchanged) and advances to the next\n+table for ARP resolution. It also sets ``reg1`` (or\n+``xxreg1``) to the IP address owned by the selected router\n+port (ingress table ``ARP Request`` will generate an ARP\n+request, if needed, with ``reg0`` as the target protocol\n+address and ``reg1`` as the source protocol address).\n+\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 ``reg8[0..15]`` and member id in\n+``reg8[16..31]``. 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+``ct_label.ecmp_reply_eth`` tells the destination MAC address to\n+which the packet should be sent. The ``ct_mark.ecmp_reply_port``\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 ``REGBIT_KNOWN_ECMP_NH`` is set, the priority-10300\n+flows in this stage set the ``outport``, while the\n+``eth.dst`` is set by flows at the ARP/ND Resolution stage.\n+\n+This table contains the following logical flows:\n+\n+- Priority-10550 flow that drops IPv6 Router Solicitation/Advertisement\n+ packets that were not processed in previous tables.\n+\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+\n+- Priority-10500 flows that match IP multicast traffic destined to\n+ groups registered on any of the attached switches and sets\n+ ``outport`` 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+\n+- Priority-10460 flows that match IGMP and MLD control packets,\n+ set ``outport`` to the ``MC_STATIC``\n+ multicast group, which ``ovn-northd``\n+ populates with the logical ports that have\n+ ``options``:mcast_flood='true'. If no router ports are configured\n+ to flood multicast traffic the packets are dropped.\n+\n+- Priority-10450 flow that matches unregistered IP multicast traffic\n+ decrements TTL and sets ``outport`` to the\n+ ``MC_STATIC`` multicast group, which ``ovn-northd``\n+ populates with the logical ports that have\n+ ``options``:mcast_flood='true'. If no router ports are configured\n+ to flood multicast traffic the packets are dropped.\n+\n+- IPv4 routing table. For each route to IPv4 network *N* with\n+ netmask *M*, on router port *P* with IP address\n+ *A* and Ethernet\n+ address *E*, a logical flow with match\n+ ``ip4.dst == N/M``, whose priority is the number of\n+ 1-bits in *M*, has the following actions::\n+\n+ ip.ttl--;\n+ reg8[0..15] = 0;\n+ reg0 = G;\n+ reg1 = A;\n+ eth.src = E;\n+ outport = P;\n+ flags.loopback = 1;\n+ next;\n+\n+ (Ingress table 1 already verified that ``ip.ttl--;`` will\n+ not yield a TTL exceeded error.)\n+\n+ If the route has a gateway, *G* is the gateway IP address.\n+ Instead, if the route is from a configured static route, *G*\n+ is the next hop IP address. Else it is ``ip4.dst``.\n+\n+- IPv6 routing table. For each route to IPv6 network\n+ *N* with netmask *M*, on router port\n+ *P* with IP address *A* and Ethernet address\n+ *E*, a logical flow with match in CIDR notation\n+ ``ip6.dst == N/M``,\n+ whose priority is the integer value of *M*, has the\n+ following actions::\n+\n+ ip.ttl--;\n+ reg8[0..15] = 0;\n+ xxreg0 = G;\n+ xxreg1 = A;\n+ eth.src = E;\n+ outport = inport;\n+ flags.loopback = 1;\n+ next;\n+\n+ (Ingress table 1 already verified that ``ip.ttl--;`` will\n+ not yield a TTL exceeded error.)\n+\n+ If the route has a gateway, *G* is the gateway IP address.\n+ Instead, if the route is from a configured static route, *G*\n+ is the next hop IP address. Else it is ``ip6.dst``.\n+\n+ If the address *A* is in the link-local scope, the\n+ route will be limited to sending on the ingress port.\n+\n+ For each static route the ``reg7 == id &&`` is\n+ prefixed in logical flow match portion. For routes with\n+ ``route_table`` value set a unique non-zero id is used.\n+ For routes within ``<main>`` route table (no route\n+ table set), this id value is 0.\n+\n+ For each *connected* route (route to the LRP's subnet CIDR)\n+ the logical flow match portion has no\n+ ``reg7 == id &&`` prefix to have route to LRP's\n+ subnets in all routing tables.\n+\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+\n+ For each IPv4/IPv6 ECMP group with group id *GID* and member\n+ ids *MID1*, *MID2*, ..., a logical flow with match\n+ in CIDR notation ``ip4.dst == N/M``,\n+ or ``ip6.dst == N/M``, whose priority\n+ is the integer value of *M*, has the following actions::\n+\n+ ip.ttl--;\n+ flags.loopback = 1;\n+ reg8[0..15] = GID;\n+ reg8[16..31] = select(MID1, MID2, ...);\n+\n+ However, when there is only one route in an ECMP group, group actions\n+ will be::\n+\n+ ip.ttl--;\n+ flags.loopback = 1;\n+ reg8[0..15] = GID;\n+ reg8[16..31] = MID1);\n+\n+- A priority-0 logical flow that matches all packets not already handled\n+ (match ``1``) and drops them (action ``drop;``).\n+\n+Ingress Table 17: IP_ROUTING_ECMP\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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 ``reg0``\n+(or ``xxreg0`` for IPv6) to the next-hop IP address\n+(leaving ``ip4.dst`` or ``ip6.dst``, the\n+packet's final destination, unchanged) and advances to the next\n+table for ARP resolution. It also sets ``reg1`` (or\n+``xxreg1``) to the IP address owned by the selected router\n+port (ingress table ``ARP Request`` will generate an ARP\n+request, if needed, with ``reg0`` as the target protocol\n+address and ``reg1`` as the source protocol address).\n+\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+\n+This table contains the following logical flows:\n+\n+- A priority-150 flow that matches ``reg8[0..15] == 0``\n+ with action ``next;`` directly bypasses packets of non-ECMP\n+ routes.\n+\n+- For each member with ID *MID* in each ECMP group with ID\n+ *GID*, a priority-100 flow with match\n+ ``reg8[0..15] == GID && reg8[16..31] == MID``\n+ has following actions::\n+\n+ [xx]reg0 = G;\n+ [xx]reg1 = A;\n+ eth.src = E;\n+ outport = P;\n+\n+- A priority-0 logical flow that matches all packets not already handled\n+ (match ``1``) and drops them (action ``drop;``).\n+\n+Ingress Table 18: Router policies\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table adds flows for the logical router policies configured\n+on the logical router. Please see the\n+``OVN_Northbound`` database ``Logical_Router_Policy``\n+table documentation in ``ovn-nb`` for supported actions.\n+\n+- For each router policy configured on the logical router, a\n+ logical flow is added with specified priority, match and\n+ actions.\n+\n+- If the policy action is ``reroute`` with 2 or more nexthops\n+ defined, then the logical flow is added with the following actions::\n+\n+ reg8[0..15] = GID;\n+ reg8[16..31] = select(1,..n);\n+\n+ where *GID* is the ECMP group id generated by\n+ ``ovn-northd`` for this policy and *n*\n+ is the number of nexthops. ``select`` action\n+ selects one of the nexthop member id, stores it in the register\n+ ``reg8[16..31]`` and advances the packet to the\n+ next stage.\n+\n+- If the policy action is ``reroute`` with just one nexhop,\n+ then the logical flow is added with the following actions::\n+\n+ [xx]reg0 = H;\n+ eth.src = E;\n+ outport = P;\n+ reg8[0..15] = 0;\n+ flags.loopback = 1;\n+ next;\n+\n+ where *H* is the ``nexthop`` defined in the\n+ router policy, *E* is the ethernet address of the\n+ logical router port from which the ``nexthop`` is\n+ reachable and *P* is the logical router port from\n+ which the ``nexthop`` is reachable.\n+\n+- If a router policy has the option ``pkt_mark=m``\n+ set and if the action is ``not`` drop, then the action also\n+ includes ``pkt.mark = m`` to mark the packet\n+ with the marker *m*.\n+\n+Ingress Table 19: ECMP handling for router policies\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table handles the ECMP for the router policies configured\n+with multiple nexthops.\n+\n+- A priority-150 flow is added to advance the packet to the next stage\n+ if the ECMP group id register ``reg8[0..15]`` is 0.\n+\n+- For each ECMP reroute router policy with multiple nexthops,\n+ a priority-100 flow is added for each nexthop *H*\n+ with the match ``reg8[0..15] == GID && reg8[16..31] == M``\n+ where *GID*\n+ is the router policy group id generated by ``ovn-northd``\n+ and *M* is the member id of the nexthop *H*\n+ generated by ``ovn-northd``. The following actions are added\n+ to the flow::\n+\n+ [xx]reg0 = H;\n+ eth.src = E;\n+ outport = P\n+ \"flags.loopback = 1; \"\n+ \"next;\"\n+\n+ where *H* is the ``nexthop`` defined in the\n+ router policy, *E* is the ethernet address of the\n+ logical router port from which the ``nexthop`` is\n+ reachable and *P* is the logical router port from\n+ which the ``nexthop`` is reachable.\n+\n+- A priority-0 logical flow that matches all packets not already handled\n+ (match ``1``) and drops them (action ``drop;``).\n+\n+Ingress Table 20: DHCP Relay Response Check\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This stage process the DHCP response packets coming from the DHCP server.\n+\n+- A priority 100 logical flow is added for each logical router port\n+ configured with DHCP relay that matches ``ip4.src`` is\n+ DHCP server ip and ``ip4.dst`` is lrp IP and\n+ ``ip4.frag == 0`` and ``udp.src == 67`` and\n+ ``udp.dst == 67`` and applies ``dhcp_relay_resp_chk``\n+ action. Original destination ip is stored in reg2.\n+ ::\n+\n+ reg9[8] = dhcp_relay_resp_chk(lrp_ip, dhcp_server_ip);next\n+\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+\n+- A priority-0 flow that matches all packets to advance to the next\n+ table.\n+\n+Ingress Table 21: DHCP Relay Response\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This stage process the DHCP response packets on which\n+``dhcp_relay_resp_chk`` action is applied in the previous stage.\n+\n+- A priority 100 logical flow is added for each logical router port\n+ configured with DHCP relay that matches ``ip4.src`` is\n+ DHCP server ip and ``reg2`` is lrp IP and\n+ ``udp.src == 67`` and ``udp.dst == 67``\n+ and ``reg9[8] == 1`` and applies following actions. If\n+ ``reg9[8]`` is set to 1 then,\n+ ``dhcp_relay_resp_chk`` was successful.\n+ ::\n+\n+ ip4.src = lrp ip;\n+ udp.dst = 68;\n+ outport = lrp port;\n+ output;\n+\n+- A priority 1 logical flow is added for the logical router port\n+ on which DHCP relay is enabled that matches ``ip4.src``\n+ is DHCP server ip and ``reg2`` is lrp IP and\n+ ``udp.src == 67`` and ``udp.dst == 67``\n+ and ``reg9[8] == 0`` and drops the packet. If\n+ ``reg9[8]`` is set to 0 then,\n+ ``dhcp_relay_resp_chk`` was unsuccessful.\n+\n+- A priority-0 flow that matches all packets to advance to the next\n+ table.\n+\n+Ingress Table 22: ARP/ND Resolution\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Any packet that reaches this table is an IP packet whose next-hop\n+IPv4 address is in ``reg0`` or IPv6 address is in\n+``xxreg0``. (``ip4.dst`` or\n+``ip6.dst`` contains the final destination.) This table\n+resolves the IP address in ``reg0`` (or\n+``xxreg0``) into an output port in ``outport``\n+and an Ethernet address in ``eth.dst``, using the\n+following flows:\n+\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+ ``outport`` was already set so the flow just advances to\n+ the next table.\n+\n+- Priority-200 flows that match ECMP reply traffic for the routes\n+ configured to use symmetric replies, with actions\n+ ``push(xxreg1); xxreg1 = ct_label; eth.dst = xxreg1[32..79]; pop(xxreg1); next;``.\n+ ``xxreg1`` is used here to avoid masked access to ct_label,\n+ to make the flow HW-offloading friendly.\n+\n+- Static MAC bindings. MAC bindings can be known statically based on\n+ data in the ``OVN_Northbound`` database. For router ports\n+ connected to logical switches, MAC bindings can be known statically\n+ from the ``addresses`` column in the\n+ ``Logical_Switch_Port`` table. (Note: the flow is not\n+ installed for IPs of logical switch ports of type\n+ ``virtual``, and dynamic MAC binding is used for those IPs\n+ instead, so that virtual parent failover does not depend on\n+ ``ovn-northd``, to achieve better failover performance.) For\n+ router ports connected to other logical routers, MAC bindings can be\n+ known statically from the ``mac`` and ``networks``\n+ column in the ``Logical_Router_Port`` 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+ ``options:dynamic_neigh_routers`` set to ``true``)\n+\n+ For each IPv4 address *A* whose host is known to have\n+ Ethernet address *E* on router port *P*, a\n+ priority-100 flow with match ``outport === P && reg0 == A``\n+ has actions ``eth.dst = E; next;``.\n+\n+ For each IPv6 address *A* whose host is known to have\n+ Ethernet address *E* on router port *P*, a\n+ priority-100 flow with match ``outport === P && xxreg0 == A``\n+ has actions ``eth.dst = E; next;``.\n+\n+ For each logical router port with an IPv4 address *A* and\n+ a mac address of *E* that is reachable via a different\n+ logical router port *P*, a priority-100 flow with\n+ match ``outport === P && reg0 == A`` has actions\n+ ``eth.dst = E; next;``.\n+\n+ For each logical router port with an IPv6 address *A* and\n+ a mac address of *E* that is reachable via a different\n+ logical router port *P*, a priority-100 flow with\n+ match ``outport === P && xxreg0 == A`` has actions\n+ ``eth.dst = E; next;``.\n+\n+- Static MAC bindings from NAT entries. MAC bindings can also be known\n+ for the entries in the ``NAT`` table. Below flows are\n+ programmed for distributed logical routers i.e with a distributed\n+ router port.\n+\n+ For each row in the ``NAT`` table with IPv4 address\n+ *A* in the ``external_ip`` column of\n+ ``NAT`` table, below two flows are\n+ programmed:\n+\n+ A priority-100 flow with the match ``outport == P && reg0 == A``\n+ has actions ``eth.dst = E; next;``, where ``P`` is the\n+ distributed logical router port, *E* is the Ethernet address\n+ if set in the ``external_mac`` column of ``NAT`` table\n+ for of type ``dnat_and_snat``, otherwise the Ethernet address of\n+ the distributed logical router port. Note that if the\n+ ``external_ip`` is not\n+ within a subnet on the owning logical router, then OVN will only\n+ create ARP resolution flows if the ``options:add_route``\n+ is set to ``true``. Otherwise, no ARP resolution flows\n+ will be added.\n+\n+ Corresponding to the above flow, a priority-150 flow with the match\n+ ``inport == P && outport == P && ip4.dst == A`` has actions\n+ ``drop;`` to exclude packets that have gone through\n+ DNAT/unSNAT stage but failed to convert the destination, to avoid\n+ loop.\n+\n+ For IPv6 NAT entries, same flows are added, but using the register\n+ ``xxreg0`` and field ``ip6`` for the match.\n+\n+- If the router datapath runs a port with ``redirect-type``\n+ set to ``bridged``, for each distributed NAT rule with IP\n+ *A* in the ``logical_ip`` column\n+ and logical port *P* in the\n+ ``logical_port`` column\n+ of ``NAT`` table, a priority-90 flow\n+ with the match ``outport == Q && ip.src === A && is_chassis_resident(P)``,\n+ where ``Q`` is the distributed logical router port and\n+ action ``get_arp(outport, reg0); next;`` for IPv4 and\n+ ``get_nd(outport, xxreg0); next;`` for IPv6.\n+\n+- Traffic with IP destination an address owned by the router should be\n+ dropped. Such traffic is normally dropped in ingress table\n+ ``IP Input`` 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+\n+ A priority-2 logical flow with match ``ip4.dst = {..}``\n+ matches on traffic destined to router owned IPv4 addresses which are\n+ also SNAT IPs. This flow has action ``drop;``.\n+\n+ A priority-2 logical flow with match ``ip6.dst = {..}``\n+ matches on traffic destined to router owned IPv6 addresses which are\n+ also SNAT IPs. This flow has action ``drop;``.\n+\n+ A priority-0 logical that flow matches all packets not already\n+ handled (match ``1``) and drops them\n+ (action ``drop;``).\n+\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 ``ARP Request`` will\n+ issue an ARP or neighbor solicitation request for cases where\n+ the binding is not yet known.)\n+\n+ A priority-0 logical flow with match ``ip4`` has actions\n+ ``get_arp(outport, reg0); next;``.\n+\n+ A priority-0 logical flow with match ``ip6`` has actions\n+ ``get_nd(outport, xxreg0); next;``.\n+\n+- For a distributed gateway LRP with ``redirect-type``\n+ set to ``bridged``, a priority-50 flow will match\n+ ``outport == \"ROUTER_PORT\" and !is_chassis_resident(\"cr-ROUTER_PORT\")``\n+ has actions ``eth.dst = E; next;``, where *E* is the\n+ ethernet address of the logical router port.\n+\n+Ingress Table 23: Check packet length\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For distributed logical routers or gateway routers with gateway\n+port configured with ``options:gateway_mtu`` to a valid\n+integer value, this table adds a priority-50 logical flow with\n+the match ``outport == GW_PORT`` where\n+*GW_PORT* is the gateway router port and applies the\n+actions ``check_pkt_larger`` and ``ct_state_save``\n+and then advances the packet to the next table.\n+::\n+\n+ REGBIT_PKT_LARGER = check_pkt_larger(L);\n+ REG_CT_STATE = ct_state_save();\n+ next;\n+\n+where *L* is the packet length to check for. If the packet\n+is larger than *L*, it stores 1 in the register bit\n+``REGBIT_PKT_LARGER``. The value of\n+*L* is taken from ``options:gateway_mtu`` column of\n+``Logical_Router_Port`` row.\n+\n+If the port is also configured with\n+``options:gateway_mtu_bypass`` then another flow is\n+added, with priority-55, to bypass the ``check_pkt_larger``\n+flow.\n+\n+This table adds one priority-0 fallback flow that matches all packets\n+and advances to the next table.\n+\n+Ingress Table 24: Handle larger packets\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For distributed logical routers or gateway routers with gateway port\n+configured with ``options:gateway_mtu`` to a valid integer\n+value, this table adds the following priority-150 logical flow for each\n+logical router port with the match\n+``inport == LRP && outport == GW_PORT && REGBIT_PKT_LARGER && !REGBIT_EGRESS_LOOPBACK``,\n+where *LRP* is the logical router port and *GW_PORT* is\n+the gateway port and applies the following action for ipv4 and ipv6\n+respectively::\n+\n+ icmp4 {\n+ icmp4.type = 3; /* Destination Unreachable. */\n+ icmp4.code = 4; /* Frag Needed and DF was Set. */\n+ icmp4.frag_mtu = M;\n+ eth.dst = E;\n+ ip4.dst = ip4.src;\n+ ip4.src = I;\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 = M;\n+ eth.dst = E;\n+ ip6.dst = ip6.src;\n+ ip6.src = I;\n+ ip.ttl = 255;\n+ REGBIT_EGRESS_LOOPBACK = 1;\n+ REGBIT_PKT_LARGER = 0;\n+ next(pipeline=ingress, table=0);\n+ };\n+\n+- Where *M* is the (fragment MTU - 58) whose value is taken from\n+ ``options:gateway_mtu`` column of\n+ ``Logical_Router_Port`` row.\n+\n+- *E* is the Ethernet address of the logical router port.\n+\n+- *I* is the IPv4/IPv6 address of the logical router port.\n+\n+This table adds one priority-0 fallback flow that matches all packets\n+and advances to the next table.\n+\n+Ingress Table 25: Gateway Redirect\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- For all the configured load balancing rules that include an IPv4\n+ address *VIP*, and a list of IPv4 backend addresses\n+ *B0*, *B1* .. *Bn* defined for the\n+ *VIP* a priority-200 flow is added that matches\n+ ``ip4 && (ip4.src == B0 || ip4.src == B1 || ... || ip4.src == Bn)``\n+ with an action\n+ ``outport = CR; next;`` where *CR* is the\n+ ``chassisredirect`` port representing the instance of the\n+ logical router distributed gateway port on the gateway chassis.\n+ If the backend IPv4 address *Bx* is also configured with\n+ L4 port *PORT* of protocol *P*, then the match\n+ also includes ``P.src`` == *PORT*.\n+ Similar flows are added for IPv6.\n+\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 ``ip4.src == B && outport == GW`` &&\n+ is_chassis_resident(*P*), where *GW* is\n+ the distributed gateway port specified in the\n+ NAT rule and *P* is the NAT logical port. IP traffic\n+ matching the above rule will be managed locally setting\n+ ``reg1`` to *C* and\n+ ``eth.src`` to *D*, where *C* is NAT\n+ external ip and *D* is NAT external mac.\n+\n+- For each ``dnat_and_snat`` NAT rule with\n+ ``stateless=true`` and ``allowed_ext_ips``\n+ configured, a priority-75 flow is programmed with match\n+ ``ip4.dst == B`` and action\n+ ``outport = CR; next;`` where *B*\n+ is the NAT rule external IP and *CR* is the\n+ ``chassisredirect`` 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 ``drop;``.\n+ For each ``dnat_and_snat`` NAT rule with\n+ ``stateless=true`` and ``exempted_ext_ips``\n+ configured, a priority-75 flow is programmed with match\n+ ``ip4.dst == B`` and action\n+ ``drop;`` where *B* is the NAT rule\n+ external IP.\n+ A similar flow is added for IPv6 traffic.\n+\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+\n+- A priority-50 logical flow with match\n+ ``outport == GW`` has actions\n+ ``outport = CR; next;``, where\n+ *GW* is the logical router distributed gateway\n+ port and *CR* is the ``chassisredirect``\n+ port representing the instance of the logical router\n+ distributed gateway port on the\n+ gateway chassis.\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Ingress Table 26: Network ID\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table contains flows that set ``flags.network_id`` for\n+IP packets:\n+\n+- A priority-110 flow with match:\n+\n+ - for IPv4: ``outport == P && REG_NEXT_HOP_IPV4 == I/C && ip4``\n+\n+ - for IPv6: ``outport == P && REG_NEXT_HOP_IPV6 == I/C && ip6``\n+\n+ and actions ``flags.network_id = N; next;``.\n+ Where *P* is the outport, *I*/*C* is a\n+ network CIDR of the port *P*, and *N* is the\n+ network id (index). There is one flow like this per router port's\n+ network.\n+\n+ ``flags.network_id`` 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 ``flags.network_id = 0; next;``\n+ and only the lexicographically first IP will be considered for SNAT for\n+ those networks.\n+\n+- A lower priority-105 flow with match ``1`` and actions\n+ ``flags.network_id = 0; next;``. This is for the case that the\n+ next-hop doesn't belong to any of the port networks, so\n+ ``flags.network_id`` should be set to zero.\n+\n+- Catch-all: A priority-0 flow with match ``1`` has\n+ actions ``next;``.\n+\n+Ingress Table 27: ARP Request\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- Unknown MAC address. A priority-100 flow for IPv4 packets with match\n+ ``eth.dst == 00:00:00:00:00:00`` has the following actions::\n+\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+\n+ Unknown MAC address. For each IPv6 static route associated with the\n+ router with the nexthop IP: *G*, a priority-200 flow\n+ for IPv6 packets with match\n+ ``eth.dst == 00:00:00:00:00:00 && xxreg0 == G``\n+ with the following actions is added::\n+\n+ nd_ns {\n+ eth.dst = E;\n+ ip6.dst = I\n+ nd.target = G;\n+ output;\n+ };\n+\n+ Where *E* is the multicast mac derived from the Gateway IP,\n+ *I* is the solicited-node multicast address corresponding\n+ to the target address *G*.\n+\n+ Unknown MAC address. A priority-100 flow for IPv6 packets with match\n+ ``eth.dst == 00:00:00:00:00:00`` has the following actions::\n+\n+ nd_ns {\n+ nd.target = xxreg0;\n+ output;\n+ };\n+\n+ (Ingress table ``IP Routing`` initialized ``reg1``\n+ with the IP address owned by ``outport`` and\n+ ``(xx)reg0`` with the next-hop IP address)\n+\n+ The IP packet that triggers the ARP/IPv6 NS request is dropped.\n+\n+- Known MAC address. A priority-0 flow with match ``1`` has\n+ actions ``next;``.\n+\n+Ingress Table 28: ECMP symmetric reply processing for egress\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+Egress Table 0: Check DNAT local\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+This table checks if the packet needs to be DNATed in the router ingress\n+table ``lr_in_dnat`` 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+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``REGBIT_DST_NAT_IP_LOCAL = 0; next;``.\n+\n+Egress Table 1: UNDNAT\n+~~~~~~~~~~~~~~~~~~~~~~~\n+\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+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Egress Table 1: UNDNAT on Gateway Routers\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- For IPv6 Neighbor Discovery or Router Solicitation/Advertisement\n+ traffic, a priority-100 flow with action ``next;``.\n+\n+- For all IP packets, a priority-50 flow with an action\n+ ``flags.loopback = 1; ct_dnat;``.\n+\n+Egress Table 1: UNDNAT on Distributed Routers\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+- For all the configured load balancing rules for a router with gateway\n+ port in ``OVN_Northbound`` database that includes an IPv4\n+ address ``VIP``, for every backend IPv4 address *B*\n+ defined for the ``VIP`` a priority-120 flow is programmed on\n+ gateway chassis that matches\n+ ``ip && ip4.src == B && outport == GW``, where *GW* is the\n+ logical router gateway port with an action ``ct_dnat;``.\n+ If the backend IPv4 address *B* is also configured with\n+ L4 port *PORT* of protocol *P*, then the\n+ match also includes ``P.src`` == *PORT*. These\n+ flows are not added for load balancers with IPv6 *VIPs*.\n+\n+ If the router is configured to force SNAT any load-balanced packets,\n+ above action will be replaced by\n+ ``flags.force_snat_for_lb = 1; ct_dnat;``.\n+\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 *A* to *B*, a priority-100 flow\n+ matches ``ip && ip4.src == B && outport == GW``, where *GW*\n+ is the logical router gateway port, with an action\n+ ``ct_dnat;``. If the NAT rule is of type\n+ dnat_and_snat and has ``stateless=true`` in the\n+ options, then the action would be ``next;``.\n+\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 ``ct_dnat``.\n+\n+ If the NAT rule can be handled in a distributed manner, then\n+ there is an additional action\n+ ``eth.src = EA;``, where *EA*\n+ is the ethernet address associated with the IP address\n+ *A* in the NAT rule. This allows upstream MAC\n+ learning to point to the correct chassis.\n+\n+Egress Table 2: Post UNDNAT\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\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, ``lr_out_snat``, to\n+ effectively match on various CT states.\n+\n+- A priority-50 logical flow is added that commits any untracked flows\n+ from the previous table ``lr_out_undnat`` for Gateway\n+ routers. This flow matches on ``ct.new && ip``\n+ with action ``ct_commit { } ; next;``.\n+\n+- If the ``options:ct-commit-all`` is set to ``true``\n+ the following flows are configured matching on\n+ ``ip && (!ct.trk || !ct.rpl) && flags.unsnat_not_tracked == 1``\n+ with an action ``ct_next(snat);`` and\n+ ``ip && flags.unsnat_new == 1`` with an action ``next;``.\n+ There is extra match when there is configured DGP\n+ ``outport == DGP && is_chassis_resident(CHASSIS)``.\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Egress Table 3: SNAT\n+~~~~~~~~~~~~~~~~~~~~~\n+\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+\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 ``nd_ns`` action)\n+ we don't want the packet to go through conntrack.\n+\n+Egress Table 3: SNAT on Gateway Routers\n+\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 *B*, a priority-100 flow matches\n+ ``flags.force_snat_for_dnat == 1 && ip`` with an\n+ action ``ct_snat(B);``.\n+\n+- If a load balancer configured to skip snat has been applied to\n+ the Gateway router pipeline, a priority-120 flow matches\n+ ``flags.skip_snat_for_lb == 1 && ip`` with an\n+ action ``next;``.\n+\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 ``options``:lb_force_snat_ip=router_ip),\n+ then for\n+ each logical router port *P* attached to the Gateway\n+ router, and for each network configured for this port, a priority-110\n+ flow matches ``flags.force_snat_for_lb == 1`` &&\n+ ``ip4`` &&\n+ ``flags.network_id == N`` &&\n+ ``outport == P``, where *N* is the\n+ network index, with an action ``ct_snat(R);``\n+ where *R* is the IP configured on the router port. A similar\n+ flow is created for IPv6, with ``ip6`` instead of\n+ ``ip4``. *N*, the network index, will be 0 for\n+ networks 17 and up.\n+\n+ If the logical router port *P* 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 *R* 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+\n+- A priority-105 flow matches the old behavior for if northd is\n+ upgraded before controller and ``flags.network_id`` 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+ ``flags.force_snat_for_lb == 1`` && ``ip4``\n+ && ``outport == P``, with action:\n+ ``ct_snat(R)``.\n+ *R* is the lexicographically first IP address configured.\n+ There is a similar flow for IPv6 with ``ip6`` instead of\n+ ``ip4``.\n+\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 *B*, a priority-100 flow matches\n+ ``flags.force_snat_for_lb == 1 && ip`` with an\n+ action ``ct_snat(B);``.\n+\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+ *A* or to change the source IP address of a packet that\n+ belongs to network *A* to *B*, a flow matches\n+ ``ip && ip4.src == A && (!ct.trk || !ct.rpl)`` with an action\n+ ``ct_snat(B);``. The priority of the flow\n+ is calculated based on the mask of *A*, with matches\n+ having larger masks getting higher priorities. If the NAT rule is\n+ of type dnat_and_snat and has ``stateless=true`` in the\n+ options, then the action would be ``ip4/6.src=(B)``.\n+\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+ *A* or to change the source IP address of a packet that\n+ belongs to network *A* to *B*, match *M*\n+ and priority *P*, a flow matches\n+ ``ip && ip4.src == A && (!ct.trk || !ct.rpl) && (M)``\n+ with an action ``ct_snat(B);``. The priority of the flow is\n+ calculated based as ``300 + P``. If the NAT rule is of type\n+ dnat_and_snat and has ``stateless=true`` in the options,\n+ then the action would be ``ip4/6.src=(B)``.\n+\n+- If the NAT rule has ``allowed_ext_ips`` configured, then\n+ there is an additional match ``ip4.dst == allowed_ext_ips``.\n+ Similarly, for IPV6, match would be\n+ ``ip6.dst == allowed_ext_ips``.\n+\n+- If the NAT rule has ``exempted_ext_ips`` 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 ``exempted_ext_ip`` and the action is ``next;``.\n+ This flow is used to bypass the ct_snat action for a packet\n+ which is destinted to ``exempted_ext_ips``.\n+\n+- If the ``options:ct-commit-all`` is set to ``true``\n+ the following two flows are configured matching on\n+ ``ip && (!ct.trk || !ct.rpl) && flags.unsnat_new == 1`` and\n+ ``ip && ct.new && flags.unsnat_not_tracked == 1``\n+ both with an action ``ct_commit_to_zone(snat);``.\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Egress Table 3: SNAT on Distributed Routers\n+\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+ *A* or to change the source IP address of a packet that\n+ belongs to network *A* to *B*, two flows are\n+ added. The priority *P* of these flows are calculated\n+ based on the mask of *A*, with matches having larger\n+ masks getting higher priorities.\n+\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+\n+ - The first flow is added with the calculated priority *P*\n+ and match ``ip && ip4.src == A && outport == GW``, where\n+ *GW* is the logical router gateway port, with an action\n+ ``ct_snat(B);`` to SNATed in the\n+ common zone. If the NAT rule is of type dnat_and_snat and has\n+ ``stateless=true`` in the options, then the action\n+ would be ``ip4/6.src=(B)``.\n+\n+ If the NAT rule can be handled in a distributed manner, then\n+ there is an additional action (for both the flows)\n+ ``eth.src = EA;``, where *EA*\n+ is the ethernet address associated with the IP address\n+ *A* in the NAT rule. This allows upstream MAC\n+ learning to point to the correct chassis.\n+\n+ If the NAT rule has ``allowed_ext_ips`` configured, then\n+ there is an additional match ``ip4.dst == allowed_ext_ips``.\n+ Similarly, for IPV6, match would be\n+ ``ip6.dst == allowed_ext_ips``.\n+\n+ If the NAT rule has ``exempted_ext_ips`` set, then\n+ there is an additional flow configured at the priority\n+ ``P + 2`` of\n+ corresponding NAT rule. The flow matches if destination ip\n+ is an ``exempted_ext_ip`` and the action is ``next;``.\n+ This flow is used to bypass the ct_snat action for a flow\n+ which is destinted to ``exempted_ext_ips``.\n+\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 ``ip4.src == A && outport == GW``,\n+ this flow matches on ``ip4.dst == A && inport == GW``. A CT\n+ state is initiated for this traffic so that the following table,\n+ ``lr_out_post_snat``, can identify whether the traffic flow was\n+ initiated from the internal or external network.\n+\n+- If the ``options:ct-commit-all`` is set to ``true``\n+ the following two flows are configured matching on\n+ ``ip && (!ct.trk || !ct.rpl) && flags.unsnat_new == 1 && outport == DGP && is_chassis_resident(CHASSIS)``\n+ and\n+ ``ip && ct.new && flags.unsnat_not_tracked == 1 && outport == DGP && is_chassis_resident(CHASSIS)``\n+ both with an action ``ct_commit_to_zone(snat);``.\n+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Egress Table 4: Post SNAT\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Packets reaching this table are processed according to the flows below:\n+\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 ``ct.new``), 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+\n+- A priority-0 logical flow that matches all packets not already\n+ handled (match ``1``) and action ``next;``.\n+\n+Egress Table 5: Egress Loopback\n+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+For distributed logical routers where one of the logical router\n+ports specifies a gateway chassis.\n+\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+\n+This table has the following flows:\n+\n+- For each NAT rule in the OVN Northbound database on a\n+ distributed router, a priority-100 logical flow with match\n+ ``ip4.dst == E && outport == GW && is_chassis_resident(P)``,\n+ where *E* is the\n+ external IP address specified in the NAT rule, *GW*\n+ is the distributed gateway port corresponding to the NAT rule\n+ (specified or inferred).\n+ For dnat_and_snat NAT rule, *P* is the logical port\n+ specified in the NAT rule.\n+ If ``logical_port`` column of\n+ ``NAT`` table is NOT set, then\n+ *P* is the ``chassisredirect port`` of\n+ *GW* with the following actions::\n+\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+\n+ ``flags.loopback`` is set since in_port is unchanged\n+ and the packet may return back to that port after NAT processing.\n+ ``REGBIT_EGRESS_LOOPBACK`` 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+\n+- A priority-0 logical flow with match ``1`` has actions\n+ ``next;``.\n+\n+Egress Table 6: Delivery\n+~~~~~~~~~~~~~~~~~~~~~~~~~~\n+\n+Packets that reach this table are ready for delivery. It contains:\n+\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 ``output;``.\n+\n+- Priority-100 logical flows that match packets on each enabled\n+ logical router port, with action ``output;``.\n+\n+- A priority-0 logical flow that matches all packets not already\n+ handled (match ``1``) and drops them\n+ (action ``drop;``).\n+\n+Drop sampling\n+-------------\n+\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+``Logical_Flow`` with the ``drop;`` action.\n+\n+When debug drop-sampling has been cofigured in the OVN Northbound\n+database, the ovn-northd will replace all the ``drop;``\n+actions with a\n+``sample(priority=65535, collector_set=id, obs_domain=obs_id, obs_point=@cookie)``\n+action, where:\n+\n+- *id* is the value the ``debug_drop_collector_set``\n+ option configured in the OVN Northbound.\n+\n+- *obs_id* has it's 8 most significant bits equal to the value\n+ of the ``debug_drop_domain_id`` option in the OVN Northbound\n+ and it's 24 least significant bits equal to the datapath's tunnel key.\ndiff --git a/northd/ovn-logical-flows.7.xml b/northd/ovn-logical-flows.7.xml\ndeleted file mode 100644\nindex b8d353695..000000000\n--- a/northd/ovn-logical-flows.7.xml\n+++ /dev/null\n@@ -1,6080 +0,0 @@\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> &&\n- outport == <var>P</var> && 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- && 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> && outport == <var>P</var> &&\n- !is_chassis_resident(\"<var>P</var>\") && 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> && 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 <-> 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 <-%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 && 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 && ip && ip4.dst == <var>VIP</var>\n- && reg1[16..23] == <var>PROTO_NUM</var> &&\n- reg1[0..15] == <var>PORT</var></code>. For IPv6\n- <var>VIPs</var>, the flow matches <code>ct.new && ip &&\n- ip6.dst == <var>VIP</var> && reg1[16..23] ==\n- <var>PROTO_NUM</var> && 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 && ct.new && ip &&\n- ip4.dst == <var>VIP</var> && <var>P</var>.dst == <var>PORT\n- </var></code>. For IPv6 <var>VIPs</var>, the flow matches\n- <code>reg9[6] == 1 && ct.new && ip &&\n- ip6.dst == <var> VIP </var>&& <var>P</var> &&\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 && ip &&\n- ip4.dst == <var>VIP</var> && reg1[16..23] ==\n- <var>PROTO_NUM</var> && reg1[0..15] == <var>PORT</var></code>.\n- For IPv6 <var>VIPs</var>,\n- the flow matches <code>ct.new && ip && ip6.dst == <var>\n- VIP </var>&& reg1[16..23] == <var>PROTO_NUM</var> &&\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 && ip &&\n- ip4.dst == <var>VIP</var></code>. For IPv6 <var>VIPs</var>,\n- the flow matches <code>ct.new && ip && 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 && ct.new && ip\n- && ip4.dst == <var>VIP</var> && <var>P</var>.dst ==\n- <var>PORT</var></code>. For IPv6 <var>VIPs</var>, the flow matches\n- <code>ct.new && ip && ip6.dst == <var>VIP</var>\n- && <var>P</var> && <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 && 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 && ct.new && ct.trk &&\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 && ct.est && ct.trk &&\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 && 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 && 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 <-> 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 <-%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 &&\n- reg8[22] == 1 && 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 && reg8[22] == 1 &&\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 && 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 && 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 && 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 && reg8[22] == 1 &&\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 && reg8[22] == 0 &&\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 &&\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> && && ((arp.op == 1 && arp.spa == <var>VIP</var> && arp.tpa == <var>VIP</var>) || (arp.op == 2 && arp.spa == <var>VIP</var>))</code>\n-<code>inport == <var>P</var> && && ((nd_ns && ip6.dst == <var>{VIP, NS_MULTICAST_ADDR}</var> && nd.target == <var>VIP</var>) || (nd_na && 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- && && 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> && && 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- && udp.dst == 67 && 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- && udp.dst == 547 && 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 && 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 <-> eth.src;\n-ip4.src <-> 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> &&\n- eth.src == <var>E</var> && eth.dst == <var>R</var>\n- && !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- && reg8[22] == 1 && 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 && reg8[22] == 1 &&\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 && 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 && reg8[22] == 1 &&\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 && reg8[22] == 0 &&\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> && (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> &&\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- && 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> && arp.spa ==\n- <var>S</var>/<var>L</var> && 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> && arp.spa == <var>S</var>/<var>L</var>\n- && arp.tpa == <var>A</var> && 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> && arp.spa == <var>S</var>/<var>L</var>\n- && 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 &&\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 &&\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> && REGBIT_PKT_LARGER\n- && 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> && REGBIT_PKT_LARGER &&\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- && 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 &&\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 && 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 && 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 <-> 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 <-> 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> &&\n- arp.spa == <var>S</var>/<var>L</var> && arp.op == 1\n- && 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> &&\n- nd_ns && ip6.dst == {<var>A</var>, <var>E</var>} &&\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 && 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 <-> 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> && nd_ns &&\n- ip6.dst == {<var>A</var>, <var>S</var>} &&\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} && !ip.later_frag &&\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> && ip.ttl == {0, 1} &&\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 && ip4.dst == <var>A</var> &&\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 && ip4.dst == <var>B</var></code> or\n- <code>ip && 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> &&\n- ip4.dst == <var>B</var></code> or <code>inport == <var>P</var>\n- && 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 && ip4.dst == <var>B</var></code> or\n- <code>ip && 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 && ip4.dst == <var>B</var></code> or\n- <code>ip && 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 &&\n- ip4.dst == <var>B</var> && inport == <var>GW</var>\n- </code> or <code>ip && ip6.dst == <var>B</var> &&\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 &&\n- ct.new</code> with an action <code>flags.unsnat_new = 1; next; </code>\n- and <code>ip && !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 && 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 && ip4.dst == <var>VIP</var></code>. For IPv6\n- <var>VIPs</var>, the flow matches <code>ip && 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 &&\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 && 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 && ip &&\n- ip.dst == <var>VIP</var> && REG_CT_PROTO == <var>P_NUM</var>\n- && 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 && ct.new &&\n- ip && ip.dst == <var>VIP</var> && REG_CT_PROTO ==\n- <var>P_NUM</var> &&\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 && !ct.rel && ip && ip.dst ==\n- <var>VIP</var> && REG_CT_PROTO == <var>P_NUM</var> &&\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 && !ct.rel && ip4 && 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 && !ct.est && !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 && !ct.rel && !ct.new &&\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 &&\n- ip4.dst == <var>A</var></code> or <code>ip &&\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 && ip4.dst ==\n- <var>A</var></code> or <code>ip && ip6.dst == <var>A</var>\n- && (<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 &&\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 &&\n- ip4.dst == <var>B</var> && 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 &&\n- ct.new && inport == DGP &&\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 && ct.new &&\n- ip && reg0 == <var>VIP</var> && <var>P</var> &&\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><main></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 &&</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><main></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 &&</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> && 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> &&\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- && 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- && 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> && 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> && 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- && 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> && outport == <var>P</var>\n- && 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> && ip.src ===\n- <var>A</var> && 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- && outport == <var>GW_PORT</var> && REGBIT_PKT_LARGER\n- && !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 && (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> &&\n- outport == <var>GW</var></code> &&\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> &&\n- REG_NEXT_HOP_IPV4 == <var>I</var>/<var>C</var> &&\n- ip4</code>\n- </li>\n- <li>\n- for IPv6: <code>outport == <var>P</var> &&\n- REG_NEXT_HOP_IPV6 == <var>I</var>/<var>C</var> &&\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 &&\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 && ip4.src == <var>B</var> &&\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 && ip4.src == <var>B</var>\n- && 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 && 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 &&\n- (!ct.trk || !ct.rpl) && flags.unsnat_not_tracked == 1</code>\n- with an action <code>ct_next(snat);</code> and <code>ip &&\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 && 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 && 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 && 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> &&\n- <code>ip4</code> &&\n- <code>flags.network_id == <var>N</var></code> &&\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> && <code>ip4</code>\n- && <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 && 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 && ip4.src == <var>A</var> &&\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 &&\n- ip4.src == <var>A</var> && (!ct.trk || !ct.rpl) &&\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- && (!ct.trk || !ct.rpl) &&\n- flags.unsnat_new == 1</code> and\n- <code>ip && ct.new && 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 && ip4.src == <var>A</var> &&\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> && outport\n- == <var>GW</var></code>, this flow matches on <code> ip4.dst ==\n- <var>A</var> && 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- && (!ct.trk || !ct.rpl) && flags.unsnat_new == 1\n- && outport == DGP && is_chassis_resident(CHASSIS)\n- </code> and <code>ip && ct.new &&\n- flags.unsnat_not_tracked == 1 && outport == DGP &&\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> &&\n- outport == <var>GW</var> &&\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/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in\nindex 1e15b468d..e8c366279 100644\n--- a/rhel/ovn-fedora.spec.in\n+++ b/rhel/ovn-fedora.spec.in\n@@ -63,6 +63,7 @@ BuildRequires: libcap-ng libcap-ng-devel\n BuildRequires: tcpdump\n %endif\n BuildRequires: unbound unbound-devel\n+BuildRequires: python3-docutils\n \n Requires: openssl hostname iproute module-init-tools openvswitch\n Requires: python3-openvswitch\n", "prefixes": [ "ovs-dev", "5/5" ] }