On 4/30/26 9:26 AM, Felix Huettner wrote:
> Am Tue, Apr 28, 2026 at 05:17:34PM +0200 schrieb Lorenzo Bianconi:
>> On Apr 28, Lorenzo Bianconi wrote:
>>>> On 4/27/26 3:50 PM, Lorenzo Bianconi wrote:
>>>>>> 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]>
>>>>>
>>>>> @Dumitru: I kept your SoB here but I was not sure about it. Please let me 
>>>>> know
>>>>> if you are fine or not with it.
>>>>>
>>>>
>>>> Hi Lorenzo,
>>>>
>>>> I guess that's fine.  I do have some comments below.
>>>>
>>>>> Regards,
>>>>> Lorenzo
>>>>>
>>>>>> 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));
>>>>>> +        }
>>>>
>>>> What about IPv6 gratuitous NS?  Now those go to MC_UNKNOWN while they
>>>> used to go to MC_FLOOD_L2.  Do we need a similar change for IPv6 as you
>>>> do here for
>>>
>>> This is done just for GARP, is there an equivalent for IPv6? let me check.
>>
>> According to my understanding the GARP IPv6 equivalent are unsolicited
>> Neighbor Advertisement packets. Reviewing the code, OVN logical router does 
>> not
>> support them, so I guess we do not need any extra flows here. What do you 
>> think?
> 
> Hi everyone,
> 

Hi Felix, Lorenzo,

> the thing is that endpoints on other VIFs might support handling the
> UNAs, so we would still need to forward the packet there, otherwise we
> have the same issue as for ipv4 previously.
> 
> Keepalived code to send these UNAs 
> https://github.com/acassen/keepalived/blob/master/keepalived/vrrp/vrrp_ndisc.c#L166
> If i get it right we could filter on the ipv6 src ip being equal to the
> neighbor Advertisement target ip.
> But not sure if this is generalizable for other implementations.
> 

OK, but the change Lorenzo is doing is for ARPs/NS targetting the
logical router port owned IPs and gratuitous ARPs generated for the same
router owned IPs.

UNAs generated by VIFs still get flooded to the L2 broadcast domain IIUC.

On a different note, Lorenzo, I think we should run some scale tests
with this patch applied (e.g., ovn-heater tests) to make sure we don't
affect scalability.  The patch adds a new flow for each load balancer
VIP for all load balancers applied on logical routers.  The same thing
happens for NAT IPs.

Would you have time to double check we won't regress from that perspective?

Thanks,
Dumitru

> Thanks
> Felix
> 
> 
>>
>> Regards,
>> Lorenzo
>>
>>>
>>>>
>>>>>>      } 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;)
>>>>
>>>> This is the IPv6 flow I mentioned above, now we'd only flood gratuitous
>>>> NS from this router port owned IPv6 address to MC_UNKNOWN, not to any
>>>> VIFs we might have in the system.
>>>
>>> ack, I will fix it.
>>>
>>> Regards,
>>> Lorenzo
>>>
>>>>
>>>>>> +  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
>>>>>>
>>>>
>>>> Regards,
>>>> Dumitru
>>>>
>>
>>
> 
> 

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

Reply via email to