In the OVN logical switch pipeline, broadcast ARP requests (and ND_NS)
generated by VIFs and by router ports are also flooded into the per switch
MC_FLOOD_L2 multicast group which includes all non-router ports of the
switch.
In deployments with large logical broadcast domains (logical switches with
a significantly large number of switch ports, e.g. 200+) this becomes a
problem because the MC_FLOOD_L2 multicast group has a lot of ports so the
chain of the OpenFlow tables that the packet needs to traverse for full
processing becomes really long, going over OVS' 4K resubmit limit and
causing the packet to be dropped.
The main reason why the ARP packets are currently sent to all non-router
ports is to allow the workloads to learn the mapping between arp.spa
(source IP) and arp.sha (source MAC). However, that's just an optimization,
which might avoid future ARP requests from other workloads; and it's not a
requirement, nothing would really break if we didn't forward those packets
to all other VIFs.
It's probably acceptable to change the behavior and just forward these ARP
requests to the ports that have LSP.addresses="unknown" as the workloads
behind those ports (or the fabric for the localnet case) might actually own
the arp.tpa target IP.

Reported-at: https://redhat.atlassian.net/browse/FDP-3439
Co-authored-by: Dumitru Ceara <[email protected]>
Signed-off-by: Dumitru Ceara <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
Changes since v1:
- Add dedicated GARP management
- Do not skip any unit-test
---
 northd/northd.c         |  25 +++++-
 northd/ovn-northd.8.xml |  14 ++-
 ovs                     |   2 +-
 tests/ovn-northd.at     | 192 +++++++++++++++++++++++++---------------
 tests/ovn.at            |  38 ++++----
 5 files changed, 173 insertions(+), 98 deletions(-)

diff --git a/northd/northd.c b/northd/northd.c
index 0b52db6cf..e606365c6 100644
--- a/northd/northd.c
+++ b/northd/northd.c
@@ -9583,6 +9583,7 @@ build_lswitch_rport_arp_req_flow(
 {
     struct ds match   = DS_EMPTY_INITIALIZER;
     struct ds m       = DS_EMPTY_INITIALIZER;
+    struct ds m_garp  = DS_EMPTY_INITIALIZER;
     struct ds actions = DS_EMPTY_INITIALIZER;
 
     arp_nd_ns_match(ips, addr_family, &m);
@@ -9604,16 +9605,27 @@ build_lswitch_rport_arp_req_flow(
                       patch_op->cr_port->json_key);
     }
 
+    if (addr_family == AF_INET) {
+        ds_clone(&m_garp, &match);
+        ds_put_format(&m_garp, " && arp.spa == %s", ips);
+    }
+
     /* Send a the packet to the router pipeline.  If the switch has non-router
      * ports then flood it there as well.
      */
     if (vector_len(&od->router_ports) != od->nbs->n_ports) {
         ds_put_format(&actions, "clone {outport = %s; output; }; "
-                                "outport = \""MC_FLOOD_L2"\"; output;",
+                                "outport = \""MC_UNKNOWN"\"; output;",
                       patch_op->json_key);
         ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
                       ds_cstr(&match), ds_cstr(&actions), lflow_ref,
                       WITH_HINT(stage_hint));
+        if (addr_family == AF_INET) {
+            ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority + 10,
+                          ds_cstr(&m_garp),
+                          "outport = \""MC_FLOOD_L2"\"; output;",
+                          lflow_ref, WITH_HINT(stage_hint));
+        }
     } else {
         ds_put_format(&actions, "outport = %s; output;", patch_op->json_key);
         ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
@@ -9628,11 +9640,17 @@ build_lswitch_rport_arp_req_flow(
         ds_clear(&actions);
         if (vector_len(&od->router_ports) != od->nbs->n_ports) {
             ds_put_format(&actions, "clone {outport = %s; output; }; "
-                                    "outport = \""MC_FLOOD_L2"\"; output;",
+                                    "outport = \""MC_UNKNOWN"\"; output;",
                           patch_op->cr_port->json_key);
             ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
                           ds_cstr(&match), ds_cstr(&actions), lflow_ref,
                           WITH_HINT(stage_hint));
+            if (addr_family == AF_INET) {
+                ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority + 10,
+                              ds_cstr(&m_garp),
+                              "outport = \""MC_FLOOD_L2"\"; output;",
+                              lflow_ref, WITH_HINT(stage_hint));
+            }
         } else {
             ds_put_format(&actions, "outport = %s; output;",
                           patch_op->cr_port->json_key);
@@ -9644,6 +9662,7 @@ build_lswitch_rport_arp_req_flow(
 
     ds_destroy(&m);
     ds_destroy(&match);
+    ds_destroy(&m_garp);
     ds_destroy(&actions);
 }
 
@@ -11061,7 +11080,7 @@ build_lswitch_destination_lookup_bmcast(struct 
ovn_datapath *od,
                        "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;",
+                      "outport = \""MC_UNKNOWN"\"; output;",
                       lflow_ref);
     }
 
diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
index 4d6370da6..75c17e75d 100644
--- a/northd/ovn-northd.8.xml
+++ b/northd/ovn-northd.8.xml
@@ -2346,6 +2346,14 @@ output;
         <ref table="IGMP_Group" db="OVN_Southbound"/> entries.
       </li>
 
+      <li>
+        Priority-95 flows for each IP address/VIP/NAT address owned by a
+        router port connected to the switch. These flows match GARP packets
+        for the specific IP addresses. Matched packets are forwarded to the
+        <code>MC_FLOOD_L2</code> multicast group which contains all non-router
+        logical ports.
+      </li>
+
       <li>
         Priority-90 flows that forward registered IP multicast traffic to
         their corresponding multicast group, which <code>ovn-northd</code>
@@ -2402,8 +2410,8 @@ output;
         router port connected to the switch. These flows match ARP requests
         and ND packets for the specific IP addresses.  Matched packets are
         forwarded only to the router that owns the IP address and to the
-        <code>MC_FLOOD_L2</code> multicast group which contains all non-router
-        logical ports.
+        <code>MC_UNKNOWN</code> multicast group which contains all enabled
+        logical ports that accept unknown destination packets.
       </li>
 
       <li>
@@ -2426,7 +2434,7 @@ output;
       <li>
         A priority-72 flow that outputs all ARP requests and ND NS (Neighbor
         Solicitation) packets with an Ethernet broadcast or multicast
-        <code>eth.dst</code> to the <code>MC_FLOOD_L2</code> multicast group
+        <code>eth.dst</code> to the <code>MC_UNKNOWN</code> multicast group
         if <code>other_config:broadcast-arps-to-all-routers=false</code>.
       </li>
 
diff --git a/ovs b/ovs
index bdb95cc19..6aefe1db3 160000
--- a/ovs
+++ b/ovs
@@ -1 +1 @@
-Subproject commit bdb95cc1920d4ab66fe062a9470eeb33a51d33e2
+Subproject commit 6aefe1db31e3df4e7b64c21f54a7287e4663e1e4
diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
index 1d7bd6c28..b66f36691 100644
--- a/tests/ovn-northd.at
+++ b/tests/ovn-northd.at
@@ -5867,8 +5867,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
+  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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 
 ovn-sbctl lflow-list ls2 > ls2_lflows
@@ -5883,8 +5884,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
+  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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.2.1 && arp.spa == 192.168.2.1), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 
 AS_BOX([Adding some reachable NAT addresses])
@@ -5907,10 +5909,13 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  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;)
+  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_unknown"; 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_unknown"; 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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.100 && arp.spa == 10.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.200 && arp.spa == 10.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 
 ovn-sbctl lflow-list ls2 > ls2_lflows
@@ -5925,10 +5930,13 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200), 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;)
+  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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200), action=(clone {outport = "ls2-ro2"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.2.1 && arp.spa == 192.168.2.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.100 && arp.spa == 20.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200 && arp.spa == 20.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 AS_BOX([Adding some unreachable NAT addresses])
@@ -5951,12 +5959,17 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  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 && 
arp.op == 1 && arp.tpa == 30.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 == 30.0.0.200), 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;)
+  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_unknown"; 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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.100 && arp.spa == 10.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.200 && arp.spa == 10.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100 && arp.spa == 30.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200 && arp.spa == 30.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 ovn-sbctl lflow-list ls2 > ls2_lflows
@@ -5971,12 +5984,17 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200), 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 == 40.0.0.100), 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 == 40.0.0.200), 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;)
+  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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200), action=(clone {outport = "ls2-ro2"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 40.0.0.100), action=(clone {outport = "ls2-ro2"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 40.0.0.200), action=(clone {outport = "ls2-ro2"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.2.1 && arp.spa == 192.168.2.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.100 && arp.spa == 20.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 20.0.0.200 && arp.spa == 20.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 40.0.0.100 && arp.spa == 40.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 40.0.0.200 && arp.spa == 40.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 AS_BOX([Adding load balancer reachable VIPs to ro1])
@@ -5996,13 +6014,19 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  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 && 
arp.op == 1 && arp.tpa == 192.168.1.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 == 30.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 == 30.0.0.200), 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;)
+  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_unknown"; 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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.100 && arp.spa == 10.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.200 && arp.spa == 10.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100 && arp.spa == 192.168.1.100), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100 && arp.spa == 30.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200 && arp.spa == 30.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 AS_BOX([Adding load balancer unreachable VIPs to ro1])
@@ -6020,13 +6044,19 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  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 && 
arp.op == 1 && arp.tpa == 192.168.1.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 == 30.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 == 30.0.0.200), 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;)
+  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_unknown"; 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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.100 && arp.spa == 10.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.200 && arp.spa == 10.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100 && arp.spa == 192.168.1.100), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100 && arp.spa == 30.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200 && arp.spa == 30.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 # Make sure that there is no flow for VIP 192.168.4.100 as ro1-ls1 doesn't
@@ -6051,13 +6081,19 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  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 && 
arp.op == 1 && arp.tpa == 192.168.1.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 == 30.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 == 30.0.0.200), 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;)
+  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_unknown"; 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_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200), action=(clone {outport = "ls1-ro1"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.100 && arp.spa == 10.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 10.0.0.200 && arp.spa == 10.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.1 && arp.spa == 192.168.1.1), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 192.168.1.100 && arp.spa == 192.168.1.100), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.100 && arp.spa == 30.0.0.100), action=(outport 
= "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 30.0.0.200 && arp.spa == 30.0.0.200), action=(outport 
= "_MC_flood_l2"; output;)
 ])
 
 
@@ -8066,17 +8102,17 @@ check ovn-nbctl lsp-add S1 S1-VIF
 check ovn-nbctl lsp-set-addresses S1-VIF "02:ac:10:01:00:02 unknown"
 check ovn-nbctl --wait=sb sync
 
-AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; 
output;)'], [1])
+AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_unknown"; 
output;)'], [1])
 
 check ovn-nbctl --wait=sb set Logical_Switch S1 \
     other_config:broadcast-arps-to-all-routers=false
 
-AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; 
output;)'], [0], [], [ignore])
+AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_unknown"; 
output;)'], [0], [], [ignore])
 
 check ovn-nbctl --wait=sb set Logical_Switch S1 \
     other_config:broadcast-arps-to-all-routers=true
 
-AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_flood_l2"; 
output;)'], [1])
+AT_CHECK([ovn-sbctl lflow-list S1 | grep ls_in_l2_lkup | grep -q 
'match=(eth.mcast && (arp.op == 1 || nd_ns)), action=(outport = "_MC_unknown"; 
output;)'], [1])
 
 OVN_CLEANUP_NORTHD
 AT_CLEANUP
@@ -14356,11 +14392,15 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110), 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.120), action=(clone {outport = 
"public-lr0"; 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:ff02), 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.10), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
nd_ns && nd.target == fe80::200:ff:fe00:ff02), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.10 && arp.spa == 172.168.0.10), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.100 && arp.spa == 172.168.0.100), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && arp.spa == 172.168.0.110), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && arp.spa == 172.168.0.120), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 
 AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e 
"20.0.0.3" -e "30:54:00:00:00:03"  -e "sw0-port1" lr0flows | ovn_strip_lflows], 
[0], [dnl
@@ -14391,8 +14431,10 @@ AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" 
-e "10.0.0.3" -e "20.0.0.3
 AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e 
"20.0.0.3" -e "30:54:00:00:00:03"  -e "sw0-port1" publicflows | 
ovn_strip_lflows | grep -v "reg0.*22"], [0], [dnl
   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=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.110), 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.120), 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.110), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && arp.spa == 172.168.0.110), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && arp.spa == 172.168.0.120), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 }
 
@@ -14536,16 +14578,20 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows | 
ovn_strip_lflows], [0], [dnl
   table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast && ip), 
action=(outport = "_MC_flood_l2"; output;)
   table=??(ls_in_l2_lkup      ), priority=72   , match=(eth.mcast && (nd_na || 
nd_rs || nd_ra)), 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;)
-  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.100 && 
!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.100 && 
is_chassis_resident("cr-public-lr0")), 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.110 && 
!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.110 && 
is_chassis_resident("cr-public-lr0")), 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.120 && 
!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.120 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
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:ff02 && 
!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 && 
nd_ns && nd.target == fe80::200:ff:fe00:ff02 && 
is_chassis_resident("cr-public-lr0")), 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.10 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; 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_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.100 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.100 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
nd_ns && nd.target == fe80::200:ff:fe00:ff02 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
nd_ns && nd.target == fe80::200:ff:fe00:ff02 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.10 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.10), action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.100 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.100), action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.110), action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.120), action=(outport = "_MC_flood_l2"; output;)
 ])
 
 AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e 
"20.0.0.3" -e "30:54:00:00:00:03"  -e "sw0-port1" lr0flows | ovn_strip_lflows], 
[0], [dnl
@@ -14570,10 +14616,12 @@ AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" 
-e "10.0.0.3" -e "20.0.0.3
 AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e 
"20.0.0.3" -e "30:54:00:00:00:03"  -e "sw0-port1" publicflows | 
ovn_strip_lflows], [0], [dnl
   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=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.110 && 
!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.110 && 
is_chassis_resident("cr-public-lr0")), 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.120 && 
!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.120 && 
is_chassis_resident("cr-public-lr0")), 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.110 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && 
!is_chassis_resident("cr-public-lr0")), action=(clone {outport = 
"cr-public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && 
is_chassis_resident("cr-public-lr0")), action=(clone {outport = "public-lr0"; 
output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.110), action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && is_chassis_resident("cr-public-lr0") 
&& arp.spa == 172.168.0.120), action=(outport = "_MC_flood_l2"; output;)
 ])
 }
 
@@ -14637,8 +14685,10 @@ AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" 
-e "10.0.0.3" -e "20.0.0.3
 AT_CHECK([grep -Fe "172.168.0.110" -e "172.168.0.120" -e "10.0.0.3" -e 
"20.0.0.3" -e "30:54:00:00:00:03"  -e "sw0-port1" publicflows | 
ovn_strip_lflows], [0], [dnl
   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=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.110), 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.120), 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.110), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=80   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120), action=(clone {outport = 
"public-lr0"; output; }; outport = "_MC_unknown"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.110 && arp.spa == 172.168.0.110), 
action=(outport = "_MC_flood_l2"; output;)
+  table=??(ls_in_l2_lkup      ), priority=90   , match=(flags[[1]] == 0 && 
arp.op == 1 && arp.tpa == 172.168.0.120 && arp.spa == 172.168.0.120), 
action=(outport = "_MC_flood_l2"; output;)
 ])
 
 OVN_CLEANUP_NORTHD
diff --git a/tests/ovn.at b/tests/ovn.at
index c0ae611bc..e0ab6fa0b 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -5192,7 +5192,7 @@ test_ip() {
 # SPA and TPA are each 8 hex digits.
 test_arp() {
     echo "$@"
-    local inport=$1 sha=$2 spa=$3 tpa=$4 reply_ha=$5
+    local inport=$1 sha=$2 spa=$3 tpa=$4 rip=$5 reply_ha=$6
     local request=$(fmt_pkt "Ether(dst='ff:ff:ff:ff:ff:ff', src='${sha}')/ \
                              ARP(hwsrc='${sha}', hwdst='ff:ff:ff:ff:ff:ff', 
psrc='${spa}', pdst='${tpa}')")
     hv=hv`vif_to_hv $inport`
@@ -5206,9 +5206,19 @@ test_arp() {
         for k in 1 2 3; do
             # 192.168.33.254 is configured to the switch patch port for lrp33,
             # so no ARP flooding expected for it.
-            if test $i$j$k != $inport && test $tpa != 192.168.33.254; then
-                echo $request >> $i$j$k.expected
+            if test $i$j$k = $inport; then
+                continue
+            fi
+
+            if test $tpa = 192.168.33.254; then
+                continue
             fi
+
+            if test $rip = $tpa && test $j$k != 11; then
+                continue
+            fi
+
+            echo $request >> $i$j$k.expected
         done
     done
 
@@ -5348,9 +5358,9 @@ for i in 1 2 3; do
       otherip=192.168.$i$j.55 # Some other IP in subnet
       externalip=1.2.3.4      # Some other IP not in subnet
 
-      test_arp $i$j$k $smac $sip        $rip        $rmac      #4
-      test_arp $i$j$k $smac $otherip    $rip        $rmac      #5
-      test_arp $i$j$k $smac $sip        $otherip               #6
+      test_arp $i$j$k $smac $sip        $rip        $rip    $rmac #4
+      test_arp $i$j$k $smac $otherip    $rip        $rip    $rmac #5
+      test_arp $i$j$k $smac $sip        $otherip    $rip          #6
 
       # When rip is 192.168.33.254, ARP request from externalip won't be
       # filtered, because 192.168.33.254 is configured to switch peer port
@@ -5359,9 +5369,9 @@ for i in 1 2 3; do
       if test $i = 3 && test $j = 3; then
         lrp33_rsp=$rmac
       fi
-      test_arp $i$j$k $smac $externalip $rip        $lrp33_rsp #7
+      test_arp $i$j$k $smac $externalip $rip $rip $lrp33_rsp #7
 
-      # MAC binding should be learned from ARP request.
+      ## MAC binding should be learned from ARP request.
       echo lrp$i$j,$sip,$smac >> mac_bindings.expected
 
       # mac_binding is learned and overwritten so only the last one remains.
@@ -27702,18 +27712,6 @@ for var in sw_dp_uuid sw_dp_key sw1_dp_key r1_dp_key 
r1_tnl_key r2_tnl_key \
    echo "$var=$value"
 done
 
-as hv1
-AT_CAPTURE_FILE([offlows])
-OVS_WAIT_FOR_OUTPUT([
-    ovs-ofctl dump-flows br-int > offlows
-    for match in "$match_send_rtr1" "$match_send_rtr2"; do
-        grep -E "$match_arp_req.*$match" offlows | grep -c 'n_packets=[[1-9]]'
-    done
-    :
-], [0], [1
-0
-])
-
 # Inject ND_NS for ofirst router owned IP address.
 src_ipv6=00100000000000000000000000000254
 dst_ipv6=00100000000000000000000000000001
-- 
2.53.0

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

Reply via email to