On Wed, Apr 8, 2026 at 2:50 PM Lorenzo Bianconi via dev <
[email protected]> wrote:

> > Logical switches should not forward IP multicast packets towards
> > connected OVN logical routers if the router is not configured to relay
> > IP multicast traffic (LR.options:mcast_relay=false).
> >
> > Previously, a single priority 71 flow matched "eth.mcast && (arp || ip)"
> > and sent all such traffic to _MC_flood, which includes all ports
> > (including router ports).  This caused IP multicast packets to be
> > forwarded to routers that would always drop them in lr_in_ip_input,
> > wasting CPU cycles.  In topologies with hundreds of routers connected
> > to logical switches, this can lead to the max resubmit limit (4K) being
> > hit by such packets, unnecessarily overloading ovs-vswitchd.
> >
> > Fix this by splitting the flow into three:
> >  - Priority 72: "eth.mcast && (nd_na || nd_rs || nd_ra)" -> _MC_flood
> >    ND NA, Router Solicitation and Router Advertisement must still reach
> >    routers: ND NA for neighbor learning, ND RS so routers can respond
> >    with Router Advertisements, ND RA for proper IPv6 network operation.
> >  - Priority 71: "eth.mcast && arp" -> _MC_flood
> >    ARP (including gratuitous ARP) still reaches all ports.
> >  - Priority 71: "eth.mcast && ip" -> _MC_flood_l2
> >    IP multicast is only sent to non-router L2 ports, plus
> >    _MC_mrouter_flood (if any connected router has relay enabled)
> >    and _MC_static (if any port has mcast_flood=true).
> >
> > Reported-at: https://redhat.atlassian.net/browse/FDP-2262
> > Assisted-by: Claude, with model: claude-opus-4-6
> > Signed-off-by: Dumitru Ceara <[email protected]>
>
> Acked-by: Lorenzo Bianconi <[email protected]>
>
> > ---
> >  northd/northd.c         |  37 +++++++-
> >  northd/ovn-northd.8.xml |  33 +++++--
> >  tests/ovn-northd.at     | 191 ++++++++++++++++++++++++++++++++++++----
> >  3 files changed, 237 insertions(+), 24 deletions(-)
> >
> > diff --git a/northd/northd.c b/northd/northd.c
> > index b7239f4e20..92c1707817 100644
> > --- a/northd/northd.c
> > +++ b/northd/northd.c
> > @@ -11020,10 +11020,45 @@ build_lswitch_destination_lookup_bmcast(struct
> ovn_datapath *od,
> >                        lflow_ref);
> >      }
> >
> > +    /* ND NA, Router Solicitation and Router Advertisement should be
> > +     * flooded to all ports including routers.  ND NA is needed for
> > +     * neighbor learning; ND RS must reach routers so they can respond
> > +     * with Router Advertisements; ND RA must reach routers for proper
> > +     * IPv6 network operation.
> > +     */
> > +    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 72,
> > +                  "eth.mcast && (nd_na || nd_rs || nd_ra)",
> > +                  "outport = \""MC_FLOOD"\"; output;", lflow_ref);
> > +
> > +    /* ARP multicast should be flooded to all ports including routers.
> */
> >      ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
> > -                  "eth.mcast && (arp || ip)",
> > +                  "eth.mcast && arp",
> >                    "outport = \""MC_FLOOD"\"; output;", lflow_ref);
> >
> > +    /* IP multicast should not be forwarded to routers that don't have
> > +     * IGMP relay enabled (mcast_relay=true).  Such routers will always
> > +     * drop IP multicast in lr_in_ip_input anyway.
> > +     */
> > +    ds_clear(actions);
> > +    if (mcast_sw_info->flood_relay) {
> > +        ds_put_cstr(actions,
> > +                    "clone { "
> > +                        "outport = \""MC_MROUTER_FLOOD"\"; "
> > +                        "output; "
> > +                    "}; ");
> > +    }
> > +    if (mcast_sw_info->flood_static) {
> > +        ds_put_cstr(actions,
> > +                    "clone { "
> > +                        "outport = \""MC_STATIC"\"; "
> > +                        "output; "
> > +                    "}; ");
> > +    }
> > +    ds_put_cstr(actions, "outport = \""MC_FLOOD_L2"\"; output;");
> > +    ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, 71,
> > +                  "eth.mcast && ip",
> > +                  ds_cstr(actions), lflow_ref);
> > +
> >      /* Non-{arp,ip} L2 multicast traffic should not be sent to router
> >       * ports since these packets will be discarded in the router
> pipeline.
> >       */
> > diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
> > index 9f2d118dd4..4d6370da6b 100644
> > --- a/northd/ovn-northd.8.xml
> > +++ b/northd/ovn-northd.8.xml
> > @@ -2414,18 +2414,41 @@ output;
> >        </li>
> >
> >        <li>
> > -        A priority-72 flow that outputs all ARP requests and ND packets
> with
> > -        an Ethernet broadcast or multicast <code>eth.dst</code> to the
> > -        <code>MC_FLOOD_L2</code> multicast group if
> > -        <code>other_config:broadcast-arps-to-all-routers=true</code>.
> > +        A priority-72 flow that outputs all ND NA (Neighbor
> Advertisement),
> > +        ND RS (Router Solicitation) and ND RA (Router Advertisement)
> packets
> > +        with an Ethernet broadcast or multicast <code>eth.dst</code> to
> the
> > +        <code>MC_FLOOD</code> multicast group, which includes all ports.
> > +        ND NA must reach routers for neighbor learning; ND RS must reach
> > +        routers so they can respond with Router Advertisements; ND RA
> must
> > +        reach routers for proper IPv6 network operation.
> >        </li>
> >
> >        <li>
> > -        A priority-71 flow that outputs all ARP or IP packets with an
> Ethernet
> > +        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
> > +        if
> <code>other_config:broadcast-arps-to-all-routers=false</code>.
> > +      </li>
> > +
> > +      <li>
> > +        A priority-71 flow that outputs all ARP packets with an Ethernet
> >          broadcast or multicast <code>eth.dst</code> to the
> >          <code>MC_FLOOD</code> multicast group.
> >        </li>
> >
> > +      <li>
> > +        A priority-71 flow that outputs all IP packets with an Ethernet
> > +        broadcast or multicast <code>eth.dst</code> to the
> > +        <code>MC_FLOOD_L2</code> multicast group, which contains only
> > +        non-router logical ports.  If any connected router has
> > +        <code>options:mcast_relay=true</code>, the packet is also
> cloned to
> > +        the <code>MC_MROUTER_FLOOD</code> multicast group (which
> contains
> > +        only the router ports with relay enabled).  If any port has
> > +        <code>options:mcast_flood=true</code>, it is also cloned to the
> > +        <code>MC_STATIC</code> multicast group.  This prevents IP
> multicast
> > +        from being unnecessarily forwarded to routers that would drop
> it.
> > +      </li>
> > +
> >        <li>
> >          A priority-70 flow that outputs all packets with an Ethernet
> broadcast
> >          or multicast <code>eth.dst</code> to the
> <code>MC_FLOOD_L2</code>
> > diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at
> > index 6230fd039a..7c2f53da69 100644
> > --- a/tests/ovn-northd.at
> > +++ b/tests/ovn-northd.at
> > @@ -5863,7 +5863,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5877,7 +5879,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5899,7 +5903,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5915,7 +5921,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5939,7 +5947,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5957,7 +5967,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls2_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:01), action=(outport = "ls2-ro2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "vm2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -5980,7 +5992,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -6002,7 +6016,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -6031,7 +6047,9 @@ AT_CHECK([grep "ls_in_l2_lkup" ls1_lflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01 && is_chassis_resident("cr-ro1-ls1")), action=(outport =
> "ls1-ro1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:02), action=(outport = "vm1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -8365,6 +8383,127 @@ OVN_CLEANUP_NORTHD
> >  AT_CLEANUP
> >  ])
> >
> > +OVN_FOR_EACH_NORTHD_NO_HV([
> > +AT_SETUP([IP multicast flood without IGMP relay])
> > +AT_KEYWORDS([mcast_relay])
> > +ovn_start
> > +
> > +check ovn-nbctl lr-add lr0
> > +check ovn-nbctl ls-add ls0
> > +
> > +check ovn-nbctl lrp-add lr0 lrp0 00:00:00:00:00:01 10.0.0.1/24
> fe80::1/64
> > +check ovn-nbctl lsp-add-router-port ls0 lsp0-router lrp0
> > +
> > +check ovn-nbctl lsp-add ls0 lsp0 -- \
> > +    lsp-set-addresses lsp0 "00:00:00:00:00:02 10.0.0.2"
> > +
> > +dnl IP multicast packet from lsp0.
> > +mcast_pkt='inport == "lsp0" && eth.src == 00:00:00:00:00:02 && eth.dst
> == 01:00:5e:00:01:2a && ip4.src == 10.0.0.2 && ip4.dst == 239.0.1.42 &&
> ip.ttl == 64 && udp.src == 42 && udp.dst == 43'
> > +
> > +dnl ARP broadcast from lsp0.
> > +arp_pkt='inport == "lsp0" && eth.src == 00:00:00:00:00:02 && eth.dst ==
> ff:ff:ff:ff:ff:ff && arp.op == 1 && arp.sha == 00:00:00:00:00:02 && arp.spa
> == 10.0.0.2 && arp.tha == 00:00:00:00:00:00 && arp.tpa == 10.0.0.3'
> > +
> > +dnl Gratuitous ND NA multicast from lsp0.
> > +nd_na_pkt='inport == "lsp0" && eth.src == 00:00:00:00:00:02 && eth.dst
> == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==
> ff02::1 && icmp6.type == 136 && nd.target == fe80::200:ff:fe00:2'
> > +
> > +dnl Router solicitation multicast from lsp0.
> > +nd_rs_pkt='inport == "lsp0" && eth.src == 00:00:00:00:00:02 && eth.dst
> == 33:33:00:00:00:02 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==
> ff02::2 && icmp6.type == 133 && ip.ttl == 255'
> > +
> > +dnl Router advertisement multicast from lsp0.
> > +nd_ra_pkt='inport == "lsp0" && eth.src == 00:00:00:00:00:02 && eth.dst
> == 33:33:00:00:00:01 && ip6.src == fe80::200:ff:fe00:2 && ip6.dst ==
> ff02::1 && icmp6.type == 134 && ip.ttl == 255'
> > +
> > +dnl Scenario 1: default, no relay, no snooping.
> > +dnl The eth.mcast && ip flow should use _MC_flood_l2 not _MC_flood.
> > +check ovn-nbctl --wait=sb sync
> > +
> > +ovn-sbctl dump-flows ls0 > lsflows
> > +AT_CAPTURE_FILE([lsflows])
> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows | grep -e 'priority=71' -e
> 'priority=72' | ovn_strip_lflows], [0], [dnl
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > +])
> > +
> > +dnl Verify packet forwarding: IP multicast should not reach the router
> > +dnl port, while ARP, ND NA, ND RS and ND RA should.
> > +AT_CHECK([ovn_trace ls0 "$mcast_pkt" | grep 'outport="lsp0-router"'],
> [1])
> > +AT_CHECK([ovn_trace ls0 "$arp_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_na_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_rs_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_ra_pkt" | grep -q 'outport="lsp0-router"'])
> > +
> > +dnl Scenario 2: relay enabled on the router but snooping not enabled on
> the switch.
> > +dnl No priority 80 flow is installed because build_mcast_flood_lswitch
> returns
> > +dnl early when snooping is disabled, so the priority 71 flow is the
> only path
> > +dnl for IP multicast to reach relay-enabled routers via
> _MC_mrouter_flood.
> > +check ovn-nbctl set logical_router lr0 options:mcast_relay="true"
> > +check ovn-nbctl --wait=sb sync
> > +
> > +ovn-sbctl dump-flows ls0 > lsflows2
> > +AT_CAPTURE_FILE([lsflows2])
> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows2 | grep -e 'priority=71' -e
> 'priority=72' | ovn_strip_lflows], [0], [dnl
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> ip), action=(clone { outport = "_MC_mrouter_flood"; output; }; 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;)
> > +])
> > +
> > +dnl Verify packet forwarding: all packet types should reach the router
> port.
> > +AT_CHECK([ovn_trace ls0 "$mcast_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$arp_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_na_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_rs_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_ra_pkt" | grep -q 'outport="lsp0-router"'])
> > +
> > +dnl Scenario 3: relay enabled on the router and snooping enabled on the
> switch.
> > +dnl The eth.mcast && ip flow should include _MC_mrouter_flood for
> relay-enabled
> > +dnl router ports plus _MC_flood_l2 for regular ports.
> > +check ovn-nbctl set logical_switch ls0 other_config:mcast_snoop="true"
> > +check ovn-nbctl --wait=sb sync
> > +
> > +ovn-sbctl dump-flows ls0 > lsflows3
> > +AT_CAPTURE_FILE([lsflows3])
> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows3 | grep -e 'priority=71' -e
> 'priority=72' | ovn_strip_lflows], [0], [dnl
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> ip), action=(clone { outport = "_MC_mrouter_flood"; output; }; 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;)
> > +])
> > +
> > +dnl Verify packet forwarding: all packet types should reach the router
> port.
> > +AT_CHECK([ovn_trace ls0 "$mcast_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$arp_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_na_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_rs_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_ra_pkt" | grep -q 'outport="lsp0-router"'])
> > +
> > +dnl Scenario 4: also enable flood_unregistered on the switch.
> > +dnl The priority 71 flow should still have _MC_mrouter_flood and
> _MC_flood_l2.
> > +dnl There should be no priority 80 flow for ip4.mcast || ip6.mcast
> because
> > +dnl flood_unregistered causes build_mcast_flood_lswitch to return early.
> > +check ovn-nbctl set logical_switch ls0
> other_config:mcast_flood_unregistered="true"
> > +check ovn-nbctl --wait=sb sync
> > +
> > +ovn-sbctl dump-flows ls0 > lsflows4
> > +AT_CAPTURE_FILE([lsflows4])
> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows4 | grep -e 'priority=71' -e
> 'priority=72' | ovn_strip_lflows], [0], [dnl
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> ip), action=(clone { outport = "_MC_mrouter_flood"; output; }; 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;)
> > +])
> > +
> > +dnl Verify there is no priority 80 flow for ip4.mcast || ip6.mcast when
> flood_unregistered is set.
> > +AT_CHECK([grep -e 'ls_in_l2_lkup' lsflows4 | grep -e 'priority=80' |
> grep -F 'ip4.mcast || ip6.mcast'], [1])
> > +
> > +dnl Verify packet forwarding: all packet types should reach the router
> port.
> > +AT_CHECK([ovn_trace ls0 "$mcast_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$arp_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_na_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_rs_pkt" | grep -q 'outport="lsp0-router"'])
> > +AT_CHECK([ovn_trace ls0 "$nd_ra_pkt" | grep -q 'outport="lsp0-router"'])
> > +
> > +OVN_CLEANUP_NORTHD
> > +AT_CLEANUP
> > +])
> > +
> >  OVN_FOR_EACH_NORTHD_NO_HV_PARALLELIZATION([
> >  AT_SETUP([ACLs after lb])
> >  AT_KEYWORDS([acl])
> > @@ -9678,7 +9817,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=100  , match=(reg8[[23]] ==
> 1), action=(output;)
> >    table=??(ls_in_l2_lkup      ), priority=110  , match=(eth.dst ==
> $svc_monitor_mac && (tcp || icmp || icmp6)),
> action=(handle_svc_check(inport);)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),
> action=(output;)
> > @@ -9714,7 +9855,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),
> action=(output;)
> > @@ -9749,7 +9892,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),
> action=(output;)
> > @@ -9785,7 +9930,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(drop;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "sw0p1"), action=(drop;)
> > @@ -9821,7 +9968,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(drop;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "sw0p1"), action=(drop;)
> > @@ -9861,7 +10010,9 @@ ovn_strip_lflows ], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:01:01), action=(outport = "sw0p1"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:02:02), action=(outport = "sw0p2"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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_unknown   ), priority=0    , match=(1),
> action=(output;)
> >    table=??(ls_in_l2_unknown   ), priority=50   , match=(outport ==
> "none"), action=(drop;)
> >    table=??(ls_out_apply_port_sec), priority=0    , match=(1),
> action=(output;)
> > @@ -14201,7 +14352,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:ff:02 && is_chassis_resident("cr-lr0-public")), action=(outport
> = "public-lr0"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 30:54:00:00:00:03 && is_chassis_resident("sw0-port1")), action=(outport =
> "public-lr0"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -14379,7 +14532,9 @@ AT_CHECK([grep "ls_in_l2_lkup" publicflows |
> ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 00:00:00:00:ff:02 && is_chassis_resident("cr-public-lr0")), action=(outport
> = "public-lr0"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=50   , match=(eth.dst ==
> 30:54:00:00:00:03 && is_chassis_resident("sw0-port1")), action=(outport =
> "public-lr0"; output;)
> >    table=??(ls_in_l2_lkup      ), priority=70   , match=(eth.mcast),
> action=(outport = "_MC_flood_l2"; output;)
> > -  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> (arp || ip)), action=(outport = "_MC_flood"; output;)
> > +  table=??(ls_in_l2_lkup      ), priority=71   , match=(eth.mcast &&
> arp), action=(outport = "_MC_flood"; output;)
> > +  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;)
> > @@ -14541,7 +14696,7 @@ AT_CHECK([ovn-sbctl dump-flows ls | grep
> ls_in_l2_lkup | grep -E "tcp.dst == 179
> >  AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep "arp.op
> == 2 && arp.tpa == 172.16.1.1" | ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=100  , match=(arp.op == 2 &&
> arp.tpa == 172.16.1.1), action=(clone { outport = "lsp-bgp"; output; };
> outport = "ls-lr"; output;)
> >  ])
> > -AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep "&&
> nd_na" | ovn_strip_lflows], [0], [dnl
> > +AT_CHECK([ovn-sbctl dump-flows ls | grep ls_in_l2_lkup | grep "ip6.dst
> == .* && nd_na" | ovn_strip_lflows], [0], [dnl
> >    table=??(ls_in_l2_lkup      ), priority=100  , match=(ip6.dst ==
> fe80::ac:10ff:fe01:1 && nd_na), action=(clone { outport = "lsp-bgp";
> output; }; outport = "ls-lr"; output;)
> >  ])
> >
> > --
> > 2.53.0
> >
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev


Looks good to me, thanks.
Acked-by: Ales Musil <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to