get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.1/patches/2220894/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2220894,
    "url": "http://patchwork.ozlabs.org/api/1.1/patches/2220894/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/ovn/patch/20260408115243.2125880-1-dceara@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": "<20260408115243.2125880-1-dceara@redhat.com>",
    "date": "2026-04-08T11:52:43",
    "name": "[ovs-dev] northd: Don't forward IP multicast to routers without IGMP relay.",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "c1c0fab05372e6d2f5faca1e1b97d744a5939c5c",
    "submitter": {
        "id": 76591,
        "url": "http://patchwork.ozlabs.org/api/1.1/people/76591/?format=api",
        "name": "Dumitru Ceara",
        "email": "dceara@redhat.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/ovn/patch/20260408115243.2125880-1-dceara@redhat.com/mbox/",
    "series": [
        {
            "id": 499125,
            "url": "http://patchwork.ozlabs.org/api/1.1/series/499125/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/ovn/list/?series=499125",
            "date": "2026-04-08T11:52:43",
            "name": "[ovs-dev] northd: Don't forward IP multicast to routers without IGMP relay.",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/499125/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2220894/comments/",
    "check": "fail",
    "checks": "http://patchwork.ozlabs.org/api/patches/2220894/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<ovs-dev-bounces@openvswitch.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "ovs-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=DNwVvOti;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::137; helo=smtp4.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)",
            "smtp4.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=DNwVvOti",
            "smtp3.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com",
            "smtp3.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=DNwVvOti"
        ],
        "Received": [
            "from smtp4.osuosl.org (smtp4.osuosl.org [IPv6:2605:bc80:3010::137])\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 4frLzc5Q8dz1xy1\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 08 Apr 2026 21:53:00 +1000 (AEST)",
            "from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 0C4D04078C;\n\tWed,  8 Apr 2026 11:52:59 +0000 (UTC)",
            "from smtp4.osuosl.org ([127.0.0.1])\n by localhost (smtp4.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id j2OVbaHOGWaQ; Wed,  8 Apr 2026 11:52:55 +0000 (UTC)",
            "from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id 53E1440750;\n\tWed,  8 Apr 2026 11:52:55 +0000 (UTC)",
            "from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 38B74C054A;\n\tWed,  8 Apr 2026 11:52:55 +0000 (UTC)",
            "from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 45288C0549\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 11:52:54 +0000 (UTC)",
            "from localhost (localhost [127.0.0.1])\n by smtp3.osuosl.org (Postfix) with ESMTP id 308466084A\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 11:52:54 +0000 (UTC)",
            "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id yQZjejWxN3dd for <ovs-dev@openvswitch.org>;\n Wed,  8 Apr 2026 11:52:52 +0000 (UTC)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by smtp3.osuosl.org (Postfix) with ESMTPS id 1EEC960847\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 11:52:51 +0000 (UTC)",
            "from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-683-QoPQR41KPVSwCiFa9cTQpw-1; Wed,\n 08 Apr 2026 07:52:48 -0400",
            "from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17])\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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 18B4D18002D1\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 11:52:47 +0000 (UTC)",
            "from cecil-rh.redhat.com (unknown [10.44.33.24])\n by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 7BA2F1955D84; Wed,  8 Apr 2026 11:52:45 +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 smtp4.osuosl.org 53E1440750",
            "OpenDKIM Filter v2.11.0 smtp3.osuosl.org 1EEC960847"
        ],
        "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=170.10.129.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=dceara@redhat.com;\n receiver=<UNKNOWN>",
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp3.osuosl.org 1EEC960847",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775649169;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding;\n bh=GdlkUI2fGPVAcGiiUX2ZgB0xUzGR3lpBkoRxH1icgXk=;\n b=DNwVvOtipUUbVzi2INaGFE+3rqJNw8USOL75m8frGLmmIXT3ggVBfJo2ksJ+GS6i3gOuj5\n DYzcZNoR8ENZ5+kgDMbuygghAdS8ZTltutlXhNn2GqZb0ltsQSWEa2gNqpxOUVk+EJXYkt\n RDfelwg0XeiOBwZqNP8iDpWUfduW0ac=",
        "X-MC-Unique": "QoPQR41KPVSwCiFa9cTQpw-1",
        "X-Mimecast-MFC-AGG-ID": "QoPQR41KPVSwCiFa9cTQpw_1775649167",
        "To": "ovs-dev@openvswitch.org",
        "Date": "Wed,  8 Apr 2026 13:52:43 +0200",
        "Message-ID": "<20260408115243.2125880-1-dceara@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.17",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-MFC-PROC-ID": "I1b_3xto0-NTBZ4_qOUqysK2puSSJl8LsW5nlrOtxPk_1775649167",
        "X-Mimecast-Originator": "redhat.com",
        "Subject": "[ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to routers\n without IGMP relay.",
        "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": "Dumitru Ceara via dev <ovs-dev@openvswitch.org>",
        "Reply-To": "Dumitru Ceara <dceara@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": "Logical switches should not forward IP multicast packets towards\nconnected OVN logical routers if the router is not configured to relay\nIP multicast traffic (LR.options:mcast_relay=false).\n\nPreviously, a single priority 71 flow matched \"eth.mcast && (arp || ip)\"\nand sent all such traffic to _MC_flood, which includes all ports\n(including router ports).  This caused IP multicast packets to be\nforwarded to routers that would always drop them in lr_in_ip_input,\nwasting CPU cycles.  In topologies with hundreds of routers connected\nto logical switches, this can lead to the max resubmit limit (4K) being\nhit by such packets, unnecessarily overloading ovs-vswitchd.\n\nFix this by splitting the flow into three:\n - Priority 72: \"eth.mcast && (nd_na || nd_rs || nd_ra)\" -> _MC_flood\n   ND NA, Router Solicitation and Router Advertisement must still reach\n   routers: ND NA for neighbor learning, ND RS so routers can respond\n   with Router Advertisements, ND RA for proper IPv6 network operation.\n - Priority 71: \"eth.mcast && arp\" -> _MC_flood\n   ARP (including gratuitous ARP) still reaches all ports.\n - Priority 71: \"eth.mcast && ip\" -> _MC_flood_l2\n   IP multicast is only sent to non-router L2 ports, plus\n   _MC_mrouter_flood (if any connected router has relay enabled)\n   and _MC_static (if any port has mcast_flood=true).\n\nReported-at: https://redhat.atlassian.net/browse/FDP-2262\nAssisted-by: Claude, with model: claude-opus-4-6\nSigned-off-by: Dumitru Ceara <dceara@redhat.com>\n---\n northd/northd.c         |  37 +++++++-\n northd/ovn-northd.8.xml |  33 +++++--\n tests/ovn-northd.at     | 191 ++++++++++++++++++++++++++++++++++++----\n 3 files changed, 237 insertions(+), 24 deletions(-)",
    "diff": "diff --git a/northd/northd.c b/northd/northd.c\nindex b7239f4e20..92c1707817 100644\n--- a/northd/northd.c\n+++ b/northd/northd.c\n@@ -11020,10 +11020,45 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,\n                       lflow_ref);\n     }\n \n+    /* ND NA, Router Solicitation and Router Advertisement should be\n+     * flooded to all ports including routers.  ND NA is needed for\n+     * neighbor learning; ND RS must reach routers so they can respond\n+     * with Router Advertisements; ND RA must reach routers for proper\n+     * IPv6 network operation.\n+     */\n+    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,\n+                  \"eth.mcast && (nd_na || nd_rs || nd_ra)\",\n+                  \"outport = \\\"\"MC_FLOOD\"\\\"; output;\", lflow_ref);\n+\n+    /* ARP multicast should be flooded to all ports including routers. */\n     ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,\n-                  \"eth.mcast && (arp || ip)\",\n+                  \"eth.mcast && arp\",\n                   \"outport = \\\"\"MC_FLOOD\"\\\"; output;\", lflow_ref);\n \n+    /* IP multicast should not be forwarded to routers that don't have\n+     * IGMP relay enabled (mcast_relay=true).  Such routers will always\n+     * drop IP multicast in lr_in_ip_input anyway.\n+     */\n+    ds_clear(actions);\n+    if (mcast_sw_info->flood_relay) {\n+        ds_put_cstr(actions,\n+                    \"clone { \"\n+                        \"outport = \\\"\"MC_MROUTER_FLOOD\"\\\"; \"\n+                        \"output; \"\n+                    \"}; \");\n+    }\n+    if (mcast_sw_info->flood_static) {\n+        ds_put_cstr(actions,\n+                    \"clone { \"\n+                        \"outport = \\\"\"MC_STATIC\"\\\"; \"\n+                        \"output; \"\n+                    \"}; \");\n+    }\n+    ds_put_cstr(actions, \"outport = \\\"\"MC_FLOOD_L2\"\\\"; output;\");\n+    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,\n+                  \"eth.mcast && ip\",\n+                  ds_cstr(actions), lflow_ref);\n+\n     /* Non-{arp,ip} L2 multicast traffic should not be sent to router\n      * ports since these packets will be discarded in the router pipeline.\n      */\ndiff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml\nindex 9f2d118dd4..4d6370da6b 100644\n--- a/northd/ovn-northd.8.xml\n+++ b/northd/ovn-northd.8.xml\n@@ -2414,18 +2414,41 @@ output;\n       </li>\n \n       <li>\n-        A priority-72 flow that outputs all ARP requests and ND packets with\n-        an Ethernet broadcast or multicast <code>eth.dst</code> to the\n-        <code>MC_FLOOD_L2</code> multicast group if\n-        <code>other_config:broadcast-arps-to-all-routers=true</code>.\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-71 flow that outputs all ARP or IP packets with an Ethernet\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>\ndiff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\nindex 6230fd039a..7c2f53da69 100644\n--- a/tests/ovn-northd.at\n+++ b/tests/ovn-northd.at\n@@ -5863,7 +5863,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 192.168.1.1), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && nd_ns && nd.target == fe80::200:ff:fe00:101), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5877,7 +5879,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && nd_ns && nd.target == fe80::200:ff:fe00:201), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5899,7 +5903,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5915,7 +5921,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5939,7 +5947,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5957,7 +5967,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport = \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -5980,7 +5992,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -6002,7 +6016,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -6031,7 +6047,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01 && is_chassis_resident(\"cr-ro1-ls1\")), action=(outport = \"ls1-ro1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport = \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -8365,6 +8383,127 @@ OVN_CLEANUP_NORTHD\n AT_CLEANUP\n ])\n \n+OVN_FOR_EACH_NORTHD_NO_HV([\n+AT_SETUP([IP multicast flood without IGMP relay])\n+AT_KEYWORDS([mcast_relay])\n+ovn_start\n+\n+check ovn-nbctl lr-add lr0\n+check ovn-nbctl ls-add ls0\n+\n+check ovn-nbctl lrp-add lr0 lrp0 00:00:00:00:00:01 10.0.0.1/24 fe80::1/64\n+check ovn-nbctl lsp-add-router-port ls0 lsp0-router lrp0\n+\n+check ovn-nbctl lsp-add ls0 lsp0 -- \\\n+    lsp-set-addresses lsp0 \"00:00:00:00:00:02 10.0.0.2\"\n+\n+dnl IP multicast packet from lsp0.\n+mcast_pkt='inport == \"lsp0\" && eth.src == 00:00:00:00:00:02 && eth.dst == 01:00:5e:00:01:2a && ip4.src == 10.0.0.2 && ip4.dst == 239.0.1.42 && ip.ttl == 64 && udp.src == 42 && udp.dst == 43'\n+\n+dnl ARP broadcast from lsp0.\n+arp_pkt='inport == \"lsp0\" && eth.src == 00:00:00:00:00:02 && eth.dst == ff:ff:ff:ff:ff:ff && arp.op == 1 && arp.sha == 00:00:00:00:00:02 && arp.spa == 10.0.0.2 && arp.tha == 00:00:00:00:00:00 && arp.tpa == 10.0.0.3'\n+\n+dnl Gratuitous ND NA multicast from lsp0.\n+nd_na_pkt='inport == \"lsp0\" && eth.src == 00:00:00:00:00:02 && eth.dst == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst == ff02::1 && icmp6.type == 136 && nd.target == fe80::200:ff:fe00:2'\n+\n+dnl Router solicitation multicast from lsp0.\n+nd_rs_pkt='inport == \"lsp0\" && eth.src == 00:00:00:00:00:02 && eth.dst == 33:33:00:00:00:02 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst == ff02::2 && icmp6.type == 133 && ip.ttl == 255'\n+\n+dnl Router advertisement multicast from lsp0.\n+nd_ra_pkt='inport == \"lsp0\" && eth.src == 00:00:00:00:00:02 && eth.dst == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst == ff02::1 && icmp6.type == 134 && ip.ttl == 255'\n+\n+dnl Scenario 1: default, no relay, no snooping.\n+dnl The eth.mcast && ip flow should use _MC_flood_l2 not _MC_flood.\n+check ovn-nbctl --wait=sb sync\n+\n+ovn-sbctl dump-flows ls0 > lsflows\n+AT_CAPTURE_FILE([lsflows])\n+AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows | grep -e 'priority=71' -e 'priority=72' | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n+])\n+\n+dnl Verify packet forwarding: IP multicast should not reach the router\n+dnl port, while ARP, ND NA, ND RS and ND RA should.\n+AT_CHECK([ovn_trace ls0 \"$mcast_pkt\" | grep 'outport=\"lsp0-router\"'], [1])\n+AT_CHECK([ovn_trace ls0 \"$arp_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_na_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_rs_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_ra_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+\n+dnl Scenario 2: relay enabled on the router but snooping not enabled on the switch.\n+dnl No priority 80 flow is installed because build_mcast_flood_lswitch returns\n+dnl early when snooping is disabled, so the priority 71 flow is the only path\n+dnl for IP multicast to reach relay-enabled routers via _MC_mrouter_flood.\n+check ovn-nbctl set logical_router lr0 options:mcast_relay=\"true\"\n+check ovn-nbctl --wait=sb sync\n+\n+ovn-sbctl dump-flows ls0 > lsflows2\n+AT_CAPTURE_FILE([lsflows2])\n+AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows2 | grep -e 'priority=71' -e 'priority=72' | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n+])\n+\n+dnl Verify packet forwarding: all packet types should reach the router port.\n+AT_CHECK([ovn_trace ls0 \"$mcast_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$arp_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_na_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_rs_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_ra_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+\n+dnl Scenario 3: relay enabled on the router and snooping enabled on the switch.\n+dnl The eth.mcast && ip flow should include _MC_mrouter_flood for relay-enabled\n+dnl router ports plus _MC_flood_l2 for regular ports.\n+check ovn-nbctl set logical_switch ls0 other_config:mcast_snoop=\"true\"\n+check ovn-nbctl --wait=sb sync\n+\n+ovn-sbctl dump-flows ls0 > lsflows3\n+AT_CAPTURE_FILE([lsflows3])\n+AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows3 | grep -e 'priority=71' -e 'priority=72' | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n+])\n+\n+dnl Verify packet forwarding: all packet types should reach the router port.\n+AT_CHECK([ovn_trace ls0 \"$mcast_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$arp_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_na_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_rs_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_ra_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+\n+dnl Scenario 4: also enable flood_unregistered on the switch.\n+dnl The priority 71 flow should still have _MC_mrouter_flood and _MC_flood_l2.\n+dnl There should be no priority 80 flow for ip4.mcast || ip6.mcast because\n+dnl flood_unregistered causes build_mcast_flood_lswitch to return early.\n+check ovn-nbctl set logical_switch ls0 other_config:mcast_flood_unregistered=\"true\"\n+check ovn-nbctl --wait=sb sync\n+\n+ovn-sbctl dump-flows ls0 > lsflows4\n+AT_CAPTURE_FILE([lsflows4])\n+AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows4 | grep -e 'priority=71' -e 'priority=72' | ovn_strip_lflows], [0], [dnl\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n+])\n+\n+dnl Verify there is no priority 80 flow for ip4.mcast || ip6.mcast when flood_unregistered is set.\n+AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows4 | grep -e 'priority=80' | grep -F 'ip4.mcast || ip6.mcast'], [1])\n+\n+dnl Verify packet forwarding: all packet types should reach the router port.\n+AT_CHECK([ovn_trace ls0 \"$mcast_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$arp_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_na_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_rs_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+AT_CHECK([ovn_trace ls0 \"$nd_ra_pkt\" | grep -q 'outport=\"lsp0-router\"'])\n+\n+OVN_CLEANUP_NORTHD\n+AT_CLEANUP\n+])\n+\n OVN_FOR_EACH_NORTHD_NO_HV_PARALLELIZATION([\n AT_SETUP([ACLs after lb])\n AT_KEYWORDS([acl])\n@@ -9678,7 +9817,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=100  , match=(reg8[[23]] == 1), action=(output;)\n   table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == $svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)\n@@ -9714,7 +9855,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)\n@@ -9749,7 +9892,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)\n@@ -9785,7 +9930,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(drop;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"sw0p1\"), action=(drop;)\n@@ -9821,7 +9968,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(drop;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"sw0p1\"), action=(drop;)\n@@ -9861,7 +10010,9 @@ ovn_strip_lflows ], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)\n   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == \"none\"), action=(drop;)\n   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)\n@@ -14201,7 +14352,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" publicflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:ff:02 && is_chassis_resident(\"cr-lr0-public\")), action=(outport = \"public-lr0\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 30:54:00:00:00:03 && is_chassis_resident(\"sw0-port1\")), action=(outport = \"public-lr0\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.10), action=(clone {outport = \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.100), action=(clone {outport = \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -14379,7 +14532,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" publicflows | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 00:00:00:00:ff:02 && is_chassis_resident(\"cr-public-lr0\")), action=(outport = \"public-lr0\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 30:54:00:00:00:03 && is_chassis_resident(\"sw0-port1\")), action=(outport = \"public-lr0\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), action=(outport = \"_MC_flood_l2\"; output;)\n-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && arp), action=(outport = \"_MC_flood\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), action=(outport = \"_MC_flood_l2\"; output;)\n+  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src == {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.10 && !is_chassis_resident(\"cr-public-lr0\")), action=(clone {outport = \"cr-public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n   table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && arp.op == 1 && arp.tpa == 172.168.0.10 && is_chassis_resident(\"cr-public-lr0\")), action=(clone {outport = \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n@@ -14541,7 +14696,7 @@ AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep -E \"tcp.dst == 179\n AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep \"arp.op == 2 && arp.tpa == 172.16.1.1\" | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=100  , match=(arp.op == 2 && arp.tpa == 172.16.1.1), action=(clone { outport = \"lsp-bgp\"; output; }; outport = \"ls-lr\"; output;)\n ])\n-AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep \"&& nd_na\" | ovn_strip_lflows], [0], [dnl\n+AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep \"ip6.dst == .* && nd_na\" | ovn_strip_lflows], [0], [dnl\n   table=??(ls_in_l2_lkup      ), priority=100  , match=(ip6.dst == fe80::ac:10ff:fe01:1 && nd_na), action=(clone { outport = \"lsp-bgp\"; output; }; outport = \"ls-lr\"; output;)\n ])\n \n",
    "prefixes": [
        "ovs-dev"
    ]
}