Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2229777/?format=api
{ "id": 2229777, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2229777/?format=api", "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-4-mmichels@redhat.com/", "project": { "id": 68, "url": "http://patchwork.ozlabs.org/api/1.1/projects/68/?format=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-4-mmichels@redhat.com>", "date": "2026-04-28T17:45:03", "name": "[ovs-dev,3/5] northd: Split logical flow docs into ovn-logical-flows(7).", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "fe5923b0224df923ad768056fe0797abf3a6f014", "submitter": { "id": 71978, "url": "http://patchwork.ozlabs.org/api/1.1/people/71978/?format=api", "name": "Mark Michelson", "email": "mmichels@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260428174509.145440-4-mmichels@redhat.com/mbox/", "series": [ { "id": 501914, "url": "http://patchwork.ozlabs.org/api/1.1/series/501914/?format=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/2229777/comments/", "check": "fail", "checks": "http://patchwork.ozlabs.org/api/patches/2229777/checks/", "tags": {}, "headers": { "Return-Path": "<ovs-dev-bounces@openvswitch.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "dev@openvswitch.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "ovs-dev@lists.linuxfoundation.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KUcU0B7N;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=140.211.166.133; helo=smtp2.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)", "smtp2.osuosl.org;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=KUcU0B7N", "smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com", "smtp1.osuosl.org;\n dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=KUcU0B7N" ], "Received": [ "from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4nsd2d5Tz1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 29 Apr 2026 03:45:56 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id B0B9940863;\n\tTue, 28 Apr 2026 17:45:54 +0000 (UTC)", "from smtp2.osuosl.org ([127.0.0.1])\n by localhost (smtp2.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 8V6Lfe4Hl89M; Tue, 28 Apr 2026 17:45:51 +0000 (UTC)", "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id 1AD654083D;\n\tTue, 28 Apr 2026 17:45:51 +0000 (UTC)", "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id E0FC2C04FB;\n\tTue, 28 Apr 2026 17:45:50 +0000 (UTC)", "from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 2A31CC04FA\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:49 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id 97277834F4\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:31 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id lUI2Of4HP3rq for <dev@openvswitch.org>;\n Tue, 28 Apr 2026 17:45:24 +0000 (UTC)", "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 5E47883409\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:22 +0000 (UTC)", "from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-597-yg7Zn2ZvMkyX-uJEGtKwDQ-1; Tue,\n 28 Apr 2026 13:45:14 -0400", "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id DB1FA195609D\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:13 +0000 (UTC)", "from localhost.localdomain.com (unknown [10.22.88.208])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 063BD19560B7\n for <dev@openvswitch.org>; Tue, 28 Apr 2026 17:45:12 +0000 (UTC)" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections - client-ip=140.211.9.56;\n helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp2.osuosl.org 1AD654083D", "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 5E47883409" ], "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=mmichels@redhat.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 5E47883409", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777398321;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=4MlCRUuvywFWV0+R98WVT4LktWlovIqQPQO2kONVL0M=;\n b=KUcU0B7NU2RPhMDv4jMXYQiezbqKj8nRBOKPRB5eo5mja8kKR5Y3OgSutCsEz4Yz1uAFPx\n 34O+g+yulTkfOAIqsMP8lnLjzolq50O/ZWKjY2xngHu35yxd8rErWQbk4HH3v/e37RXn38\n 5nEQO83nwv38ZCd6sTh7l4E4N263Foo=", "X-MC-Unique": "yg7Zn2ZvMkyX-uJEGtKwDQ-1", "X-Mimecast-MFC-AGG-ID": "yg7Zn2ZvMkyX-uJEGtKwDQ_1777398314", "To": "dev@openvswitch.org", "Date": "Tue, 28 Apr 2026 13:45:03 -0400", "Message-ID": "<20260428174509.145440-4-mmichels@redhat.com>", "In-Reply-To": "<20260428174509.145440-1-mmichels@redhat.com>", "References": "<20260428174509.145440-1-mmichels@redhat.com>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "lU2VETdYzhliCu9pL0n-elvgwYsv9keE8jzjkHPRR48_1777398314", "X-Mimecast-Originator": "redhat.com", "Subject": "[ovs-dev] [PATCH ovn 3/5] northd: Split logical flow docs into\n ovn-logical-flows(7).", "X-BeenThere": "ovs-dev@openvswitch.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "<ovs-dev.openvswitch.org>", "List-Unsubscribe": "<https://mail.openvswitch.org/mailman/options/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=unsubscribe>", "List-Archive": "<http://mail.openvswitch.org/pipermail/ovs-dev/>", "List-Post": "<mailto:ovs-dev@openvswitch.org>", "List-Help": "<mailto:ovs-dev-request@openvswitch.org?subject=help>", "List-Subscribe": "<https://mail.openvswitch.org/mailman/listinfo/ovs-dev>,\n <mailto:ovs-dev-request@openvswitch.org?subject=subscribe>", "From": "Mark Michelson via dev <ovs-dev@openvswitch.org>", "Reply-To": "Mark Michelson <mmichels@redhat.com>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "ovs-dev-bounces@openvswitch.org", "Sender": "\"dev\" <ovs-dev-bounces@openvswitch.org>" }, "content": "Move the \"Logical Flow Table Structure\" and \"Drop sampling\" sections\nfrom ovn-northd.8.xml into a new ovn-logical-flows.7.xml manpage.\nThis separates the logical flow pipeline reference documentation from\nthe ovn-northd daemon description. A cross-reference stub remains in\novn-northd(8) pointing readers to the new manpage.\n\nAssisted-by: Claude Code (Claude Opus 4.6)\nSigned-off-by: Mark Michelson <mmichels@redhat.com>\n---\n northd/automake.mk | 3 +\n northd/ovn-logical-flows.7.xml | 6080 ++++++++++++++++++++++++++++++++\n northd/ovn-northd.8.xml | 6065 +------------------------------\n 3 files changed, 6088 insertions(+), 6060 deletions(-)\n create mode 100644 northd/ovn-logical-flows.7.xml", "diff": "diff --git a/northd/automake.mk b/northd/automake.mk\nindex 8cd4fb3a1..47142a5b0 100644\n--- a/northd/automake.mk\n+++ b/northd/automake.mk\n@@ -71,3 +71,6 @@ northd_ovn_northd_LDADD = \\\n man_MANS += northd/ovn-northd.8\n EXTRA_DIST += northd/ovn-northd.8.xml\n CLEANFILES += northd/ovn-northd.8\n+man_MANS += northd/ovn-logical-flows.7\n+EXTRA_DIST += northd/ovn-logical-flows.7.xml\n+CLEANFILES += northd/ovn-logical-flows.7\ndiff --git a/northd/ovn-logical-flows.7.xml b/northd/ovn-logical-flows.7.xml\nnew file mode 100644\nindex 000000000..b8d353695\n--- /dev/null\n+++ b/northd/ovn-logical-flows.7.xml\n@@ -0,0 +1,6080 @@\n+<?xml version=\"1.0\" encoding=\"utf-8\"?>\n+<manpage program=\"ovn-logical-flows\" section=\"7\" title=\"OVN Logical Flows\">\n+ <h1>Name</h1>\n+ <p>ovn-logical-flows -- OVN logical flow table reference</p>\n+\n+ <h1>Description</h1>\n+ <p>\n+ This document describes the logical flow tables that\n+ <code>ovn-northd</code>(8) populates in the\n+ <code>OVN_Southbound</code> database. It covers both logical\n+ switch and logical router datapath pipelines, as well as\n+ drop sampling behavior.\n+ </p>\n+\n+ <h1>Logical Flow Table Structure</h1>\n+\n+ <p>\n+ One of the main purposes of <code>ovn-northd</code> is to populate the\n+ <code>Logical_Flow</code> table in the <code>OVN_Southbound</code>\n+ database. This section describes how <code>ovn-northd</code> does this\n+ for switch and router logical datapaths.\n+ </p>\n+\n+ <h2>Logical Switch Datapaths</h2>\n+\n+ <h3>Ingress Table 0: Admission Control and Ingress Port Security check</h3>\n+\n+ <p>\n+ Ingress table 0 contains these logical flows:\n+ </p>\n+\n+ <ul>\n+ <li>\n+ Priority 100 flows to drop packets with VLAN tags or multicast Ethernet\n+ source addresses.\n+ </li>\n+\n+ <li>\n+ For each disabled logical port, a priority 100 flow is added which\n+ matches on all packets and applies the action\n+ <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code> so that the packets are\n+ dropped in the next stage.\n+ </li>\n+\n+ <li>\n+ <p>\n+ For each logical port that's defined as a target of routing protocol\n+ redirecting (via <code>routing-protocol-redirect</code> option set on\n+ Logical Router Port), a filter is set in place that disallows\n+ following traffic exiting this port:\n+ </p>\n+ <ul>\n+ <li>\n+ ARP replies\n+ </li>\n+ <li>\n+ IPv6 Neighbor Discovery - Router Advertisements\n+ </li>\n+ <li>\n+ IPv6 Neighbor Discovery - Neighbor Advertisements\n+ </li>\n+ </ul>\n+ <p>\n+ Since this port shares IP and MAC addresses with the Logical Router\n+ Port, we wan't to prevent duplicate replies and advertisements. This\n+ is achieved by a rule with priority 80 that sets\n+ <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code>.\n+ </p>\n+ </li>\n+\n+ <li>\n+ For each logical switch that has connected physical ports\n+ (localnet or l2gateway) and is also connected to a distributed router,\n+ filtering rules are added for ARP requests coming from localnet or\n+ l2gateway ports, allowed for processing on gateway chassis.\n+ The <code>REGBIT_EXT_ARP</code> register is set for all ARP requests\n+ originating from physical ports with priority 75 flow.\n+ </li>\n+\n+ <li>\n+ For each (enabled) vtep logical port, a priority 70 flow is added which\n+ matches on all packets and applies the action\n+ <code>next(pipeline=ingress, table=S_SWITCH_IN_L3_LKUP) = 1;</code>\n+ to skip most stages of ingress pipeline and go directly to ingress L2\n+ lookup table to determine the output port. Packets from VTEP (RAMP)\n+ switch should not be subjected to any ACL checks. Egress pipeline will\n+ do the ACL checks.\n+ </li>\n+\n+ <li>\n+ For each enabled logical port configured with qdisc queue id in the\n+ <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n+ db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+ db=\"OVN_Northbound\"/>, a priority 70 flow is added which\n+ matches on all packets and applies the action\n+ <code>set_queue(id);\n+ REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;\"</code>.\n+ </li>\n+\n+ <li>\n+ A priority 1 flow is added which matches on all packets for all the\n+ logical ports and applies the action\n+ <code>REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;</code> to\n+ evaluate the port security. The action <code>check_in_port_sec</code>\n+ applies the port security rules defined in the\n+ <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n+ db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n+ db=\"OVN_Northbound\"/> table.\n+ </li>\n+ </ul>\n+\n+ <h3>Ingress Table 1: Ingress Port Security - Apply</h3>\n+\n+ <p>\n+ For each logical switch port <var>P</var> of type router connected to a\n+ gw router a priority-120 flow that matches 'recirculated' icmp{4,6} error\n+ 'packet too big' and <code>eth.src == <var>D</var> &&\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/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml\nindex 4d6370da6..e5d460382 100644\n--- a/northd/ovn-northd.8.xml\n+++ b/northd/ovn-northd.8.xml\n@@ -255,6068 +255,13 @@\n </p>\n \n <h1>Logical Flow Table Structure</h1>\n-\n- <p>\n- One of the main purposes of <code>ovn-northd</code> is to populate the\n- <code>Logical_Flow</code> table in the <code>OVN_Southbound</code>\n- database. This section describes how <code>ovn-northd</code> does this\n- for switch and router logical datapaths.\n- </p>\n-\n- <h2>Logical Switch Datapaths</h2>\n-\n- <h3>Ingress Table 0: Admission Control and Ingress Port Security check</h3>\n-\n- <p>\n- Ingress table 0 contains these logical flows:\n- </p>\n-\n- <ul>\n- <li>\n- Priority 100 flows to drop packets with VLAN tags or multicast Ethernet\n- source addresses.\n- </li>\n-\n- <li>\n- For each disabled logical port, a priority 100 flow is added which\n- matches on all packets and applies the action\n- <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code> so that the packets are\n- dropped in the next stage.\n- </li>\n-\n- <li>\n- <p>\n- For each logical port that's defined as a target of routing protocol\n- redirecting (via <code>routing-protocol-redirect</code> option set on\n- Logical Router Port), a filter is set in place that disallows\n- following traffic exiting this port:\n- </p>\n- <ul>\n- <li>\n- ARP replies\n- </li>\n- <li>\n- IPv6 Neighbor Discovery - Router Advertisements\n- </li>\n- <li>\n- IPv6 Neighbor Discovery - Neighbor Advertisements\n- </li>\n- </ul>\n- <p>\n- Since this port shares IP and MAC addresses with the Logical Router\n- Port, we wan't to prevent duplicate replies and advertisements. This\n- is achieved by a rule with priority 80 that sets\n- <code>REGBIT_PORT_SEC_DROP\" = 1; next;\"</code>.\n- </p>\n- </li>\n-\n- <li>\n- For each logical switch that has connected physical ports\n- (localnet or l2gateway) and is also connected to a distributed router,\n- filtering rules are added for ARP requests coming from localnet or\n- l2gateway ports, allowed for processing on gateway chassis.\n- The <code>REGBIT_EXT_ARP</code> register is set for all ARP requests\n- originating from physical ports with priority 75 flow.\n- </li>\n-\n- <li>\n- For each (enabled) vtep logical port, a priority 70 flow is added which\n- matches on all packets and applies the action\n- <code>next(pipeline=ingress, table=S_SWITCH_IN_L3_LKUP) = 1;</code>\n- to skip most stages of ingress pipeline and go directly to ingress L2\n- lookup table to determine the output port. Packets from VTEP (RAMP)\n- switch should not be subjected to any ACL checks. Egress pipeline will\n- do the ACL checks.\n- </li>\n-\n- <li>\n- For each enabled logical port configured with qdisc queue id in the\n- <ref column=\"options:qdisc_queue_id\" table=\"Logical_Switch_Port\"\n- db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n- db=\"OVN_Northbound\"/>, a priority 70 flow is added which\n- matches on all packets and applies the action\n- <code>set_queue(id);\n- REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;\"</code>.\n- </li>\n-\n- <li>\n- A priority 1 flow is added which matches on all packets for all the\n- logical ports and applies the action\n- <code>REGBIT_PORT_SEC_DROP\" = check_in_port_sec(); next;</code> to\n- evaluate the port security. The action <code>check_in_port_sec</code>\n- applies the port security rules defined in the\n- <ref column=\"port_security\" table=\"Logical_Switch_Port\"\n- db=\"OVN_Northbound\"/> column of <ref table=\"Logical_Switch_Port\"\n- db=\"OVN_Northbound\"/> table.\n- </li>\n- </ul>\n-\n- <h3>Ingress Table 1: Ingress Port Security - Apply</h3>\n-\n- <p>\n- For each logical switch port <var>P</var> of type router connected to a\n- gw router a priority-120 flow that matches 'recirculated' icmp{4,6} error\n- 'packet too big' and <code>eth.src == <var>D</var> &&\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+ For a detailed description of the logical flow tables that\n+ <code>ovn-northd</code> populates in the\n+ <code>OVN_Southbound</code> database, including logical switch\n+ and router datapath pipelines and drop sampling behavior, see\n+ <code>ovn-logical-flows</code>(7).\n </p>\n \n- <ul>\n- <li>\n- <p>\n- For each NAT rule in the OVN Northbound database on a\n- distributed router, a priority-100 logical flow with match\n- <code>ip4.dst == <var>E</var> &&\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>\n", "prefixes": [ "ovs-dev", "3/5" ] }