On Thu, May 14, 2026 at 6:46 PM Lorenzo Bianconi <
[email protected]> 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]>
> Signed-off-by: Lorenzo Bianconi <[email protected]>
> ---
> Changes since v2:
> - Rebase on top of ovn main branch
> - simplify ovn-northd flows
> - Remove committed ovs submodule dump
> Changes since v1:
> - Add dedicated GARP management
> - Do not skip any unit-test
> ---
>  Documentation/ref/ovn-logical-flows.7.rst |  11 +-
>  northd/northd.c                           |  19 ++-
>  tests/ovn-northd.at                       | 192 ++++++++++++++--------
>  tests/ovn.at                              |  38 ++---
>  4 files changed, 163 insertions(+), 97 deletions(-)
>
> diff --git a/Documentation/ref/ovn-logical-flows.7.rst
> b/Documentation/ref/ovn-logical-flows.7.rst
> index 0b69d7bb0..c8977956f 100644
> --- a/Documentation/ref/ovn-logical-flows.7.rst
> +++ b/Documentation/ref/ovn-logical-flows.7.rst
> @@ -1415,6 +1415,11 @@ This table implements switching behavior.  It
> contains these logical flows:
>    IPv6 Neighbor Advertisements to this port as well. These allow to build
> proper
>    ARP/IPv6 neighbor list on this port.
>
> +- Priority-95 flows for each IP address/VIP/NAT address owned by a router
> port
>

nit: This should be 90.


> +  connected to the switch. These flows match GARP packets for the
> specific I
>

nit: s/I/IP/


> +  addresses. Matched packets are forwarded to the ``MC_FLOOD_L2``
> multicast
> +  group  which contains all non-router logical ports.
> +
>  - Priority-90 flows for transit switches that forward registered IP
> multicast
>    traffic to their corresponding multicast group , which ``ovn-northd``
> creates
>    based on learnt ``IGMP_Group`` entries.
> @@ -1451,8 +1456,8 @@ This table implements switching behavior.  It
> contains these logical flows:
>  - Priority-80 flows for each IP address/VIP/NAT address owned by a 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 ``MC_FLOOD_L2`` multicast group which
> contains
> -  all non-router logical ports.
> +  owns the IP address and to the ``MC_UNKNOWN`` multicast group which
> contains
> +  all enabled logical ports that accept unknown destination packets.
>
>  - Priority-75 flows for each port connected to a logical router matching
> self
>    originated ARP request/RARP request/ND packets.  These packets are
> flooded to
> @@ -1467,7 +1472,7 @@ This table implements switching behavior.  It
> contains these logical flows:
>
>  - A priority-72 flow that outputs all ARP requests and ND NS (Neighbor
>    Solicitation) packets with an Ethernet broadcast or multicast
> ``eth.dst`` to
> -  the ``MC_FLOOD_L2`` multicast group if
> ``other_config:broadcast-arps-to-all-
> +  the ``MC_UNKNOWN`` multicast group if
> ``other_config:broadcast-arps-to-all-
>    routers=false``.
>
>  - A priority-71 flow that outputs all ARP packets with an Ethernet
> broadcast or
> diff --git a/northd/northd.c b/northd/northd.c
> index 8305e0428..4162143de 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, &m);
> +        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,7 +9640,7 @@ 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,
> @@ -9644,6 +9656,7 @@ build_lswitch_rport_arp_req_flow(
>
>      ds_destroy(&m);
>      ds_destroy(&match);
> +    ds_destroy(&m_garp);
>      ds_destroy(&actions);
>  }
>
> @@ -11085,7 +11098,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/tests/ovn-northd.at b/tests/ovn-northd.at
> index 074b1526b..501f78b67 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;)
>  ])
>
>
> @@ -8068,17 +8104,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
> @@ -14465,11 +14501,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
> @@ -14500,8 +14540,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;)
>  ])
>  }
>
> @@ -14645,16 +14687,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 && 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
> @@ -14679,10 +14725,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 && 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;)
>  ])
>  }
>
> @@ -14746,8 +14794,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 fbaa63d99..9251a7ef5 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.
> @@ -27891,18 +27901,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.54.0
>
>
Thank you Lorenzo,

I have fixed the nits and applied this to main.

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

Reply via email to