On 2/17/26 11:00 AM, Ilya Maximets wrote:
> On 2/17/26 9:48 AM, Lorenzo Bianconi wrote:
>> On Feb 17, Ilya Maximets wrote:
>>> On 2/13/26 6:03 PM, Lorenzo Bianconi wrote:
>>>> Do not forward non-{ip,arp} L2 multicast packets to routers ports in
>>>> order to not exceed OVS recirculation limit if the logical switch is
>>>> connected to multiple OVN routers since these packets will be discarded
>>>> in the router pipeline.
>>>>
>>>> Reported-at: https://issues.redhat.com/browse/FDP-1908
>>>> Signed-off-by: Lorenzo Bianconi <[email protected]>
>>>> ---
>>>> Changes in v3:
>>>> - Convert system-test in unit-test
>>>> - Use 71 priority for new added flow
>>>> ---

Hi Lorenzo, Ilya,

Thanks for the patch and review!

>>>>  northd/northd.c         | 26 +++++++++++-----
>>>>  northd/ovn-northd.8.xml |  8 ++++-
>>>>  tests/ovn-northd.at     | 68 ++++++++++++++++++++++++++++++-----------
>>>>  tests/ovn.at            | 49 +++++++++++++++++++++++++++++
>>>>  4 files changed, 125 insertions(+), 26 deletions(-)
>>>>
>>>> diff --git a/northd/northd.c b/northd/northd.c
>>>> index 4ecdd9c2d..10b328527 100644
>>>> --- a/northd/northd.c
>>>> +++ b/northd/northd.c
>>>> @@ -10767,16 +10767,26 @@ build_lswitch_destination_lookup_bmcast(struct 
>>>> ovn_datapath *od,
>>>>                        lflow_ref);
>>>>      }
>>>>  
>>>> -    if (!smap_get_bool(&od->nbs->other_config,
>>>> -                       "broadcast-arps-to-all-routers", true)) {
>>>> -        ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
>>>> -                      "eth.mcast && (arp.op == 1 || nd_ns)",
>>>> -                      "outport = \""MC_FLOOD_L2"\"; output;",
>>>> -                      lflow_ref);
>>>> -    }
>>>> +    ds_clear(actions);
>>>> +    bool broadcast_arps_to_all_routers = smap_get_bool(
>>>> +            &od->nbs->other_config,
>>>> +            "broadcast-arps-to-all-routers",
>>>> +            true);
>>>> +    ds_put_format(actions, "outport = \"%s\"; output;",
>>>> +                  broadcast_arps_to_all_routers ?  MC_FLOOD : 
>>>> MC_FLOOD_L2);
>>>> +    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
>>>> +                  "eth.mcast && (arp.op == 1 || nd_ns)",
>>>> +                  ds_cstr(actions), lflow_ref);
>>>
>>> This code looks correct to me, though I'd still keep the original
>>> prio 72 flow block and make the new prio 71 flow wider to catch
>>> any arp, not only the replies.  But it's just a style preference
>>> at this point.  Should be fine either way.
>>
>> maybe I am missing something here, but are we going to break
>> "broadcast-arps-to-all-routers" option if we add a prio 71 flow that match 
>> even
>> arp requests and set outport to MC_FLOOD?
> 
> For the broadcast-arps-to-all-routers=false with the current v3 we have:
> 
>  priority=70   , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
>  priority=71   , match=(eth.mcast && (arp.op == 2 || ip)), action=(outport = 
> "_MC_flood"; output;)
>  priority=72   , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport 
> = "_MC_flood_l2"; output;)
> 
> Here all the ARP requests and NS traffic is only flooded to switch ports
> and ARP replies and the rest of ND, together with IP traffic goes to all
> ports including routers.
> 
> For the broadcast-arps-to-all-routers=true:
> 
>  priority=70   , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
>  priority=71   , match=(eth.mcast && (arp.op == 2 || ip)), action=(outport = 
> "_MC_flood"; output;)
>  priority=72   , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport 
> = "_MC_flood"; output;)
> 
> Here all the ARP requests and NS are flooded to all ports including routers,
> as all the IP traffic and ARP/ND replies as well.
> 
> --
> 
> What I suggested for broadcast-arps-to-all-routers=false:
> 
>  priority=70   , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
>  priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = 
> "_MC_flood"; output;)
>  priority=72   , match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport 
> = "_MC_flood_l2"; output;)
> 
> Here all the ARP requests and NS traffic is only flooded to switch ports
> and ARP replies and the rest of ND, together with IP traffic goes to all
> ports including routers.  It doesn't matter that we do not match on the
> specific 'op' number, as the flow is lower priority.  'arp' is a superset
> of 'arp.op == 1', the same as 'ip' is a superset of 'nd_ns'.  The bahavior
> is the same between this and the current v3.
> 
> For broadcast-arps-to-all-routers=true:
> 
>  priority=70   , match=(eth.mcast), action=(outport = "_MC_flood_l2"; output;)
>  priority=71   , match=(eth.mcast && (arp || ip)), action=(outport = 
> "_MC_flood"; output;)
> 
> Here all the ARP and NS are flooded to all ports including routers, as all the
> IP traffic as well.  The same behavior as in this v3, but with one less flow.
> We can do that because the prio 71 flow is less specific.
> 
> WDYT?

I agree with Ilya, this seems easier to read.

> 
> I'm not sure if we need a v4 for this tough.  As I said, v3 is correct, just
> a slightly different way to express the same logic.  I'll leave it up to you
> to decide.  Or maybe Dumitru has a preference?
> 

I can make the change myself, no need for a v4.  This is the required
incremental change:

diff --git a/northd/northd.c b/northd/northd.c
index e138502f4f..7fe36b8500 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -10767,22 +10767,19 @@ build_lswitch_destination_lookup_bmcast(struct 
ovn_datapath *od,
                       lflow_ref);
     }
 
-    ds_clear(actions);
-    bool broadcast_arps_to_all_routers = smap_get_bool(
-            &od->nbs->other_config,
-            "broadcast-arps-to-all-routers",
-            true);
-    ds_put_format(actions, "outport = \"%s\"; output;",
-                  broadcast_arps_to_all_routers ?  MC_FLOOD : MC_FLOOD_L2);
-    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
-                  "eth.mcast && (arp.op == 1 || nd_ns)",
-                  ds_cstr(actions), lflow_ref);
+    if (!smap_get_bool(&od->nbs->other_config,
+                       "broadcast-arps-to-all-routers", true)) {
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
+                      "eth.mcast && (arp.op == 1 || nd_ns)",
+                      "outport = \""MC_FLOOD_L2"\"; output;",
+                      lflow_ref);
+    }
 
     ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
-                  "eth.mcast && (arp.op == 2 || ip)",
+                  "eth.mcast && (arp || ip)",
                   "outport = \""MC_FLOOD"\"; output;", lflow_ref);
 
-    /* non-{arp,ip} L2 multicast traffic should not be sent to router
+    /* Non-{arp,ip} L2 multicast traffic should not be sent to router
      * ports since these packets will be discarded in the router pipeline.
      */
     ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",

>>
>>>
>>> There is a couple small nits for the test below.  With these
>>> addressed (can probbaly be addressed on commit) and with or without
>>> the flow format change:
>>
>> I am fine to send a v4, just let me know.
>>
>> Regards,
>> Lorenzo
>>
>>>
>>> Acked-by: Ilya Maximets <[email protected]>
>>>
>>> Would be great if we can also have this backported as OVS logs are
>>> filled with dropped packets on resubmit limit on many real world
>>> setups, and these messages often distract from real issues that
>>> people are dealing with.
>>>
>>>>  
>>>> -    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",
>>>> +    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
>>>> +                  "eth.mcast && (arp.op == 2 || ip)",
>>>>                    "outport = \""MC_FLOOD"\"; output;", lflow_ref);
>>>> +
>>>> +    /* non-{arp,ip} L2 multicast traffic should not be sent to router
>>>> +     * ports since these packets will be discarded in the router pipeline.
>>>> +     */
>>>> +    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",
>>>> +                  "outport = \""MC_FLOOD_L2"\"; output;", lflow_ref);
>>>>  }
>>>>  
>>>>  /* Ingress table 30: destination lookup, multicast handling (priority 
>>>> 80). */
>>>> diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
>>>> index a17bc5f22..8ba68a4d0 100644
>>>> --- a/northd/ovn-northd.8.xml
>>>> +++ b/northd/ovn-northd.8.xml
>>>> @@ -2420,9 +2420,15 @@ output;
>>>>          <code>other_config:broadcast-arps-to-all-routers=true</code>.
>>>>        </li>
>>>>  
>>>> +      <li>
>>>> +        A priority-71 flow that outputs all ARP replies or IP packets 
>>>> with an
>>>> +        Ethernet broadcast or multicast <code>eth.dst</code> to the <code>
>>>> +        MC_FLOOD</code> multicast group.
>>>> +      </li>
>>>> +
>>>>        <li>
>>>>          A priority-70 flow that outputs all packets with an Ethernet 
>>>> broadcast
>>>> -        or multicast <code>eth.dst</code> to the <code>MC_FLOOD</code>
>>>> +        or multicast <code>eth.dst</code> to the <code>MC_FLOOD_L2</code>
>>>>          multicast group.
>>>>        </li>
>>>>  
>>>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
>>>> index 36b3db6f6..8a37561a5 100644
>>>> --- a/tests/ovn-northd.at
>>>> +++ b/tests/ovn-northd.at
>>>> @@ -5743,7 +5743,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5756,7 +5758,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5777,7 +5781,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5792,7 +5798,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5815,7 +5823,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5832,7 +5842,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5854,7 +5866,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5875,7 +5889,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -5903,7 +5919,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    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;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -9537,7 +9555,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=0    , match=(1), 
>>>> action=(outport = get_fdb(eth.dst); next;)
>>>>    table=??(ls_in_l2_lkup      ), priority=100  , match=(reg8[[23]] == 1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_out_apply_port_sec), priority=0    , match=(1), 
>>>> action=(output;)
>>>> @@ -9572,7 +9592,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_out_apply_port_sec), priority=0    , match=(1), 
>>>> action=(output;)
>>>> @@ -9606,7 +9628,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_out_apply_port_sec), priority=0    , match=(1), 
>>>> action=(output;)
>>>> @@ -9641,7 +9665,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(drop;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "sw0p1"), action=(drop;)
>>>> @@ -9676,7 +9702,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(drop;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "sw0p1"), action=(drop;)
>>>> @@ -9715,7 +9743,9 @@ ovn_strip_lflows ], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:00:02), action=(outport = "sw0p2"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=0    , match=(1), 
>>>> action=(output;)
>>>>    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == 
>>>> "none"), action=(drop;)
>>>>    table=??(ls_out_apply_port_sec), priority=0    , match=(1), 
>>>> action=(output;)
>>>> @@ -14054,7 +14084,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
>>>> $svc_monitor_mac && (tcp || icmp || icmp6)), 
>>>> action=(handle_svc_check(inport);)
>>>>    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;)
>>>>    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;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> @@ -14231,7 +14263,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
>>>> ovn_strip_lflows], [0], [dnl
>>>>    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
>>>> 00:00:00:00:ff:02 && !is_chassis_resident("cr-public-lr0")), 
>>>> action=(outport = "cr-public-lr0"; output;)
>>>>    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;)
>>>>    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;)
>>>> -  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
>>>> action=(outport = "_MC_flood_l2"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && 
>>>> (arp.op == 2 || ip)), action=(outport = "_MC_flood"; output;)
>>>> +  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && 
>>>> (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
>>>>    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;)
>>>>    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;)
>>>>    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;)
>>>> diff --git a/tests/ovn.at b/tests/ovn.at
>>>> index c6abd7b8b..2139c9fb1 100644
>>>> --- a/tests/ovn.at
>>>> +++ b/tests/ovn.at
>>>> @@ -45652,3 +45652,52 @@ check_zone_flush ovn-controller-2.log 3
>>>>  OVN_CLEANUP([hv1])
>>>>  AT_CLEANUP
>>>>  ])
>>>> +
>>>> +OVN_FOR_EACH_NORTHD([
>>>> +AT_SETUP([Drop unknown eth type on router ports])
>>>> +AT_SKIP_IF([test $HAVE_SCAPY = no])
>>>> +AT_SKIP_IF([test $HAVE_TCPDUMP = no])
>>>
>>> nit: This test doesn't use tcpdump, AFAICT.
>>>
>>>> +ovn_start
>>>> +
>>>> +net_add n1
>>>> +
>>>> +sim_add hv1
>>>> +as hv1
>>>> +check ovs-vsctl add-br br-phys
>>>> +ovn_attach n1 br-phys 192.168.0.1
>>>> +check ovs-vsctl -- add-port br-int hv1-vif1 -- \
>>>> +    set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
>>>> +    options:tx_pcap=hv1/vif1-tx.pcap \
>>>> +    options:rxq_pcap=hv1/vif1-rx.pcap
>>>> +ovs-vsctl -- add-port br-int hv1-vif2 -- \
>>>
>>> nit: Missing check.
>>>
>>>> +    set interface hv1-vif2 external-ids:iface-id=sw0-p2 \
>>>> +    options:tx_pcap=hv1/vif2-tx.pcap \
>>>> +    options:rxq_pcap=hv1/vif2-rx.pcap
>>>> +
>>>> +check ovn-nbctl ls-add sw0
>>>> +check ovn-nbctl lsp-add sw0 sw0-p1
>>>> +check ovn-nbctl lsp-set-addresses sw0-p1 "50:54:10:00:00:01 10.0.0.1"
>>>> +check ovn-nbctl lsp-add sw0 sw0-p2
>>>> +check ovn-nbctl lsp-set-addresses sw0-p2 "50:54:20:00:00:01 10.0.0.2"
>>>> +
>>>> +check ovn-nbctl lr-add lr0
>>>> +check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
>>>> +check ovn-nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
>>>> +
>>>> +# create an ACL to log traffic on the router port.
>>>
>>> nit: Capital letter.
>>>
>>>> +check ovn-nbctl --log --name='eth-unknown' acl-add sw0 to-lport 1000 
>>>> 'outport == "sw0-lr0" && eth.type == 0x5ff' allow
>>>> +
>>>> +OVN_POPULATE_ARP
>>>> +wait_for_ports_up
>>>> +check ovn-nbctl --wait=hv sync
>>>> +
>>>> +packet=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='50:54:10:00:00:01', 
>>>> type=0x5ff)")
>>>> +echo $packet > expected
>>>> +check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
>>>> +OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
>>>> +
>>>> +AT_CHECK([grep -q 'name="eth-unknown"' hv1/ovn-controller.log],[1])
>>>
>>> nit: Space after the comma.
>>>
>>> Note: Not sure if this would give false-negatives sometimes, i.e. if the log
>>> is not written yet while we're checking, but actually will be at some point.
>>> But I suppose the chances are very low as there are many other operations
>>> between sending and the checking, and we also can't really wait for the 
>>> event
>>> that doesn't happen.  So, it's probbaly fine.
>>>
>>> Best regards, Ilya Maximets.
>>>
> 

I took care of the other small nits Ilya had above and applied the patch
to main and backported it to all stable branches down to 24.03.  The full
incremental change I squashed in can be found below.

Regards,
Dumitru

---
diff --git a/northd/northd.c b/northd/northd.c
index e138502f4f..7fe36b8500 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -10767,22 +10767,19 @@ build_lswitch_destination_lookup_bmcast(struct 
ovn_datapath *od,
                       lflow_ref);
     }
 
-    ds_clear(actions);
-    bool broadcast_arps_to_all_routers = smap_get_bool(
-            &od->nbs->other_config,
-            "broadcast-arps-to-all-routers",
-            true);
-    ds_put_format(actions, "outport = \"%s\"; output;",
-                  broadcast_arps_to_all_routers ?  MC_FLOOD : MC_FLOOD_L2);
-    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
-                  "eth.mcast && (arp.op == 1 || nd_ns)",
-                  ds_cstr(actions), lflow_ref);
+    if (!smap_get_bool(&od->nbs->other_config,
+                       "broadcast-arps-to-all-routers", true)) {
+        ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
+                      "eth.mcast && (arp.op == 1 || nd_ns)",
+                      "outport = \""MC_FLOOD_L2"\"; output;",
+                      lflow_ref);
+    }
 
     ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
-                  "eth.mcast && (arp.op == 2 || ip)",
+                  "eth.mcast && (arp || ip)",
                   "outport = \""MC_FLOOD"\"; output;", lflow_ref);
 
-    /* non-{arp,ip} L2 multicast traffic should not be sent to router
+    /* Non-{arp,ip} L2 multicast traffic should not be sent to router
      * ports since these packets will be discarded in the router pipeline.
      */
     ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 70, "eth.mcast",
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 8ba68a4d0d..9f2d118dd4 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -2421,9 +2421,9 @@ output;
       </li>
 
       <li>
-        A priority-71 flow that outputs all ARP replies or IP packets with an
-        Ethernet broadcast or multicast <code>eth.dst</code> to the <code>
-        MC_FLOOD</code> multicast group.
+        A priority-71 flow that outputs all ARP or IP packets with an Ethernet
+        broadcast or multicast <code>eth.dst</code> to the
+        <code>MC_FLOOD</code> multicast group.
       </li>
 
       <li>
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 8a37561a5d..605d2ec4f2 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -5744,8 +5744,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5759,8 +5758,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "vm2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5782,8 +5780,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5799,8 +5796,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "vm2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5824,8 +5820,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5843,8 +5838,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "vm2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5867,8 +5861,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5890,8 +5883,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -5920,8 +5912,7 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   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;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:02), action=(outport = "vm1"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -9556,8 +9547,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=100  , match=(reg8[[23]] == 1), 
action=(output;)
   table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst == 
$svc_monitor_mac && (tcp || icmp || icmp6)), action=(handle_svc_check(inport);)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
@@ -9593,8 +9583,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
@@ -9629,8 +9618,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
@@ -9666,8 +9654,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(drop;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "sw0p1"), 
action=(drop;)
@@ -9703,8 +9690,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(drop;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "sw0p1"), 
action=(drop;)
@@ -9744,8 +9730,7 @@ ovn_strip_lflows ], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
   table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst == 
00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   table=??(ls_in_l2_unknown   ), priority=0    , match=(1), action=(output;)
   table=??(ls_in_l2_unknown   ), priority=50   , match=(outport == "none"), 
action=(drop;)
   table=??(ls_out_apply_port_sec), priority=0    , match=(1), action=(output;)
@@ -14085,8 +14070,7 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
ovn_strip_lflows], [0], [dnl
   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;)
   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;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
@@ -14264,8 +14248,7 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
ovn_strip_lflows], [0], [dnl
   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;)
   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;)
   table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast), 
action=(outport = "_MC_flood_l2"; output;)
-  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp.op 
== 2 || ip)), action=(outport = "_MC_flood"; output;)
-  table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (arp.op 
== 1 || nd_ns)), action=(outport = "_MC_flood"; output;)
+  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && (arp || 
ip)), action=(outport = "_MC_flood"; output;)
   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;)
   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;)
   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;)
diff --git a/tests/ovn.at b/tests/ovn.at
index 2139c9fb19..3a3b05ab7f 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -45656,7 +45656,6 @@ AT_CLEANUP
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([Drop unknown eth type on router ports])
 AT_SKIP_IF([test $HAVE_SCAPY = no])
-AT_SKIP_IF([test $HAVE_TCPDUMP = no])
 ovn_start
 
 net_add n1
@@ -45669,7 +45668,7 @@ check ovs-vsctl -- add-port br-int hv1-vif1 -- \
     set interface hv1-vif1 external-ids:iface-id=sw0-p1 \
     options:tx_pcap=hv1/vif1-tx.pcap \
     options:rxq_pcap=hv1/vif1-rx.pcap
-ovs-vsctl -- add-port br-int hv1-vif2 -- \
+check ovs-vsctl -- add-port br-int hv1-vif2 -- \
     set interface hv1-vif2 external-ids:iface-id=sw0-p2 \
     options:tx_pcap=hv1/vif2-tx.pcap \
     options:rxq_pcap=hv1/vif2-rx.pcap
@@ -45684,7 +45683,7 @@ check ovn-nbctl lr-add lr0
 check ovn-nbctl lrp-add lr0 lr0-sw0 00:00:00:00:ff:01 10.0.0.254/24
 check ovn-nbctl lsp-add-router-port sw0 sw0-lr0 lr0-sw0
 
-# create an ACL to log traffic on the router port.
+# Create an ACL to log traffic on the router port.
 check ovn-nbctl --log --name='eth-unknown' acl-add sw0 to-lport 1000 'outport 
== "sw0-lr0" && eth.type == 0x5ff' allow
 
 OVN_POPULATE_ARP
@@ -45696,7 +45695,7 @@ echo $packet > expected
 check as hv1 ovs-appctl netdev-dummy/receive hv1-vif1 $packet
 OVN_CHECK_PACKETS([hv1/vif2-tx.pcap], [expected])
 
-AT_CHECK([grep -q 'name="eth-unknown"' hv1/ovn-controller.log],[1])
+AT_CHECK([grep -q 'name="eth-unknown"' hv1/ovn-controller.log], [1])
 
 OVN_CLEANUP([hv1])
 AT_CLEANUP

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to