[{"id":3674751,"web_url":"http://patchwork.ozlabs.org/comment/3674751/","msgid":"<adZO3QTF-wX6vsYh@lore-desk>","list_archive_url":null,"date":"2026-04-08T12:49:33","subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers without IGMP relay.","submitter":{"id":73083,"url":"http://patchwork.ozlabs.org/api/people/73083/","name":"Lorenzo Bianconi","email":"lorenzo.bianconi@redhat.com"},"content":"> Logical switches should not forward IP multicast packets towards\n> connected OVN logical routers if the router is not configured to relay\n> IP multicast traffic (LR.options:mcast_relay=false).\n> \n> Previously, a single priority 71 flow matched \"eth.mcast && (arp || ip)\"\n> and sent all such traffic to _MC_flood, which includes all ports\n> (including router ports).  This caused IP multicast packets to be\n> forwarded to routers that would always drop them in lr_in_ip_input,\n> wasting CPU cycles.  In topologies with hundreds of routers connected\n> to logical switches, this can lead to the max resubmit limit (4K) being\n> hit by such packets, unnecessarily overloading ovs-vswitchd.\n> \n> Fix 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> \n> Reported-at: https://redhat.atlassian.net/browse/FDP-2262\n> Assisted-by: Claude, with model: claude-opus-4-6\n> Signed-off-by: Dumitru Ceara <dceara@redhat.com>\n\nAcked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>\n\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(-)\n> \n> diff --git a/northd/northd.c b/northd/northd.c\n> index 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>       */\n> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml\n> index 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>\n> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\n> index 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> -- \n> 2.53.0\n>","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=Jd/xsLNJ;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=google header.b=GSLxHKTB;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::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=Jd/xsLNJ;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key)\n header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=google\n header.b=GSLxHKTB","smtp1.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp1.osuosl.org;\n dkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com\n header.a=rsa-sha256 header.s=mimecast20190719 header.b=Jd/xsLNJ;\n dkim=pass (2048-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=google header.b=GSLxHKTB"],"Received":["from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::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 4frNFL103Kz1xv0\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 08 Apr 2026 22:49:57 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp2.osuosl.org (Postfix) with ESMTP id E5E6440108;\n\tWed,  8 Apr 2026 12:49:49 +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 pfH5mU8Yt3wr; Wed,  8 Apr 2026 12:49:47 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp2.osuosl.org (Postfix) with ESMTPS id 65D5A400C2;\n\tWed,  8 Apr 2026 12:49:47 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id DB39CC054A;\n\tWed,  8 Apr 2026 12:49:46 +0000 (UTC)","from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\n by lists.linuxfoundation.org (Postfix) with ESMTP id D765EC0549\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 12:49:45 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id BF15D81DBF\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 12:49:45 +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 tmXAy3G04w4R for <ovs-dev@openvswitch.org>;\n Wed,  8 Apr 2026 12:49:43 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 39E75817F5\n for <ovs-dev@openvswitch.org>; Wed,  8 Apr 2026 12:49:42 +0000 (UTC)","from mail-wm1-f72.google.com (mail-wm1-f72.google.com\n [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-164-_K6LqqXkPwiNLREXdLNOKw-1; Wed, 08 Apr 2026 08:49:39 -0400","by mail-wm1-f72.google.com with SMTP id\n 5b1f17b1804b1-488c2764f83so8380085e9.2\n for <ovs-dev@openvswitch.org>; Wed, 08 Apr 2026 05:49:38 -0700 (PDT)","from localhost (net-37-119-153-93.cust.vodafonedsl.it.\n [37.119.153.93]) by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-488c5325dd5sm31104195e9.2.2026.04.08.05.49.34\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 08 Apr 2026 05:49:34 -0700 (PDT)"],"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 65D5A400C2","OpenDKIM Filter v2.11.0 smtp1.osuosl.org 39E75817F5"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com;\n envelope-from=lorenzo.bianconi@redhat.com; receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp1.osuosl.org 39E75817F5","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775652581;\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 in-reply-to:in-reply-to:references:references;\n bh=BVGqnx2bfCpkNbZJmuYUCtFNEj+oWPnicrZjRaoknrE=;\n b=Jd/xsLNJ0ynT9pvnlMu3jUoQgtr9sjRWXI2vxfCuEvZcjB3LzCl9ZHB9/nH891TZIRcmah\n DorXJDVgru1SvrRvk2KNxVZuakL456NjxthNj3HVZvRVFQhNt8y+ujnGLlE6lipyv+soBY\n nOottazehaMJnyGz0NypBycN3Bg+4dA=","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com; s=google; t=1775652578; x=1776257378; darn=openvswitch.org;\n h=in-reply-to:content-disposition:mime-version:references:message-id\n :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to;\n bh=BVGqnx2bfCpkNbZJmuYUCtFNEj+oWPnicrZjRaoknrE=;\n b=GSLxHKTBPsFIDCuIIFoZu0WJQzeRfl5R1hXt4ITLR3rQFVfr//Xok6CHR3OMXQF8JE\n kB3cVk5QhnyDGh5W0EP2ob+BKnIK6AgWvUSdm0efGcVUszJekgeRBK7DBXA9LPBfHNtn\n m2FhnKqkaCN4UGYP0yReRwoTBIviYx6xmD6AD6YyTxa5o1MSVd2nFXokX7OAZyZtuoV+\n 80E0NUCJTOJC0w/KATm7I56KIdYHPRNLrR7Bxm6gz7BINJB5uo259SifIpT9XcHP3ii6\n yYNKS8FSobMu8bpMFpcNJW6a1MI2GXm77JYnh7iTNfiWeTXlK5qUcthZhzTjAoBfqspk\n 7Gmw=="],"X-MC-Unique":"_K6LqqXkPwiNLREXdLNOKw-1","X-Mimecast-MFC-AGG-ID":"_K6LqqXkPwiNLREXdLNOKw_1775652578","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775652578; x=1776257378;\n h=in-reply-to:content-disposition:mime-version:references:message-id\n :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=BVGqnx2bfCpkNbZJmuYUCtFNEj+oWPnicrZjRaoknrE=;\n b=H8OxttTJAOQNLDmQBpSQdO8CJs1uB8LB6z6hW9IPjyhWZa0XysNTymjbJ4DKoJmYeP\n YomPIAMFM680GXMgMmPlwSeFOXmlQ3MFdcHlDUMXII33NJ+I8FRJYQgW0D/MhiAL7oqQ\n pFAgO8ZwvWfvoR2fAU4aF9i7JCBevhVlkcPftSj/HeKshN6GfhXRTfBV59O/5KDhiJCX\n A+T4n0c+jhldHROgLWKKrCaasQlz1fIHyK2LVYX+T7QunqSmUkQx8SgADmd06Xbh41ni\n 2TIvhwLlHdFA4lwBG4Tuq/o3288fu8ZPbTkmPYchmfMpkbeuNKvNLQAGHT5GI5q5Gear\n TleA==","X-Gm-Message-State":"AOJu0YykBqwzjENy94l5CV4RkXdNxFHb9EGrv7WSEcUjdd9Ut7BkU2Mo\n HKK3THmONvs6a7TeHu/loXdqrso/KcOFueOPofL+Y5mphEAU0ZLY+qc2BQriUpEtS9njb+shu/m\n yKQ8zXaV0qHEcKj8L6gEKZBiHoGDq5B6xq/kCwfZRodir0NVrOIUDfRODE+E=","X-Gm-Gg":"AeBDieu687XFhVpVwxO4MVT1EsILf14pjPpFNTWEiHpZqARhwU76G2kVD/29K/CCfJC\n pffUof4vlPGTfj7z0OWH7On6yrJzUcwcBz4TAM5D3ol+uRMXGx96FXMtmzk/U2QDUoFOvaooNEX\n uiVqPAy7BIn0/m6NDCB6O5QebdbyEbVhlgwXcnOZaQDvYWl4GxU4ViVt6XwG3+VsTEZlFuqJ3bh\n AHL/TFTaWAs3GKr5JmsnBv8FR3sbQtYnBg8RtPx6wZUsmDRVPscE7ogbh7vmZAI+3fVAb0cVWaV\n MS5kcMiuNTjp+KpOeLhHo3w5Os6lxZQASWMufBu9lQvBa/X8P7w4zqn1e4FBlPOPY4REIhdiJwK\n 7xVy/p5VoU/BjOpcCVltEy/rzIsLaQovhpT3LkjgFXxApAcOJ8HvQoLNT+MIFz0oqvwbE/A==","X-Received":["by 2002:a05:600c:4e86:b0:480:4a8f:2d5c with SMTP id\n 5b1f17b1804b1-488997c9b69mr277734055e9.29.1775652577256;\n Wed, 08 Apr 2026 05:49:37 -0700 (PDT)","by 2002:a05:600c:4e86:b0:480:4a8f:2d5c with SMTP id\n 5b1f17b1804b1-488997c9b69mr277733245e9.29.1775652576102;\n Wed, 08 Apr 2026 05:49:36 -0700 (PDT)"],"Date":"Wed, 8 Apr 2026 14:49:33 +0200","To":"Dumitru Ceara <dceara@redhat.com>","Cc":"ovs-dev@openvswitch.org","Message-ID":"<adZO3QTF-wX6vsYh@lore-desk>","References":"<20260408115243.2125880-1-dceara@redhat.com>","MIME-Version":"1.0","In-Reply-To":"<20260408115243.2125880-1-dceara@redhat.com>","X-Content-Filtered-By":"Mailman/MimeDel 2.1.30","Subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers 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":"Lorenzo Bianconi via dev <ovs-dev@openvswitch.org>","Reply-To":"Lorenzo Bianconi <lorenzo.bianconi@redhat.com>","Content-Type":"multipart/mixed; boundary=\"===============0900529504389321337==\"","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}},{"id":3675173,"web_url":"http://patchwork.ozlabs.org/comment/3675173/","msgid":"<CALVEqe6oy3Y+8ATDEXF1Ozs43dobpHJjiG0Wb7aWhfMS5Es=MQ@mail.gmail.com>","list_archive_url":null,"date":"2026-04-09T08:33:00","subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers without IGMP relay.","submitter":{"id":83634,"url":"http://patchwork.ozlabs.org/api/people/83634/","name":"Ales Musil","email":"amusil@redhat.com"},"content":"On Wed, Apr 8, 2026 at 2:50 PM Lorenzo Bianconi via dev <\novs-dev@openvswitch.org> wrote:\n\n> > Logical switches should not forward IP multicast packets towards\n> > connected OVN logical routers if the router is not configured to relay\n> > IP multicast traffic (LR.options:mcast_relay=false).\n> >\n> > Previously, a single priority 71 flow matched \"eth.mcast && (arp || ip)\"\n> > and sent all such traffic to _MC_flood, which includes all ports\n> > (including router ports).  This caused IP multicast packets to be\n> > forwarded to routers that would always drop them in lr_in_ip_input,\n> > wasting CPU cycles.  In topologies with hundreds of routers connected\n> > to logical switches, this can lead to the max resubmit limit (4K) being\n> > hit by such packets, unnecessarily overloading ovs-vswitchd.\n> >\n> > Fix 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> >\n> > Reported-at: https://redhat.atlassian.net/browse/FDP-2262\n> > Assisted-by: Claude, with model: claude-opus-4-6\n> > Signed-off-by: Dumitru Ceara <dceara@redhat.com>\n>\n> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>\n>\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(-)\n> >\n> > diff --git a/northd/northd.c b/northd/northd.c\n> > index b7239f4e20..92c1707817 100644\n> > --- a/northd/northd.c\n> > +++ b/northd/northd.c\n> > @@ -11020,10 +11020,45 @@ build_lswitch_destination_lookup_bmcast(struct\n> 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> */\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\n> pipeline.\n> >       */\n> > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml\n> > index 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\n> 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\n> Advertisement),\n> > +        ND RS (Router Solicitation) and ND RA (Router Advertisement)\n> packets\n> > +        with an Ethernet broadcast or multicast <code>eth.dst</code> to\n> 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\n> 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\n> Ethernet\n> > +        A priority-72 flow that outputs all ARP requests and ND NS\n> (Neighbor\n> > +        Solicitation) packets with an Ethernet broadcast or multicast\n> > +        <code>eth.dst</code> to the <code>MC_FLOOD_L2</code> multicast\n> group\n> > +        if\n> <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\n> cloned to\n> > +        the <code>MC_MROUTER_FLOOD</code> multicast group (which\n> 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\n> multicast\n> > +        from being unnecessarily forwarded to routers that would drop\n> it.\n> > +      </li>\n> > +\n> >        <li>\n> >          A priority-70 flow that outputs all packets with an Ethernet\n> broadcast\n> >          or multicast <code>eth.dst</code> to the\n> <code>MC_FLOOD_L2</code>\n> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at\n> > index 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 |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 192.168.1.1), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && nd_ns && nd.target == fe80::200:ff:fe00:101), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5877,7 +5879,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && nd_ns && nd.target == fe80::200:ff:fe00:201), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5899,7 +5903,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5915,7 +5921,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5939,7 +5947,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5957,7 +5967,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls2_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:01), action=(outport = \"ls2-ro2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"vm2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:02:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 192.168.2.1), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 20.0.0.100), action=(clone {outport =\n> \"ls2-ro2\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -5980,7 +5992,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -6002,7 +6016,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -6031,7 +6047,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" ls1_lflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01 && is_chassis_resident(\"cr-ro1-ls1\")), action=(outport =\n> \"ls1-ro1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:02), action=(outport = \"vm1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:01:01} && eth.dst == ff:ff:ff:ff:ff:ff && (arp.op == 1 ||\n> rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.100), action=(clone {outport =\n> \"ls1-ro1\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 10.0.0.200), action=(clone {outport =\n> \"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\n> 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\n> == 01:00:5e:00:01:2a && ip4.src == 10.0.0.2 && ip4.dst == 239.0.1.42 &&\n> 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 ==\n> ff:ff:ff:ff:ff:ff && arp.op == 1 && arp.sha == 00:00:00:00:00:02 && arp.spa\n> == 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\n> == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==\n> 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\n> == 33:33:00:00:00:02 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==\n> 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\n> == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==\n> 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\n> 'priority=72' | ovn_strip_lflows], [0], [dnl\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (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\"'],\n> [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\n> the switch.\n> > +dnl No priority 80 flow is installed because build_mcast_flood_lswitch\n> returns\n> > +dnl early when snooping is disabled, so the priority 71 flow is the\n> only path\n> > +dnl for IP multicast to reach relay-enabled routers via\n> _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\n> 'priority=72' | ovn_strip_lflows], [0], [dnl\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport =\n> \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (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\n> 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\n> switch.\n> > +dnl The eth.mcast && ip flow should include _MC_mrouter_flood for\n> 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\n> 'priority=72' | ovn_strip_lflows], [0], [dnl\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport =\n> \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (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\n> 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\n> _MC_flood_l2.\n> > +dnl There should be no priority 80 flow for ip4.mcast || ip6.mcast\n> because\n> > +dnl flood_unregistered causes build_mcast_flood_lswitch to return early.\n> > +check ovn-nbctl set logical_switch ls0\n> 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\n> 'priority=72' | ovn_strip_lflows], [0], [dnl\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(clone { outport = \"_MC_mrouter_flood\"; output; }; outport =\n> \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (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\n> flood_unregistered is set.\n> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows4 | grep -e 'priority=80' |\n> grep -F 'ip4.mcast || ip6.mcast'], [1])\n> > +\n> > +dnl Verify packet forwarding: all packet types should reach the router\n> 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]] ==\n> 1), action=(output;)\n> >    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst ==\n> $svc_monitor_mac && (tcp || icmp || icmp6)),\n> action=(handle_svc_check(inport);)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),\n> action=(output;)\n> > @@ -9714,7 +9855,9 @@ ovn_strip_lflows ], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),\n> action=(output;)\n> > @@ -9749,7 +9892,9 @@ ovn_strip_lflows ], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),\n> action=(output;)\n> > @@ -9785,7 +9930,9 @@ ovn_strip_lflows ], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(drop;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"sw0p1\"), action=(drop;)\n> > @@ -9821,7 +9968,9 @@ ovn_strip_lflows ], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(drop;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"sw0p1\"), action=(drop;)\n> > @@ -9861,7 +10010,9 @@ ovn_strip_lflows ], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:01:01), action=(outport = \"sw0p1\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:02:02), action=(outport = \"sw0p2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_unknown   ), priority=0    , match=(1),\n> action=(output;)\n> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==\n> \"none\"), action=(drop;)\n> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),\n> action=(output;)\n> > @@ -14201,7 +14352,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" publicflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:ff:02 && is_chassis_resident(\"cr-lr0-public\")), action=(outport\n> = \"public-lr0\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 30:54:00:00:00:03 && is_chassis_resident(\"sw0-port1\")), action=(outport =\n> \"public-lr0\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff &&\n> (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\";\n> output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 172.168.0.10), action=(clone {outport =\n> \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 172.168.0.100), action=(clone {outport =\n> \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -14379,7 +14532,9 @@ AT_CHECK([grep \"ls_in_l2_lkup\" publicflows |\n> ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 00:00:00:00:ff:02 && is_chassis_resident(\"cr-public-lr0\")), action=(outport\n> = \"public-lr0\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==\n> 30:54:00:00:00:03 && is_chassis_resident(\"sw0-port1\")), action=(outport =\n> \"public-lr0\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),\n> action=(outport = \"_MC_flood_l2\"; output;)\n> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> (arp || ip)), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> arp), action=(outport = \"_MC_flood\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&\n> ip), action=(outport = \"_MC_flood_l2\"; output;)\n> > +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast &&\n> (nd_na || nd_rs || nd_ra)), action=(outport = \"_MC_flood\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=75   , match=(eth.src ==\n> {00:00:00:00:ff:02, 30:54:00:00:00:03} && eth.dst == ff:ff:ff:ff:ff:ff &&\n> (arp.op == 1 || rarp.op == 3 || nd_ns)), action=(outport = \"_MC_flood_l2\";\n> output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 172.168.0.10 &&\n> !is_chassis_resident(\"cr-public-lr0\")), action=(clone {outport =\n> \"cr-public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> >    table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0\n> && arp.op == 1 && arp.tpa == 172.168.0.10 &&\n> is_chassis_resident(\"cr-public-lr0\")), action=(clone {outport =\n> \"public-lr0\"; output; }; outport = \"_MC_flood_l2\"; output;)\n> > @@ -14541,7 +14696,7 @@ AT_CHECK([ovn-sbctl dump-flows ls | grep\n> 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\n> == 2 && arp.tpa == 172.16.1.1\" | ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=100  , match=(arp.op == 2 &&\n> arp.tpa == 172.16.1.1), action=(clone { outport = \"lsp-bgp\"; output; };\n> outport = \"ls-lr\"; output;)\n> >  ])\n> > -AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep \"&&\n> nd_na\" | ovn_strip_lflows], [0], [dnl\n> > +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep \"ip6.dst\n> == .* && nd_na\" | ovn_strip_lflows], [0], [dnl\n> >    table=??(ls_in_l2_lkup      ), priority=100  , match=(ip6.dst ==\n> fe80::ac:10ff:fe01:1 && nd_na), action=(clone { outport = \"lsp-bgp\";\n> output; }; outport = \"ls-lr\"; output;)\n> >  ])\n> >\n> > --\n> > 2.53.0\n> >\n> _______________________________________________\n> dev mailing list\n> dev@openvswitch.org\n> https://mail.openvswitch.org/mailman/listinfo/ovs-dev\n\n\nLooks good to me, thanks.\nAcked-by: Ales Musil <amusil@redhat.com>","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=g4hfmdye;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org\n (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=patchwork.ozlabs.org)","smtp1.osuosl.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=g4hfmdye","smtp2.osuosl.org; dmarc=pass (p=quarantine dis=none)\n header.from=redhat.com","smtp2.osuosl.org; dkim=pass (1024-bit key,\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=g4hfmdye"],"Received":["from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138])\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 4frtXW0QGMz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 09 Apr 2026 18:34:50 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp1.osuosl.org (Postfix) with ESMTP id 9D6D082861;\n\tThu,  9 Apr 2026 08:34:46 +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 mpVnKpj8ta63; Thu,  9 Apr 2026 08:34:43 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org\n [IPv6:2605:bc80:3010:104::8cd3:938])\n\tby smtp1.osuosl.org (Postfix) with ESMTPS id 58FA982813;\n\tThu,  9 Apr 2026 08:34:43 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 3CEBEC054A;\n\tThu,  9 Apr 2026 08:34:43 +0000 (UTC)","from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 35D13C0549\n for <ovs-dev@openvswitch.org>; Thu,  9 Apr 2026 08:34:42 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp2.osuosl.org (Postfix) with ESMTP id 279654039B\n for <ovs-dev@openvswitch.org>; Thu,  9 Apr 2026 08:34:42 +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 7MZUGUy-1-Ii for <ovs-dev@openvswitch.org>;\n Thu,  9 Apr 2026 08:34:38 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp2.osuosl.org (Postfix) with ESMTPS id 39F4E400BA\n for <ovs-dev@openvswitch.org>; Thu,  9 Apr 2026 08:34:37 +0000 (UTC)","from mail-yw1-f199.google.com (mail-yw1-f199.google.com\n [209.85.128.199]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-316-gP549hHnMYGEvEYo9OVuaw-1; Thu, 09 Apr 2026 04:34:33 -0400","by mail-yw1-f199.google.com with SMTP id\n 00721157ae682-7a3715e9e69so13718247b3.0\n for <ovs-dev@openvswitch.org>; Thu, 09 Apr 2026 01:34:33 -0700 (PDT)"],"X-Virus-Scanned":["amavis at osuosl.org","amavis at osuosl.org"],"X-Comment":"SPF check N/A for local connections -\n client-ip=2605:bc80:3010:104::8cd3:938; helo=lists.linuxfoundation.org;\n envelope-from=ovs-dev-bounces@openvswitch.org; receiver=<UNKNOWN> ","DKIM-Filter":["OpenDKIM Filter v2.11.0 smtp1.osuosl.org 58FA982813","OpenDKIM Filter v2.11.0 smtp2.osuosl.org 39F4E400BA"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.124;\n helo=us-smtp-delivery-124.mimecast.com; envelope-from=amusil@redhat.com;\n receiver=<UNKNOWN>","DMARC-Filter":"OpenDMARC Filter v1.4.2 smtp2.osuosl.org 39F4E400BA","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1775723676;\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 in-reply-to:in-reply-to:references:references;\n bh=sHowmRy7jXqS05Z38Sahb+o6/ejL/N/haCjBkWJVf3A=;\n b=g4hfmdyehg+4Vk92D2Bkmcw+fdk7qUheYGoi0vFzyzaRO1A5iHpsQNZAJVr+qrBHBOVSpo\n OGCxkOE/SnZnkb7XsyCzoHpt5G2RpbAaIVJy/hPWiPyArygOq3W399naIuPqGkHrqUgvZj\n MEFQYhAgQgxVxhvUu2gYooS7jS11glo=","X-MC-Unique":"gP549hHnMYGEvEYo9OVuaw-1","X-Mimecast-MFC-AGG-ID":"gP549hHnMYGEvEYo9OVuaw_1775723673","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775723673; x=1776328473;\n h=cc:to:subject:message-id:date:from:in-reply-to:references\n :mime-version:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=sHowmRy7jXqS05Z38Sahb+o6/ejL/N/haCjBkWJVf3A=;\n b=XKI8kq+Y3A4cJVuoYdFSK5JUN6SiDm3NMIoENSLcHiS/HQK6m8xEoARQEuGgj/c0Bi\n VdzP1Vmj2KiW7fbfQPjAqCX+sD4lsFU+Fkqqscz9t+iHeJSWX8KVuYTZCEiisRLWuWfp\n T1DoMKsApKdoPMgQ8xvZrjfKV6YqeRoLY6rMBNfk7MpczVEbEbN83A91suKVrr75FlZ/\n J9v4UHOXkSlk2YZVYO8+VrWNILzOpaoRyS/aRlfkGTHf1x7Cm2rZqztfToRDnKLzHE2K\n pRo/ZjEzRSIiFG69b8XHAbvQS5vWdKEZrd8cfODBKUtbwJg9+Osw4Gs1HWbOH+YQX1tM\n Qwow==","X-Forwarded-Encrypted":"i=1;\n AJvYcCW64UxT7yTuIg8/fWyyJuR3ph3/uW6JF35LpGaYnObXEbqXuG1VkEWLIEcOeqpkQLDqCxzITbrX@openvswitch.org","X-Gm-Message-State":"AOJu0Yyq6qZ2GapStleNhbCWmNPgqnuYsjnkXGkatXkBIbpIdEDgsqTK\n zl9PxrnFe7Njmm/XXoGKhsQ8NDXvcEIdMjtovPJdLQ2VbQ+M1Dnz7T6ImKue9QzCxa4nPnehqrI\n I7oGcTljJQ0rV6mhVqLa4wAxCTKHBlnZe3JZbDMzrFJwEET5rxT4/M0Clj2G9twP7UP+9+oXQd5\n trVSTmC0hpo0Id+oXPAnEgJi/T30sc/quTkw==","X-Gm-Gg":"AeBDiesAZOl5NC7CRrhHnVOKlQn+V8pNz30DtGi93ouoWhHSdiNwTcvMastdjpXdpiF\n SJb2G+/I6clsYnU2kJ3bzxoyju4pZp26MjOvl2QVvMZd5f/tetQ1QyvyIZ9ri54iiFolhmhRYoH\n y15Ptkoz1EkhCL/mZ65uLzk3i+Jp7Q4Ewc2a47V74Vw+MDTTsF5xVSpy7c0O39NiWsScJ0CU2Bb\n atCH1hM3d6NaOGULVKODs97+0H8L+LTFf9Fh37pWVBOlwXgmD0o1Zq8H3tJlTxSLwBjl3zPJtAt\n AfK6hm9LPUVgmD6PYIbsQ1WbpZKTssnA39c8edRkOXNf8KkG0asHGhjWGP6N1hUOKX+BFi8JvKM\n y7K9dnc3Hwchj19tbCbtasnRDxucUAfGlub7jlnscGBaIKg==","X-Received":["by 2002:a53:c048:0:10b0:650:23d1:c90c with SMTP id\n 956f58d0204a3-65187274149mr1614276d50.43.1775723672860;\n Thu, 09 Apr 2026 01:34:32 -0700 (PDT)","by 2002:a53:c048:0:10b0:650:23d1:c90c with SMTP id\n 956f58d0204a3-65187274149mr1614256d50.43.1775723672186; Thu, 09 Apr 2026\n 01:34:32 -0700 (PDT)"],"MIME-Version":"1.0","References":"<20260408115243.2125880-1-dceara@redhat.com>\n <adZO3QTF-wX6vsYh@lore-desk>","In-Reply-To":"<adZO3QTF-wX6vsYh@lore-desk>","Date":"Thu, 9 Apr 2026 10:33:00 +0200","X-Gm-Features":"AQROBzCiZzV6O-I-eV9WFBcvVy68lb0nk8SNBGjD-8LSlsYVMKmNx56L_OuTOjk","Message-ID":"\n <CALVEqe6oy3Y+8ATDEXF1Ozs43dobpHJjiG0Wb7aWhfMS5Es=MQ@mail.gmail.com>","To":"Lorenzo Bianconi <lorenzo.bianconi@redhat.com>","Cc":"Dumitru Ceara <dceara@redhat.com>, ovs-dev@openvswitch.org","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"_Zh0aEIkIwXJL4uUluLiE2ypnweoUWkmNXSy2pUIF8U_1775723673","X-Mimecast-Originator":"redhat.com","X-Content-Filtered-By":"Mailman/MimeDel 2.1.30","Subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers 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":"Ales Musil via dev <ovs-dev@openvswitch.org>","Reply-To":"Ales Musil <amusil@redhat.com>","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}},{"id":3676545,"web_url":"http://patchwork.ozlabs.org/comment/3676545/","msgid":"<d6da52dd-c210-46b3-8ed0-03f7190b8fed@redhat.com>","list_archive_url":null,"date":"2026-04-13T08:15:33","subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers without IGMP relay.","submitter":{"id":76591,"url":"http://patchwork.ozlabs.org/api/people/76591/","name":"Dumitru Ceara","email":"dceara@redhat.com"},"content":"On 4/9/26 10:33 AM, Ales Musil wrote:\n> On Wed, Apr 8, 2026 at 2:50 PM Lorenzo Bianconi via dev <\n> ovs-dev@openvswitch.org> wrote:\n> \n>>> Logical switches should not forward IP multicast packets towards\n>>> connected OVN logical routers if the router is not configured to relay\n>>> IP multicast traffic (LR.options:mcast_relay=false).\n>>>\n>>> Previously, a single priority 71 flow matched \"eth.mcast && (arp || ip)\"\n>>> and sent all such traffic to _MC_flood, which includes all ports\n>>> (including router ports).  This caused IP multicast packets to be\n>>> forwarded to routers that would always drop them in lr_in_ip_input,\n>>> wasting CPU cycles.  In topologies with hundreds of routers connected\n>>> to logical switches, this can lead to the max resubmit limit (4K) being\n>>> hit by such packets, unnecessarily overloading ovs-vswitchd.\n>>>\n>>> Fix 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>>>\n>>> Reported-at: https://redhat.atlassian.net/browse/FDP-2262\n>>> Assisted-by: Claude, with model: claude-opus-4-6\n>>> Signed-off-by: Dumitru Ceara <dceara@redhat.com>\n>>\n>> Acked-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>\n>>\n\n...\n\n> \n> Looks good to me, thanks.\n> Acked-by: Ales Musil <amusil@redhat.com>\n> \n\nHi Lorenzo, Ales,\n\nThanks for the reviews!  Applied to main and all stable branches down to\n24.03.\n\nRegards,\nDumitru","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=ZR/YJAX7;\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=ZR/YJAX7","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=ZR/YJAX7"],"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 4fvKwg2f4Sz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 18:15:47 +1000 (AEST)","from localhost (localhost [127.0.0.1])\n\tby smtp4.osuosl.org (Postfix) with ESMTP id 1901D40FA1;\n\tMon, 13 Apr 2026 08:15:45 +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 bPcOJ2GUu-Se; Mon, 13 Apr 2026 08:15:43 +0000 (UTC)","from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56])\n\tby smtp4.osuosl.org (Postfix) with ESMTPS id 8FBEA40EFF;\n\tMon, 13 Apr 2026 08:15:43 +0000 (UTC)","from lf-lists.osuosl.org (localhost [127.0.0.1])\n\tby lists.linuxfoundation.org (Postfix) with ESMTP id 6A3B9C054A;\n\tMon, 13 Apr 2026 08:15:43 +0000 (UTC)","from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n by lists.linuxfoundation.org (Postfix) with ESMTP id 72D32C0549\n for <ovs-dev@openvswitch.org>; Mon, 13 Apr 2026 08:15:41 +0000 (UTC)","from localhost (localhost [127.0.0.1])\n by smtp3.osuosl.org (Postfix) with ESMTP id 6495260E66\n for <ovs-dev@openvswitch.org>; Mon, 13 Apr 2026 08:15:41 +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 LFQ-nNK-LsKI for <ovs-dev@openvswitch.org>;\n Mon, 13 Apr 2026 08:15:40 +0000 (UTC)","from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by smtp3.osuosl.org (Postfix) with ESMTPS id 57DEC608D8\n for <ovs-dev@openvswitch.org>; Mon, 13 Apr 2026 08:15:39 +0000 (UTC)","from mail-wm1-f70.google.com (mail-wm1-f70.google.com\n [209.85.128.70]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-144--2hrO-rUPwGpMMcO0Y6shw-1; Mon, 13 Apr 2026 04:15:37 -0400","by mail-wm1-f70.google.com with SMTP id\n 5b1f17b1804b1-488d1dfad98so23191015e9.3\n for <ovs-dev@openvswitch.org>; Mon, 13 Apr 2026 01:15:37 -0700 (PDT)","from ?IPV6:2001:1c05:1417:d800:d1ef:9817:2a26:625d?\n (2001-1c05-1417-d800-d1ef-9817-2a26-625d.cable.dynamic.v6.ziggo.nl.\n [2001:1c05:1417:d800:d1ef:9817:2a26:625d])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-488d5934a6dsm304821355e9.11.2026.04.13.01.15.34\n (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128);\n Mon, 13 Apr 2026 01:15:35 -0700 (PDT)"],"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 8FBEA40EFF","OpenDKIM Filter v2.11.0 smtp3.osuosl.org 57DEC608D8"],"Received-SPF":"Pass (mailfrom) identity=mailfrom; client-ip=170.10.133.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 57DEC608D8","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1776068138;\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 in-reply-to:in-reply-to:references:references;\n bh=8ZHTy7VOtK+kM7av8CVCUy/05IGSoDKdQs/s0GnX/x0=;\n b=ZR/YJAX7CJ6RC4OfrYQs+sZxBN0SO56Bg4BUYE9JOA/TlVK371eFnKhuinZk2Pi+Wvjtr7\n 7OoG7pi9Q1SxaIcZA2hWEHTwKsUIpEu8IIUgoTNUYSjNjrgWms97ZbwrKqxzmlIDSPbym5\n upK+O1s3GwJbxsB2cOK0ozI5y4puLts=","X-MC-Unique":"-2hrO-rUPwGpMMcO0Y6shw-1","X-Mimecast-MFC-AGG-ID":"-2hrO-rUPwGpMMcO0Y6shw_1776068136","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776068136; x=1776672936;\n h=content-transfer-encoding:in-reply-to:content-language:from\n :references:cc:to:subject:user-agent:mime-version:date:message-id\n :x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id\n :reply-to;\n bh=8ZHTy7VOtK+kM7av8CVCUy/05IGSoDKdQs/s0GnX/x0=;\n b=pWQ00HR7JiFJKwplEd5A4QGyrM4LSZwrM3ZYEoejYlCAl9qpnEHj7Cw6TKA6ymDsmz\n mHz8y+sHrb5uIeBV00AcdBs07J4iZAoNPw4CnEIU+KAv4beGtny29HJpanXRgZYly+Jj\n HsVg1dOo1wVL05DbQBO1T8mM0/0ND7jS6kzi2sJJc1Lb3xcdpl90SaR+7bHsKHQ+0OsH\n AczTi+wpzYpgmeloNhirqHhXMFy9CLoGFV3HyLd8ZRQ6eEmPhF8WC0Q0z2Wa9XoDmwyv\n ILd69wi1keeBFH5rKystds31Rg7w4eKIuv7aL0bQTEyKIhfqsUn05Hh2NwV/ZqKFlEhN\n UOKw==","X-Gm-Message-State":"AOJu0YzLlgg1QY/4vD1xwun96icmD3ln3t/urJ6aQ0ePYjOee29btJTR\n qr9/i8QYf41QUfXqbaB8NPkWvMZivzC/sbelgD4oHE482ithDfXSiuZ91OaxrKVBQ1/1Xw1Ivv3\n HCxP+7qCtntMAn+5/jbKUaTB4qfwqo4JbzzDEDYjz2CTCrcdANd9rblwlTQg=","X-Gm-Gg":"AeBDieumXCazQVFQUn+y25sbP6n/1sHGQWUt3VFRTQiseJAXjZmqDL+gBAlIscVA1aP\n pVjTtfJIbh4vBHbchGPsuclW1jHB+/zue/Cskp7d8ZDiIoqJXjmvo4WzW020CvI+rzec95bUxKd\n AzmhCr+kHRV/0ez6dadU7rGhi9HA4psm0qGvNHpmsfArYe8XAiIAb0Ly8NgFNpxQnUzOcmboEvh\n zyNlThJigr7URQUvYsKabLeD3vwDQ+cyX6VHgfbFtt6S7XuhVhdf7Zny5vy6pgRphDqUjMKTymx\n Ni/6tQSVXSlukUVPXcgr9YPt/V2RqXFHKmp/8vQvlnLbWl1qbI0ZPzmxBX0CBqVIlxBKQ8sxib2\n pRNMPaHOBNgugqnu7oCcNYFA6C1CzxlFjBmlPKVQ7e8bn30clCK0mjEQgavNudpijInGyGzoUAP\n TBe0Ju8SY6w3QPVZoTPWgMPalFZVj3ynWFOwR31kljuvS6HzpphcAtrN2PLMuysUFZ3/G/b1LW","X-Received":["by 2002:a05:600c:350c:b0:488:9661:2570 with SMTP id\n 5b1f17b1804b1-488d67ce8c2mr173085215e9.8.1776068136002;\n Mon, 13 Apr 2026 01:15:36 -0700 (PDT)","by 2002:a05:600c:350c:b0:488:9661:2570 with SMTP id\n 5b1f17b1804b1-488d67ce8c2mr173084825e9.8.1776068135580;\n Mon, 13 Apr 2026 01:15:35 -0700 (PDT)"],"Message-ID":"<d6da52dd-c210-46b3-8ed0-03f7190b8fed@redhat.com>","Date":"Mon, 13 Apr 2026 10:15:33 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","To":"Ales Musil <amusil@redhat.com>,\n Lorenzo Bianconi <lorenzo.bianconi@redhat.com>","Cc":"ovs-dev@openvswitch.org","References":"<20260408115243.2125880-1-dceara@redhat.com>\n <adZO3QTF-wX6vsYh@lore-desk>\n <CALVEqe6oy3Y+8ATDEXF1Ozs43dobpHJjiG0Wb7aWhfMS5Es=MQ@mail.gmail.com>","In-Reply-To":"\n <CALVEqe6oy3Y+8ATDEXF1Ozs43dobpHJjiG0Wb7aWhfMS5Es=MQ@mail.gmail.com>","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"PE7L0kte8oRebkLTpu6uagaHalFRZGzNbeM68tTskxg_1776068136","X-Mimecast-Originator":"redhat.com","Content-Language":"en-US","Subject":"Re: [ovs-dev] [PATCH ovn] northd: Don't forward IP multicast to\n routers 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=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"ovs-dev-bounces@openvswitch.org","Sender":"\"dev\" <ovs-dev-bounces@openvswitch.org>"}}]