diff mbox series

[ovs-dev,v2,1/2] tests: Move ovn interconnection tests to ovn-ic.at.

Message ID 20240312105649.1197509-1-mheib@redhat.com
State Accepted
Headers show
Series [ovs-dev,v2,1/2] tests: Move ovn interconnection tests to ovn-ic.at. | expand

Checks

Context Check Description
ovsrobot/apply-robot success apply and check: success
ovsrobot/github-robot-_Build_and_Test success github build: passed
ovsrobot/github-robot-_ovn-kubernetes success github build: passed

Commit Message

Mohammad Heib March 12, 2024, 10:56 a.m. UTC
Move ovn-ic tests that exist in ovn.at to ovn-ic.at.

Signed-off-by: Mohammad Heib <mheib@redhat.com>
---
 tests/ovn-ic.at | 687 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/ovn.at    | 686 -----------------------------------------------
 2 files changed, 687 insertions(+), 686 deletions(-)

Comments

Dumitru Ceara March 28, 2024, 2:01 p.m. UTC | #1
On 3/12/24 11:56, Mohammad Heib wrote:
> Move ovn-ic tests that exist in ovn.at to ovn-ic.at.
> 
> Signed-off-by: Mohammad Heib <mheib@redhat.com>
> ---

Thanks, Mohammad!  Applied to main and 24.03.

Regards,
Dumitru
diff mbox series

Patch

diff --git a/tests/ovn-ic.at b/tests/ovn-ic.at
index 44dbf8ab1..12267e960 100644
--- a/tests/ovn-ic.at
+++ b/tests/ovn-ic.at
@@ -1442,3 +1442,690 @@  OVN_CLEANUP_IC([az1], [az2])
 
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([interconnection])
+AT_KEYWORDS([slowtest])
+
+ovn_init_ic_db
+# The number needs to stay relatively low due to high memory consumption
+# with address sanitizers enabled.
+n_az=3
+n_ts=3
+for i in `seq 1 $n_az`; do
+    ovn_start az$i
+done
+
+net_add n1
+
+# 1 HV and 1 GW per AZ
+for az in `seq 1 $n_az`; do
+    sim_add hv$az
+    as hv$az
+    check ovs-vsctl add-br br-phys
+    ovn_az_attach az$az n1 br-phys 192.168.$az.1 16
+    for p in `seq 1 $n_ts`; do
+        check ovs-vsctl -- add-port br-int vif$p -- \
+            set interface vif$p external-ids:iface-id=lsp$az-$p \
+            options:tx_pcap=hv$az/vif$p-tx.pcap \
+            options:rxq_pcap=hv$az/vif$p-rx.pcap \
+            ofport-request=$p
+    done
+
+    sim_add gw$az
+    as gw$az
+    check ovs-vsctl add-br br-phys
+    ovn_az_attach az$az n1 br-phys 192.168.$az.2 16
+    check ovs-vsctl set open . external-ids:ovn-is-interconn=true
+done
+
+for ts in `seq 1 $n_ts`; do
+    AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts$ts], [0], [ignore])
+    for az in `seq 1 $n_az`; do
+        echo "az$az: wait for ts$ts..."
+        check ovn_as az$az ovn-nbctl wait-until logical_switch ts$ts
+    done
+done
+
+for az in `seq 1 $n_az`; do
+    ovn_as az$az
+    check ovn-nbctl set nb_global . options:ic-route-learn=true
+    check ovn-nbctl set nb_global . options:ic-route-adv=true
+
+    # Each AZ has n_ts LSPi->LSi->LRi connecting to each TSi
+    echo
+    echo "az$az"
+    for i in `seq 1 $n_ts`; do
+        lsp_mac=00:00:00:0$az:0$i:00
+        lrp_ls_mac=00:00:00:0$az:0$i:01
+        lrp_ts_mac=00:00:00:0$az:0$i:02
+        lsp_ip=10.$az.$i.123
+        lrp_ls_ip=10.$az.$i.1
+        lrp_ts_ip=169.254.$i.$az
+
+        check ovn-nbctl ls-add ls$az-$i
+        check ovn-nbctl lsp-add ls$az-$i lsp$az-$i
+        check ovn-nbctl lsp-set-addresses lsp$az-$i "$lsp_mac $lsp_ip"
+
+        check ovn-nbctl lr-add lr$az-$i
+
+        check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ls$az-$i $lrp_ls_mac $lrp_ls_ip/24
+        check ovn-nbctl lsp-add ls$az-$i lsp-ls$az-$i-lr$az-$i
+        check ovn-nbctl lsp-set-addresses lsp-ls$az-$i-lr$az-$i router
+        check ovn-nbctl lsp-set-type lsp-ls$az-$i-lr$az-$i router
+        check ovn-nbctl lsp-set-options lsp-ls$az-$i-lr$az-$i router-port=lrp-lr$az-$i-ls$az-$i
+
+        check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ts$i $lrp_ts_mac $lrp_ts_ip/24
+        check ovn-nbctl lsp-add ts$i lsp-ts$i-lr$az-$i
+        check ovn-nbctl lsp-set-addresses lsp-ts$i-lr$az-$i router
+        check ovn-nbctl lsp-set-type lsp-ts$i-lr$az-$i router
+        check ovn-nbctl lsp-set-options lsp-ts$i-lr$az-$i router-port=lrp-lr$az-$i-ts$i
+        check ovn-nbctl lrp-set-gateway-chassis lrp-lr$az-$i-ts$i gw$az
+    done
+    check ovn-nbctl --wait=hv sync
+    ovn-sbctl list Port_Binding > az$az.ports
+    wait_for_ports_up
+done
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+OVN_POPULATE_ARP
+
+for i in `seq 1 $n_az`; do
+    check ovn_as az$i ovn-nbctl --wait=hv sync
+    ovn_as az$i ovn-sbctl dump-flows > az$i/sbflows
+done
+
+# Allow some time for ovn-northd and ovn-controller to catch up.
+# XXX This should be more systematic.
+sleep 2
+
+# Populate requested-chassis options for remote lsps
+for az in $(seq 1 $n_az); do
+    ovn_as az${az}
+    for ts in $(seq 1 $n_ts); do
+        for i in $(seq 1 $n_ts); do
+            if [[ $i -eq ${az} ]]; then
+                continue
+            fi
+            check ovn-nbctl lsp-set-options lsp-ts${ts}-lr${i}-${ts} requested-chassis=gw$i
+        done
+    done
+done
+
+ovn-ic-nbctl show > ic-nbctl.dump
+AT_CAPTURE_FILE([ic-nbctl.dump])
+
+(echo "---------ISB dump-----"
+ ovn-ic-sbctl show
+ echo "---------------------"
+ ovn-ic-sbctl list gateway
+ echo "---------------------"
+ ovn-ic-sbctl list datapath_binding
+ echo "---------------------"
+ ovn-ic-sbctl list port_binding
+ echo "---------------------"
+ ovn-ic-sbctl list route
+ echo "---------------------") > ic-sbctl.dump
+AT_CAPTURE_FILE([ic-sbctl.dump])
+
+AT_CAPTURE_FILE([expected])
+AT_CAPTURE_FILE([received])
+check_packets() {
+    > expected
+    > received
+    for az in `seq 1 $n_az`; do
+        for i in `seq 1 $n_ts`; do
+            pcap=hv$az/vif$i-tx.pcap
+            echo "--- $pcap" | tee -a expected >> received
+            if test -e $az-$i.expected; then
+                sort $az-$i.expected >> expected
+            fi
+            if test -e $pcap; then
+                $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | sort >> received
+            fi
+            echo | tee -a expected >> received
+        done
+    done
+
+    $at_diff expected received >/dev/null
+}
+
+# Send packets between AZs on each TS
+for s_az in $(seq 1 $n_az); do
+    ovn_as az${s_az}
+    as hv${s_az}
+    for d_az in $(seq 1 $n_az); do
+        if test $s_az = $d_az; then
+            continue
+        fi
+
+        for i in $(seq 1 $n_ts); do
+            echo
+            AS_BOX([packet from az$s_az to az$d_az via ts$i])
+            lsp_smac=00:00:00:0${s_az}:0$i:00
+            lsp_dmac=00:00:00:0${d_az}:0$i:00
+            lrp_ls_smac=00:00:00:0${s_az}:0$i:01
+            lrp_ls_dmac=00:00:00:0${d_az}:0$i:01
+            lsp_sip=10.${s_az}.$i.123
+            lsp_dip=10.${d_az}.$i.123
+
+            ovn_inport=lsp${s_az}-$i
+            packet="inport==\"$ovn_inport\" && eth.src==$lsp_smac && eth.dst==$lrp_ls_smac &&
+                    ip4 && ip.ttl==64 && ip4.src==$lsp_sip && ip4.dst==$lsp_dip &&
+                    udp && udp.src==53 && udp.dst==4369"
+            echo "sending: $packet"
+            AT_CHECK([ovn_trace --ovs "$packet" > ${s_az}-${d_az}-$i.ovn-trace])
+            OVS_WAIT_UNTIL([ovs-appctl -t ovn-controller inject-pkt "$packet"])
+            ovs_inport=$(ovs-vsctl --bare --columns=ofport find Interface external-ids:iface-id="$ovn_inport")
+
+            ovs_packet=$(echo $packet | ovstest test-ovn expr-to-packets)
+            echo ovs_inport=$ovs_inport ovs_packet=$ovs_packet
+            AT_CHECK([ovs-appctl ofproto/trace br-int in_port="$ovs_inport" "$ovs_packet" > ${s_az}-${d_az}-$i.ovs-trace])
+
+            # Packet to Expect
+            # The TTL should be decremented by 2.
+            packet="eth.src==$lrp_ls_dmac && eth.dst==$lsp_dmac &&
+                    ip4 && ip.ttl==62 && ip4.src==$lsp_sip && ip4.dst==$lsp_dip &&
+                    udp && udp.src==53 && udp.dst==4369"
+            echo $packet | ovstest test-ovn expr-to-packets >> ${d_az}-$i.expected
+        done
+    done
+done
+OVS_WAIT_UNTIL([check_packets], [$at_diff -F'^---' expected received])
+
+for az in `seq 1 $n_az`; do
+    OVN_CLEANUP_SBOX([hv$az])
+    OVN_CLEANUP_SBOX([gw$az])
+    OVN_CLEANUP_AZ([az$az])
+done
+
+OVN_CLEANUP_IC
+
+AT_CLEANUP
+])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([interconnection - static multicast])
+
+# Logical network:
+#
+#       AZ1                     |                     AZ2
+#   ---------------------------------------------------------------------
+#                               |
+#                               |     +-- LR2 --- LS2 --- LSP2 (sender)
+#                               |     |            |
+#                               |     |            +----- LSP4 (receiver)
+#                               |    /
+#     LSP1  --- LS1 --- LR1 --- TS ---
+#   (receiver)                  |    \
+#                               |     +-- LR3 --- LS3 --- LSP3 (receiver)
+#
+# LS1, LS2, LS3 configured to flood unregistered IP multicast.
+# LR1, LR2, LR3 configured to relay IP multicast.
+# LR1-LS1 configured to flood IP multicast traffic unconditionally.
+# LR3-LS3 configured to flood IP multicast traffic unconditionally.
+
+AT_CAPTURE_FILE([exp])
+AT_CAPTURE_FILE([rcv])
+check_packets() {
+    > exp
+    > rcv
+    if test "$1" = --uniq; then
+        sort="sort -u"; shift
+    else
+        sort=sort
+    fi
+    for tuple in "$@"; do
+        set $tuple; pcap=$1 type=$2
+        echo "--- $pcap" | tee -a exp >> rcv
+        $sort "$type" >> exp
+        $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | $sort >> rcv
+        echo | tee -a exp >> rcv
+    done
+
+    $at_diff exp rcv >/dev/null
+}
+
+ovn_init_ic_db
+ovn_start az1
+ovn_start az2
+
+net_add n1
+
+sim_add hv1
+as hv1
+check ovs-vsctl add-br br-phys
+ovn_az_attach az1 n1 br-phys 192.168.1.1 16
+check ovs-vsctl -- add-port br-int hv1-vif1 \
+    -- set interface hv1-vif1 external-ids:iface-id=lsp1 \
+       options:tx_pcap=hv1/vif1-tx.pcap \
+       options:rxq_pcap=hv1/vif1-rx.pcap
+check ovs-vsctl set open . external-ids:ovn-is-interconn=true
+
+sim_add hv2
+as hv2
+check ovs-vsctl add-br br-phys
+ovn_az_attach az2 n1 br-phys 192.168.2.1 16
+check ovs-vsctl -- add-port br-int hv2-vif1 \
+    -- set interface hv2-vif1 external-ids:iface-id=lsp2 \
+       options:tx_pcap=hv2/vif1-tx.pcap \
+       options:rxq_pcap=hv2/vif1-rx.pcap
+check ovs-vsctl -- add-port br-int hv2-vif2 \
+    -- set interface hv2-vif2 external-ids:iface-id=lsp3 \
+       options:tx_pcap=hv2/vif2-tx.pcap \
+       options:rxq_pcap=hv2/vif2-rx.pcap
+check ovs-vsctl -- add-port br-int hv2-vif3 \
+    -- set interface hv2-vif3 external-ids:iface-id=lsp4 \
+       options:tx_pcap=hv2/vif3-tx.pcap \
+       options:rxq_pcap=hv2/vif3-rx.pcap
+check ovs-vsctl set open . external-ids:ovn-is-interconn=true
+
+AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts], [0], [ignore])
+check ovn_as az1 ovn-nbctl wait-until logical_switch ts
+check ovn_as az2 ovn-nbctl wait-until logical_switch ts
+
+ovn_as az1
+check ovn-nbctl lr-add lr1 \
+    -- lrp-add lr1 lr1-ts 00:00:00:01:00:01 42.42.42.1/24 \
+    -- lrp-add lr1 lr1-ls1 00:00:00:01:01:00 43.43.43.1/24 \
+    -- lrp-set-gateway-chassis lr1-ts hv1
+check ovn-nbctl ls-add ls1 \
+    -- lsp-add ls1 ls1-lr1 \
+    -- lsp-set-addresses ls1-lr1 router \
+    -- lsp-set-type ls1-lr1 router \
+    -- lsp-set-options ls1-lr1 router-port=lr1-ls1 \
+    -- lsp-add ls1 lsp1
+check ovn-nbctl lsp-add ts ts-lr1 \
+    -- lsp-set-addresses ts-lr1 router \
+    -- lsp-set-type ts-lr1 router \
+    -- lsp-set-options ts-lr1 router-port=lr1-ts
+wait_for_ports_up
+
+ovn_as az2
+check ovn-nbctl lr-add lr2 \
+    -- lrp-add lr2 lr2-ts 00:00:00:02:00:01 42.42.42.2/24 \
+    -- lrp-add lr2 lr2-ls2 00:00:00:02:01:00 44.44.44.1/24 \
+    -- lrp-set-gateway-chassis lr2-ts hv2
+check ovn-nbctl ls-add ls2 \
+    -- lsp-add ls2 ls2-lr2 \
+    -- lsp-set-addresses ls2-lr2 router \
+    -- lsp-set-type ls2-lr2 router \
+    -- lsp-set-options ls2-lr2 router-port=lr2-ls2 \
+    -- lsp-add ls2 lsp2 \
+    -- lsp-add ls2 lsp4
+check ovn-nbctl lsp-add ts ts-lr2 \
+    -- lsp-set-addresses ts-lr2 router \
+    -- lsp-set-type ts-lr2 router \
+    -- lsp-set-options ts-lr2 router-port=lr2-ts
+
+check ovn-nbctl lr-add lr3 \
+    -- lrp-add lr3 lr3-ts 00:00:00:02:00:02 42.42.42.3/24 \
+    -- lrp-add lr3 lr3-ls3 00:00:00:02:02:00 44.44.45.1/24 \
+    -- lrp-set-gateway-chassis lr3-ts hv2
+check ovn-nbctl ls-add ls3 \
+    -- lsp-add ls3 ls3-lr3 \
+    -- lsp-set-addresses ls3-lr3 router \
+    -- lsp-set-type ls3-lr3 router \
+    -- lsp-set-options ls3-lr3 router-port=lr3-ls3 \
+    -- lsp-add ls3 lsp3
+check ovn-nbctl lsp-add ts ts-lr3 \
+    -- lsp-set-addresses ts-lr3 router \
+    -- lsp-set-type ts-lr3 router \
+    -- lsp-set-options ts-lr3 router-port=lr3-ts
+
+wait_for_ports_up
+
+ovn_as az1
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr2])
+check ovn-nbctl lsp-set-options ts-lr2 requested-chassis=hv2
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr3])
+check ovn-nbctl lsp-set-options ts-lr3 requested-chassis=hv2
+
+ovn_as az2
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr1])
+check ovn-nbctl lsp-set-options ts-lr1 requested-chassis=hv1
+
+dnl Enable unregistered IP multicast flooding and IP multicast relay.
+ovn_as az1
+check ovn-nbctl set logical_switch ls1 other_config:mcast_snoop="true" \
+    other_config:mcast_flood_unregistered="true"
+check ovn-nbctl set logical_router lr1 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr1-ls1 options:mcast_flood="true"
+
+ovn_as az2
+check ovn-nbctl set logical_switch ls2 other_config:mcast_snoop="true" \
+    other_config:mcast_flood_unregistered="true"
+check ovn-nbctl set logical_router lr2 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr2-ts options:mcast_flood="true"
+check ovn-nbctl set logical_switch ls3 other_config:mcast_snoop="true" \
+    other_config:mcast_flood_unregistered="true"
+check ovn-nbctl set logical_router lr3 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr3-ls3 options:mcast_flood="true"
+
+check ovn_as az1 ovn-nbctl --wait=hv sync
+check ovn_as az2 ovn-nbctl --wait=hv sync
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+OVN_POPULATE_ARP
+
+# Send an IP multicast packet from lsp2, it should be forwarded
+# statically to lsp1, lsp3 and lsp4.
+> expected_az1
+> expected_az2
+> expected_az2_switched
+send_ip_multicast_pkt hv2-vif1 hv2 \
+    000000000001 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
+    e518e518000aed350000
+store_ip_multicast_pkt \
+    000000010100 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
+    e518e518000aed350000 expected_az1
+store_ip_multicast_pkt \
+    000000020200 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
+    e518e518000aed350000 expected_az2
+store_ip_multicast_pkt \
+    000000000001 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
+    e518e518000aed350000 expected_az2_switched
+
+OVS_WAIT_UNTIL(
+  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
+                 'hv2/vif2-tx.pcap expected_az2' \
+                 'hv2/vif3-tx.pcap expected_az2_switched'],
+  [$at_diff -F'^---' exp rcv])
+
+# Send an IP multicast packet from lsp2 towards 224.0.0.x, it should be
+# forwarded statically only to lsp3.
+as hv1 reset_pcap_file hv1-vif1 hv1/vif1
+as hv2 reset_pcap_file hv2-vif2 hv2/vif2
+as hv2 reset_pcap_file hv2-vif3 hv2/vif3
+> expected_az1
+> expected_az2
+> expected_az2_switched
+send_ip_multicast_pkt hv2-vif1 hv2 \
+    000000000001 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 224 0 0 1) 1e 20 8cae 11 \
+    e518e518000aed350000
+store_ip_multicast_pkt \
+    000000000001 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 224 0 0 1) 1e 20 8cae 11 \
+    e518e518000aed350000 expected_az2_switched
+
+OVS_WAIT_UNTIL(
+  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
+                 'hv2/vif2-tx.pcap expected_az2' \
+                 'hv2/vif3-tx.pcap expected_az2_switched'],
+  [$at_diff -F'^---' exp rcv])
+
+OVN_CLEANUP_SBOX([hv1],["/IGMP Querier enabled without a valid IPv4 or IPv6 address/d
+/IGMP Querier enabled with invalid ETH src address/d"])
+
+OVN_CLEANUP_SBOX([hv2],["/IGMP Querier enabled without a valid IPv4 or IPv6 address/d
+/IGMP Querier enabled with invalid ETH src address/d"])
+
+OVN_CLEANUP_IC([az1],[az2])
+AT_CLEANUP
+])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([interconnection - IGMP/MLD multicast])
+AT_KEYWORDS([IP-multicast])
+
+# Logical network:
+#
+#       AZ1                     |                     AZ2
+#   ---------------------------------------------------------------------
+#                               |
+#                               |     +-- LR2 --- LS2 --- LSP2 (sender)
+#                               |    /
+#     LSP1  --- LS1 --- LR1 --- TS ---
+#   (receiver)                  |    \
+#                               |     +-- LR3 --- LS3 --- LSP3 (receiver)
+#
+# LS1, LS2, LS3, TS configured to snoop IP multicast.
+# LR1, LR2, LR3 configured to relay IP multicast.
+# LR1-TS configured to flood IP multicast traffic unconditionally.
+# LR2-TS configured to flood IP multicast traffic unconditionally.
+# LR3-TS configured to flood IP multicast traffic unconditionally.
+
+AT_CAPTURE_FILE([exp])
+AT_CAPTURE_FILE([rcv])
+check_packets() {
+    > exp
+    > rcv
+    if test "$1" = --uniq; then
+        sort="sort -u"; shift
+    else
+        sort=sort
+    fi
+    for tuple in "$@"; do
+        set $tuple; pcap=$1 type=$2
+        echo "--- $pcap" | tee -a exp >> rcv
+        $sort "$type" >> exp
+        $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | $sort >> rcv
+        echo | tee -a exp >> rcv
+    done
+
+    $at_diff exp rcv >/dev/null
+}
+
+ovn_init_ic_db
+ovn_start az1
+ovn_start az2
+
+net_add n1
+
+sim_add hv1
+as hv1
+check ovs-vsctl add-br br-phys
+ovn_az_attach az1 n1 br-phys 192.168.1.1 16
+check ovs-vsctl -- add-port br-int hv1-vif1 \
+    -- set interface hv1-vif1 external-ids:iface-id=lsp1 \
+       options:tx_pcap=hv1/vif1-tx.pcap \
+       options:rxq_pcap=hv1/vif1-rx.pcap
+check ovs-vsctl set open . external-ids:ovn-is-interconn=true
+
+sim_add hv2
+as hv2
+check ovs-vsctl add-br br-phys
+ovn_az_attach az2 n1 br-phys 192.168.2.1 16
+check ovs-vsctl -- add-port br-int hv2-vif1 \
+    -- set interface hv2-vif1 external-ids:iface-id=lsp2 \
+       options:tx_pcap=hv2/vif1-tx.pcap \
+       options:rxq_pcap=hv2/vif1-rx.pcap
+check ovs-vsctl -- add-port br-int hv2-vif2 \
+    -- set interface hv2-vif2 external-ids:iface-id=lsp3 \
+       options:tx_pcap=hv2/vif2-tx.pcap \
+       options:rxq_pcap=hv2/vif2-rx.pcap
+check ovs-vsctl set open . external-ids:ovn-is-interconn=true
+
+AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts], [0], [ignore])
+check ovn_as az1 ovn-nbctl wait-until logical_switch ts
+check ovn_as az2 ovn-nbctl wait-until logical_switch ts
+
+ovn_as az1
+check ovn-nbctl lr-add lr1 \
+    -- lrp-add lr1 lr1-ts 00:00:00:01:00:01 42.42.42.1/24 4242::1/64 \
+    -- lrp-add lr1 lr1-ls1 00:00:00:01:01:00 43.43.43.1/24 4343::1/64\
+    -- lrp-set-gateway-chassis lr1-ts hv1
+check ovn-nbctl ls-add ls1 \
+    -- lsp-add ls1 ls1-lr1 \
+    -- lsp-set-addresses ls1-lr1 router \
+    -- lsp-set-type ls1-lr1 router \
+    -- lsp-set-options ls1-lr1 router-port=lr1-ls1 \
+    -- lsp-add ls1 lsp1
+check ovn-nbctl lsp-add ts ts-lr1 \
+    -- lsp-set-addresses ts-lr1 router \
+    -- lsp-set-type ts-lr1 router \
+    -- lsp-set-options ts-lr1 router-port=lr1-ts
+wait_for_ports_up
+
+ovn_as az2
+check ovn-nbctl lr-add lr2 \
+    -- lrp-add lr2 lr2-ts 00:00:00:02:00:01 42.42.42.2/24 4242::2/64 \
+    -- lrp-add lr2 lr2-ls2 00:00:00:02:01:00 44.44.44.1/24 4444::1/64 \
+    -- lrp-set-gateway-chassis lr2-ts hv2
+check ovn-nbctl ls-add ls2 \
+    -- lsp-add ls2 ls2-lr2 \
+    -- lsp-set-addresses ls2-lr2 router \
+    -- lsp-set-type ls2-lr2 router \
+    -- lsp-set-options ls2-lr2 router-port=lr2-ls2 \
+    -- lsp-add ls2 lsp2
+check ovn-nbctl lsp-add ts ts-lr2 \
+    -- lsp-set-addresses ts-lr2 router \
+    -- lsp-set-type ts-lr2 router \
+    -- lsp-set-options ts-lr2 router-port=lr2-ts
+
+check ovn-nbctl lr-add lr3 \
+    -- lrp-add lr3 lr3-ts 00:00:00:02:00:02 42.42.42.3/24 4242::3/64 \
+    -- lrp-add lr3 lr3-ls3 00:00:00:02:02:00 44.44.45.1/24 4445::1/64 \
+    -- lrp-set-gateway-chassis lr3-ts hv2
+check ovn-nbctl ls-add ls3 \
+    -- lsp-add ls3 ls3-lr3 \
+    -- lsp-set-addresses ls3-lr3 router \
+    -- lsp-set-type ls3-lr3 router \
+    -- lsp-set-options ls3-lr3 router-port=lr3-ls3 \
+    -- lsp-add ls3 lsp3
+check ovn-nbctl lsp-add ts ts-lr3 \
+    -- lsp-set-addresses ts-lr3 router \
+    -- lsp-set-type ts-lr3 router \
+    -- lsp-set-options ts-lr3 router-port=lr3-ts
+
+wait_for_ports_up
+
+ovn_as az1
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr2])
+check ovn-nbctl lsp-set-options ts-lr2 requested-chassis=hv2
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr3])
+check ovn-nbctl lsp-set-options ts-lr3 requested-chassis=hv2
+
+ovn_as az2
+OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr1])
+check ovn-nbctl lsp-set-options ts-lr1 requested-chassis=hv1
+
+dnl Enable IP multicast snooping and IP multicast relay.  Reports are
+dnl forwarded statically.
+ovn_as az1
+check ovn-nbctl set logical_switch ls1 other_config:mcast_snoop="true"
+check ovn-nbctl set Logical_Switch_Port ls1-lr1 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_router lr1 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr1-ts options:mcast_flood="true"
+check ovn-nbctl set logical_switch ts other_config:mcast_snoop="true"
+check ovn-nbctl set logical_switch_port ts-lr1 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_switch_port ts-lr2 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_switch_port ts-lr3 options:mcast_flood_reports="true"
+
+ovn_as az2
+check ovn-nbctl set logical_switch ls2 other_config:mcast_snoop="true"
+check ovn-nbctl set Logical_Switch_Port ls2-lr2 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_router lr2 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr2-ts options:mcast_flood="true"
+check ovn-nbctl set logical_switch ls3 other_config:mcast_snoop="true"
+check ovn-nbctl set Logical_Switch_Port ls3-lr3 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_router lr3 options:mcast_relay="true"
+check ovn-nbctl set logical_router_port lr3-ts options:mcast_flood="true"
+check ovn-nbctl set logical_switch ts other_config:mcast_snoop="true"
+check ovn-nbctl set logical_switch_port ts-lr1 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_switch_port ts-lr2 options:mcast_flood_reports="true"
+check ovn-nbctl set logical_switch_port ts-lr3 options:mcast_flood_reports="true"
+
+check ovn_as az1 ovn-nbctl --wait=hv sync
+check ovn_as az2 ovn-nbctl --wait=hv sync
+
+# Pre-populate the hypervisors' ARP tables so that we don't lose any
+# packets for ARP resolution (native tunneling doesn't queue packets
+# for ARP resolution).
+OVN_POPULATE_ARP
+
+# Inject IGMP Join for 239.0.1.68 on LSP1.
+send_igmp_v3_report hv1-vif1 hv1 \
+    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
+    $(ip_to_hex 239 0 1 68) 04 e9b9 \
+    /dev/null
+
+# Inject MLD Join for ff0a:dead:beef::1 on LSP1.
+send_mld_v2_report hv1-vif1 hv1 \
+    000000000001 10000000000000000000000000000001 \
+    ff0adeadbeef00000000000000000001 04 c0e4 \
+    /dev/null
+
+# Inject IGMP Join for 239.0.1.68 on LSP3.
+send_igmp_v3_report hv2-vif2 hv2 \
+    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
+    $(ip_to_hex 239 0 1 68) 04 e9b9 \
+    /dev/null
+
+# Inject MLD Join for ff0a:dead:beef::1 on LSP3.
+send_mld_v2_report hv2-vif2 hv2 \
+    000000000001 10000000000000000000000000000001 \
+    ff0adeadbeef00000000000000000001 04 c0e4 \
+    /dev/null
+
+# Check that the IGMP and MLD groups are learned on both AZs (on the LS
+# and TS).
+ovn_as az1
+wait_row_count IGMP_Group 2 address=239.0.1.68
+wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"'
+check ovn-nbctl --wait=hv sync
+
+ovn_as az2
+wait_row_count IGMP_Group 2 address=239.0.1.68
+wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"'
+check ovn-nbctl --wait=hv sync
+
+# Send an IP multicast packet from LSP2, it should be forwarded
+# to lsp1 and lsp3.
+> expected_az1
+> expected_az2
+send_ip_multicast_pkt hv2-vif1 hv2 \
+    000000000001 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
+    e518e518000aed350000
+store_ip_multicast_pkt \
+    000000010100 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
+    e518e518000aed350000 expected_az1
+store_ip_multicast_pkt \
+    000000020200 01005e000144 \
+    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
+    e518e518000aed350000 expected_az2
+
+send_ip6_multicast_pkt hv2-vif1 hv2 \
+    000000000001 333300000001 \
+    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
+    000e 40 11 \
+    93407a69000e2b4e61736461640a
+store_ip6_multicast_pkt \
+    000000010100 333300000001 \
+    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
+    000e 3e 11 \
+    93407a69000e2b4e61736461640a \
+    expected_az1
+store_ip6_multicast_pkt \
+    000000020200 333300000001 \
+    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
+    000e 3e 11 \
+    93407a69000e2b4e61736461640a \
+    expected_az2
+
+OVS_WAIT_UNTIL(
+  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
+                 'hv2/vif2-tx.pcap expected_az2'],
+  [$at_diff -F'^---' exp rcv])
+
+OVN_CLEANUP_SBOX([hv1], ["/IGMP Querier enabled without a valid IPv4/d
+/IGMP Querier enabled with invalid ETH src/d"])
+
+OVN_CLEANUP_SBOX([hv2], ["/IGMP Querier enabled without a valid IPv4/d
+/IGMP Querier enabled with invalid ETH src/d"])
+
+OVN_CLEANUP_IC([az1],[az2])
+AT_CLEANUP
+])
+
diff --git a/tests/ovn.at b/tests/ovn.at
index e87df6c8d..c2c1ce869 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -26272,692 +26272,6 @@  OVN_CLEANUP([hv1])
 AT_CLEANUP
 ])
 
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([interconnection])
-AT_KEYWORDS([slowtest])
-
-ovn_init_ic_db
-# The number needs to stay relatively low due to high memory consumption
-# with address sanitizers enabled.
-n_az=3
-n_ts=3
-for i in `seq 1 $n_az`; do
-    ovn_start az$i
-done
-
-net_add n1
-
-# 1 HV and 1 GW per AZ
-for az in `seq 1 $n_az`; do
-    sim_add hv$az
-    as hv$az
-    check ovs-vsctl add-br br-phys
-    ovn_az_attach az$az n1 br-phys 192.168.$az.1 16
-    for p in `seq 1 $n_ts`; do
-        check ovs-vsctl -- add-port br-int vif$p -- \
-            set interface vif$p external-ids:iface-id=lsp$az-$p \
-            options:tx_pcap=hv$az/vif$p-tx.pcap \
-            options:rxq_pcap=hv$az/vif$p-rx.pcap \
-            ofport-request=$p
-    done
-
-    sim_add gw$az
-    as gw$az
-    check ovs-vsctl add-br br-phys
-    ovn_az_attach az$az n1 br-phys 192.168.$az.2 16
-    check ovs-vsctl set open . external-ids:ovn-is-interconn=true
-done
-
-for ts in `seq 1 $n_ts`; do
-    AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts$ts], [0], [ignore])
-    for az in `seq 1 $n_az`; do
-        echo "az$az: wait for ts$ts..."
-        check ovn_as az$az ovn-nbctl wait-until logical_switch ts$ts
-    done
-done
-
-for az in `seq 1 $n_az`; do
-    ovn_as az$az
-    check ovn-nbctl set nb_global . options:ic-route-learn=true
-    check ovn-nbctl set nb_global . options:ic-route-adv=true
-
-    # Each AZ has n_ts LSPi->LSi->LRi connecting to each TSi
-    echo
-    echo "az$az"
-    for i in `seq 1 $n_ts`; do
-        lsp_mac=00:00:00:0$az:0$i:00
-        lrp_ls_mac=00:00:00:0$az:0$i:01
-        lrp_ts_mac=00:00:00:0$az:0$i:02
-        lsp_ip=10.$az.$i.123
-        lrp_ls_ip=10.$az.$i.1
-        lrp_ts_ip=169.254.$i.$az
-
-        check ovn-nbctl ls-add ls$az-$i
-        check ovn-nbctl lsp-add ls$az-$i lsp$az-$i
-        check ovn-nbctl lsp-set-addresses lsp$az-$i "$lsp_mac $lsp_ip"
-
-        check ovn-nbctl lr-add lr$az-$i
-
-        check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ls$az-$i $lrp_ls_mac $lrp_ls_ip/24
-        check ovn-nbctl lsp-add ls$az-$i lsp-ls$az-$i-lr$az-$i
-        check ovn-nbctl lsp-set-addresses lsp-ls$az-$i-lr$az-$i router
-        check ovn-nbctl lsp-set-type lsp-ls$az-$i-lr$az-$i router
-        check ovn-nbctl lsp-set-options lsp-ls$az-$i-lr$az-$i router-port=lrp-lr$az-$i-ls$az-$i
-
-        check ovn-nbctl lrp-add lr$az-$i lrp-lr$az-$i-ts$i $lrp_ts_mac $lrp_ts_ip/24
-        check ovn-nbctl lsp-add ts$i lsp-ts$i-lr$az-$i
-        check ovn-nbctl lsp-set-addresses lsp-ts$i-lr$az-$i router
-        check ovn-nbctl lsp-set-type lsp-ts$i-lr$az-$i router
-        check ovn-nbctl lsp-set-options lsp-ts$i-lr$az-$i router-port=lrp-lr$az-$i-ts$i
-        check ovn-nbctl lrp-set-gateway-chassis lrp-lr$az-$i-ts$i gw$az
-    done
-    check ovn-nbctl --wait=hv sync
-    ovn-sbctl list Port_Binding > az$az.ports
-    wait_for_ports_up
-done
-
-# Pre-populate the hypervisors' ARP tables so that we don't lose any
-# packets for ARP resolution (native tunneling doesn't queue packets
-# for ARP resolution).
-OVN_POPULATE_ARP
-
-for i in `seq 1 $n_az`; do
-    check ovn_as az$i ovn-nbctl --wait=hv sync
-    ovn_as az$i ovn-sbctl dump-flows > az$i/sbflows
-done
-
-# Allow some time for ovn-northd and ovn-controller to catch up.
-# XXX This should be more systematic.
-sleep 2
-
-# Populate requested-chassis options for remote lsps
-for az in $(seq 1 $n_az); do
-    ovn_as az${az}
-    for ts in $(seq 1 $n_ts); do
-        for i in $(seq 1 $n_ts); do
-            if [[ $i -eq ${az} ]]; then
-                continue
-            fi
-            check ovn-nbctl lsp-set-options lsp-ts${ts}-lr${i}-${ts} requested-chassis=gw$i
-        done
-    done
-done
-
-ovn-ic-nbctl show > ic-nbctl.dump
-AT_CAPTURE_FILE([ic-nbctl.dump])
-
-(echo "---------ISB dump-----"
- ovn-ic-sbctl show
- echo "---------------------"
- ovn-ic-sbctl list gateway
- echo "---------------------"
- ovn-ic-sbctl list datapath_binding
- echo "---------------------"
- ovn-ic-sbctl list port_binding
- echo "---------------------"
- ovn-ic-sbctl list route
- echo "---------------------") > ic-sbctl.dump
-AT_CAPTURE_FILE([ic-sbctl.dump])
-
-AT_CAPTURE_FILE([expected])
-AT_CAPTURE_FILE([received])
-check_packets() {
-    > expected
-    > received
-    for az in `seq 1 $n_az`; do
-        for i in `seq 1 $n_ts`; do
-            pcap=hv$az/vif$i-tx.pcap
-            echo "--- $pcap" | tee -a expected >> received
-            if test -e $az-$i.expected; then
-                sort $az-$i.expected >> expected
-            fi
-            if test -e $pcap; then
-                $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | sort >> received
-            fi
-            echo | tee -a expected >> received
-        done
-    done
-
-    $at_diff expected received >/dev/null
-}
-
-# Send packets between AZs on each TS
-for s_az in $(seq 1 $n_az); do
-    ovn_as az${s_az}
-    as hv${s_az}
-    for d_az in $(seq 1 $n_az); do
-        if test $s_az = $d_az; then
-            continue
-        fi
-
-        for i in $(seq 1 $n_ts); do
-            echo
-            AS_BOX([packet from az$s_az to az$d_az via ts$i])
-            lsp_smac=00:00:00:0${s_az}:0$i:00
-            lsp_dmac=00:00:00:0${d_az}:0$i:00
-            lrp_ls_smac=00:00:00:0${s_az}:0$i:01
-            lrp_ls_dmac=00:00:00:0${d_az}:0$i:01
-            lsp_sip=10.${s_az}.$i.123
-            lsp_dip=10.${d_az}.$i.123
-
-            ovn_inport=lsp${s_az}-$i
-            packet="inport==\"$ovn_inport\" && eth.src==$lsp_smac && eth.dst==$lrp_ls_smac &&
-                    ip4 && ip.ttl==64 && ip4.src==$lsp_sip && ip4.dst==$lsp_dip &&
-                    udp && udp.src==53 && udp.dst==4369"
-            echo "sending: $packet"
-            AT_CHECK([ovn_trace --ovs "$packet" > ${s_az}-${d_az}-$i.ovn-trace])
-            OVS_WAIT_UNTIL([ovs-appctl -t ovn-controller inject-pkt "$packet"])
-            ovs_inport=$(ovs-vsctl --bare --columns=ofport find Interface external-ids:iface-id="$ovn_inport")
-
-            ovs_packet=$(echo $packet | ovstest test-ovn expr-to-packets)
-            echo ovs_inport=$ovs_inport ovs_packet=$ovs_packet
-            AT_CHECK([ovs-appctl ofproto/trace br-int in_port="$ovs_inport" "$ovs_packet" > ${s_az}-${d_az}-$i.ovs-trace])
-
-            # Packet to Expect
-            # The TTL should be decremented by 2.
-            packet="eth.src==$lrp_ls_dmac && eth.dst==$lsp_dmac &&
-                    ip4 && ip.ttl==62 && ip4.src==$lsp_sip && ip4.dst==$lsp_dip &&
-                    udp && udp.src==53 && udp.dst==4369"
-            echo $packet | ovstest test-ovn expr-to-packets >> ${d_az}-$i.expected
-        done
-    done
-done
-OVS_WAIT_UNTIL([check_packets], [$at_diff -F'^---' expected received])
-
-for az in `seq 1 $n_az`; do
-    OVN_CLEANUP_SBOX([hv$az])
-    OVN_CLEANUP_SBOX([gw$az])
-    OVN_CLEANUP_AZ([az$az])
-done
-
-OVN_CLEANUP_IC
-
-AT_CLEANUP
-])
-
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([interconnection - static multicast])
-
-# Logical network:
-#
-#       AZ1                     |                     AZ2
-#   ---------------------------------------------------------------------
-#                               |
-#                               |     +-- LR2 --- LS2 --- LSP2 (sender)
-#                               |     |            |
-#                               |     |            +----- LSP4 (receiver)
-#                               |    /
-#     LSP1  --- LS1 --- LR1 --- TS ---
-#   (receiver)                  |    \
-#                               |     +-- LR3 --- LS3 --- LSP3 (receiver)
-#
-# LS1, LS2, LS3 configured to flood unregistered IP multicast.
-# LR1, LR2, LR3 configured to relay IP multicast.
-# LR1-LS1 configured to flood IP multicast traffic unconditionally.
-# LR3-LS3 configured to flood IP multicast traffic unconditionally.
-
-AT_CAPTURE_FILE([exp])
-AT_CAPTURE_FILE([rcv])
-check_packets() {
-    > exp
-    > rcv
-    if test "$1" = --uniq; then
-        sort="sort -u"; shift
-    else
-        sort=sort
-    fi
-    for tuple in "$@"; do
-        set $tuple; pcap=$1 type=$2
-        echo "--- $pcap" | tee -a exp >> rcv
-        $sort "$type" >> exp
-        $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | $sort >> rcv
-        echo | tee -a exp >> rcv
-    done
-
-    $at_diff exp rcv >/dev/null
-}
-
-ovn_init_ic_db
-ovn_start az1
-ovn_start az2
-
-net_add n1
-
-sim_add hv1
-as hv1
-check ovs-vsctl add-br br-phys
-ovn_az_attach az1 n1 br-phys 192.168.1.1 16
-check ovs-vsctl -- add-port br-int hv1-vif1 \
-    -- set interface hv1-vif1 external-ids:iface-id=lsp1 \
-       options:tx_pcap=hv1/vif1-tx.pcap \
-       options:rxq_pcap=hv1/vif1-rx.pcap
-check ovs-vsctl set open . external-ids:ovn-is-interconn=true
-
-sim_add hv2
-as hv2
-check ovs-vsctl add-br br-phys
-ovn_az_attach az2 n1 br-phys 192.168.2.1 16
-check ovs-vsctl -- add-port br-int hv2-vif1 \
-    -- set interface hv2-vif1 external-ids:iface-id=lsp2 \
-       options:tx_pcap=hv2/vif1-tx.pcap \
-       options:rxq_pcap=hv2/vif1-rx.pcap
-check ovs-vsctl -- add-port br-int hv2-vif2 \
-    -- set interface hv2-vif2 external-ids:iface-id=lsp3 \
-       options:tx_pcap=hv2/vif2-tx.pcap \
-       options:rxq_pcap=hv2/vif2-rx.pcap
-check ovs-vsctl -- add-port br-int hv2-vif3 \
-    -- set interface hv2-vif3 external-ids:iface-id=lsp4 \
-       options:tx_pcap=hv2/vif3-tx.pcap \
-       options:rxq_pcap=hv2/vif3-rx.pcap
-check ovs-vsctl set open . external-ids:ovn-is-interconn=true
-
-AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts], [0], [ignore])
-check ovn_as az1 ovn-nbctl wait-until logical_switch ts
-check ovn_as az2 ovn-nbctl wait-until logical_switch ts
-
-ovn_as az1
-check ovn-nbctl lr-add lr1 \
-    -- lrp-add lr1 lr1-ts 00:00:00:01:00:01 42.42.42.1/24 \
-    -- lrp-add lr1 lr1-ls1 00:00:00:01:01:00 43.43.43.1/24 \
-    -- lrp-set-gateway-chassis lr1-ts hv1
-check ovn-nbctl ls-add ls1 \
-    -- lsp-add ls1 ls1-lr1 \
-    -- lsp-set-addresses ls1-lr1 router \
-    -- lsp-set-type ls1-lr1 router \
-    -- lsp-set-options ls1-lr1 router-port=lr1-ls1 \
-    -- lsp-add ls1 lsp1
-check ovn-nbctl lsp-add ts ts-lr1 \
-    -- lsp-set-addresses ts-lr1 router \
-    -- lsp-set-type ts-lr1 router \
-    -- lsp-set-options ts-lr1 router-port=lr1-ts
-wait_for_ports_up
-
-ovn_as az2
-check ovn-nbctl lr-add lr2 \
-    -- lrp-add lr2 lr2-ts 00:00:00:02:00:01 42.42.42.2/24 \
-    -- lrp-add lr2 lr2-ls2 00:00:00:02:01:00 44.44.44.1/24 \
-    -- lrp-set-gateway-chassis lr2-ts hv2
-check ovn-nbctl ls-add ls2 \
-    -- lsp-add ls2 ls2-lr2 \
-    -- lsp-set-addresses ls2-lr2 router \
-    -- lsp-set-type ls2-lr2 router \
-    -- lsp-set-options ls2-lr2 router-port=lr2-ls2 \
-    -- lsp-add ls2 lsp2 \
-    -- lsp-add ls2 lsp4
-check ovn-nbctl lsp-add ts ts-lr2 \
-    -- lsp-set-addresses ts-lr2 router \
-    -- lsp-set-type ts-lr2 router \
-    -- lsp-set-options ts-lr2 router-port=lr2-ts
-
-check ovn-nbctl lr-add lr3 \
-    -- lrp-add lr3 lr3-ts 00:00:00:02:00:02 42.42.42.3/24 \
-    -- lrp-add lr3 lr3-ls3 00:00:00:02:02:00 44.44.45.1/24 \
-    -- lrp-set-gateway-chassis lr3-ts hv2
-check ovn-nbctl ls-add ls3 \
-    -- lsp-add ls3 ls3-lr3 \
-    -- lsp-set-addresses ls3-lr3 router \
-    -- lsp-set-type ls3-lr3 router \
-    -- lsp-set-options ls3-lr3 router-port=lr3-ls3 \
-    -- lsp-add ls3 lsp3
-check ovn-nbctl lsp-add ts ts-lr3 \
-    -- lsp-set-addresses ts-lr3 router \
-    -- lsp-set-type ts-lr3 router \
-    -- lsp-set-options ts-lr3 router-port=lr3-ts
-
-wait_for_ports_up
-
-ovn_as az1
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr2])
-check ovn-nbctl lsp-set-options ts-lr2 requested-chassis=hv2
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr3])
-check ovn-nbctl lsp-set-options ts-lr3 requested-chassis=hv2
-
-ovn_as az2
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr1])
-check ovn-nbctl lsp-set-options ts-lr1 requested-chassis=hv1
-
-dnl Enable unregistered IP multicast flooding and IP multicast relay.
-ovn_as az1
-check ovn-nbctl set logical_switch ls1 other_config:mcast_snoop="true" \
-    other_config:mcast_flood_unregistered="true"
-check ovn-nbctl set logical_router lr1 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr1-ls1 options:mcast_flood="true"
-
-ovn_as az2
-check ovn-nbctl set logical_switch ls2 other_config:mcast_snoop="true" \
-    other_config:mcast_flood_unregistered="true"
-check ovn-nbctl set logical_router lr2 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr2-ts options:mcast_flood="true"
-check ovn-nbctl set logical_switch ls3 other_config:mcast_snoop="true" \
-    other_config:mcast_flood_unregistered="true"
-check ovn-nbctl set logical_router lr3 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr3-ls3 options:mcast_flood="true"
-
-check ovn_as az1 ovn-nbctl --wait=hv sync
-check ovn_as az2 ovn-nbctl --wait=hv sync
-
-# Pre-populate the hypervisors' ARP tables so that we don't lose any
-# packets for ARP resolution (native tunneling doesn't queue packets
-# for ARP resolution).
-OVN_POPULATE_ARP
-
-# Send an IP multicast packet from lsp2, it should be forwarded
-# statically to lsp1, lsp3 and lsp4.
-> expected_az1
-> expected_az2
-> expected_az2_switched
-send_ip_multicast_pkt hv2-vif1 hv2 \
-    000000000001 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
-    e518e518000aed350000
-store_ip_multicast_pkt \
-    000000010100 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
-    e518e518000aed350000 expected_az1
-store_ip_multicast_pkt \
-    000000020200 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
-    e518e518000aed350000 expected_az2
-store_ip_multicast_pkt \
-    000000000001 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
-    e518e518000aed350000 expected_az2_switched
-
-OVS_WAIT_UNTIL(
-  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
-                 'hv2/vif2-tx.pcap expected_az2' \
-                 'hv2/vif3-tx.pcap expected_az2_switched'],
-  [$at_diff -F'^---' exp rcv])
-
-# Send an IP multicast packet from lsp2 towards 224.0.0.x, it should be
-# forwarded statically only to lsp3.
-as hv1 reset_pcap_file hv1-vif1 hv1/vif1
-as hv2 reset_pcap_file hv2-vif2 hv2/vif2
-as hv2 reset_pcap_file hv2-vif3 hv2/vif3
-> expected_az1
-> expected_az2
-> expected_az2_switched
-send_ip_multicast_pkt hv2-vif1 hv2 \
-    000000000001 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 224 0 0 1) 1e 20 8cae 11 \
-    e518e518000aed350000
-store_ip_multicast_pkt \
-    000000000001 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 224 0 0 1) 1e 20 8cae 11 \
-    e518e518000aed350000 expected_az2_switched
-
-OVS_WAIT_UNTIL(
-  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
-                 'hv2/vif2-tx.pcap expected_az2' \
-                 'hv2/vif3-tx.pcap expected_az2_switched'],
-  [$at_diff -F'^---' exp rcv])
-
-OVN_CLEANUP_SBOX([hv1],["/IGMP Querier enabled without a valid IPv4 or IPv6 address/d
-/IGMP Querier enabled with invalid ETH src address/d"])
-
-OVN_CLEANUP_SBOX([hv2],["/IGMP Querier enabled without a valid IPv4 or IPv6 address/d
-/IGMP Querier enabled with invalid ETH src address/d"])
-
-OVN_CLEANUP_IC([az1],[az2])
-AT_CLEANUP
-])
-
-OVN_FOR_EACH_NORTHD([
-AT_SETUP([interconnection - IGMP/MLD multicast])
-AT_KEYWORDS([IP-multicast])
-
-# Logical network:
-#
-#       AZ1                     |                     AZ2
-#   ---------------------------------------------------------------------
-#                               |
-#                               |     +-- LR2 --- LS2 --- LSP2 (sender)
-#                               |    /
-#     LSP1  --- LS1 --- LR1 --- TS ---
-#   (receiver)                  |    \
-#                               |     +-- LR3 --- LS3 --- LSP3 (receiver)
-#
-# LS1, LS2, LS3, TS configured to snoop IP multicast.
-# LR1, LR2, LR3 configured to relay IP multicast.
-# LR1-TS configured to flood IP multicast traffic unconditionally.
-# LR2-TS configured to flood IP multicast traffic unconditionally.
-# LR3-TS configured to flood IP multicast traffic unconditionally.
-
-AT_CAPTURE_FILE([exp])
-AT_CAPTURE_FILE([rcv])
-check_packets() {
-    > exp
-    > rcv
-    if test "$1" = --uniq; then
-        sort="sort -u"; shift
-    else
-        sort=sort
-    fi
-    for tuple in "$@"; do
-        set $tuple; pcap=$1 type=$2
-        echo "--- $pcap" | tee -a exp >> rcv
-        $sort "$type" >> exp
-        $PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" $pcap | $sort >> rcv
-        echo | tee -a exp >> rcv
-    done
-
-    $at_diff exp rcv >/dev/null
-}
-
-ovn_init_ic_db
-ovn_start az1
-ovn_start az2
-
-net_add n1
-
-sim_add hv1
-as hv1
-check ovs-vsctl add-br br-phys
-ovn_az_attach az1 n1 br-phys 192.168.1.1 16
-check ovs-vsctl -- add-port br-int hv1-vif1 \
-    -- set interface hv1-vif1 external-ids:iface-id=lsp1 \
-       options:tx_pcap=hv1/vif1-tx.pcap \
-       options:rxq_pcap=hv1/vif1-rx.pcap
-check ovs-vsctl set open . external-ids:ovn-is-interconn=true
-
-sim_add hv2
-as hv2
-check ovs-vsctl add-br br-phys
-ovn_az_attach az2 n1 br-phys 192.168.2.1 16
-check ovs-vsctl -- add-port br-int hv2-vif1 \
-    -- set interface hv2-vif1 external-ids:iface-id=lsp2 \
-       options:tx_pcap=hv2/vif1-tx.pcap \
-       options:rxq_pcap=hv2/vif1-rx.pcap
-check ovs-vsctl -- add-port br-int hv2-vif2 \
-    -- set interface hv2-vif2 external-ids:iface-id=lsp3 \
-       options:tx_pcap=hv2/vif2-tx.pcap \
-       options:rxq_pcap=hv2/vif2-rx.pcap
-check ovs-vsctl set open . external-ids:ovn-is-interconn=true
-
-AT_CHECK([ovn-ic-nbctl create Transit_Switch name=ts], [0], [ignore])
-check ovn_as az1 ovn-nbctl wait-until logical_switch ts
-check ovn_as az2 ovn-nbctl wait-until logical_switch ts
-
-ovn_as az1
-check ovn-nbctl lr-add lr1 \
-    -- lrp-add lr1 lr1-ts 00:00:00:01:00:01 42.42.42.1/24 4242::1/64 \
-    -- lrp-add lr1 lr1-ls1 00:00:00:01:01:00 43.43.43.1/24 4343::1/64\
-    -- lrp-set-gateway-chassis lr1-ts hv1
-check ovn-nbctl ls-add ls1 \
-    -- lsp-add ls1 ls1-lr1 \
-    -- lsp-set-addresses ls1-lr1 router \
-    -- lsp-set-type ls1-lr1 router \
-    -- lsp-set-options ls1-lr1 router-port=lr1-ls1 \
-    -- lsp-add ls1 lsp1
-check ovn-nbctl lsp-add ts ts-lr1 \
-    -- lsp-set-addresses ts-lr1 router \
-    -- lsp-set-type ts-lr1 router \
-    -- lsp-set-options ts-lr1 router-port=lr1-ts
-wait_for_ports_up
-
-ovn_as az2
-check ovn-nbctl lr-add lr2 \
-    -- lrp-add lr2 lr2-ts 00:00:00:02:00:01 42.42.42.2/24 4242::2/64 \
-    -- lrp-add lr2 lr2-ls2 00:00:00:02:01:00 44.44.44.1/24 4444::1/64 \
-    -- lrp-set-gateway-chassis lr2-ts hv2
-check ovn-nbctl ls-add ls2 \
-    -- lsp-add ls2 ls2-lr2 \
-    -- lsp-set-addresses ls2-lr2 router \
-    -- lsp-set-type ls2-lr2 router \
-    -- lsp-set-options ls2-lr2 router-port=lr2-ls2 \
-    -- lsp-add ls2 lsp2
-check ovn-nbctl lsp-add ts ts-lr2 \
-    -- lsp-set-addresses ts-lr2 router \
-    -- lsp-set-type ts-lr2 router \
-    -- lsp-set-options ts-lr2 router-port=lr2-ts
-
-check ovn-nbctl lr-add lr3 \
-    -- lrp-add lr3 lr3-ts 00:00:00:02:00:02 42.42.42.3/24 4242::3/64 \
-    -- lrp-add lr3 lr3-ls3 00:00:00:02:02:00 44.44.45.1/24 4445::1/64 \
-    -- lrp-set-gateway-chassis lr3-ts hv2
-check ovn-nbctl ls-add ls3 \
-    -- lsp-add ls3 ls3-lr3 \
-    -- lsp-set-addresses ls3-lr3 router \
-    -- lsp-set-type ls3-lr3 router \
-    -- lsp-set-options ls3-lr3 router-port=lr3-ls3 \
-    -- lsp-add ls3 lsp3
-check ovn-nbctl lsp-add ts ts-lr3 \
-    -- lsp-set-addresses ts-lr3 router \
-    -- lsp-set-type ts-lr3 router \
-    -- lsp-set-options ts-lr3 router-port=lr3-ts
-
-wait_for_ports_up
-
-ovn_as az1
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr2])
-check ovn-nbctl lsp-set-options ts-lr2 requested-chassis=hv2
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr3])
-check ovn-nbctl lsp-set-options ts-lr3 requested-chassis=hv2
-
-ovn_as az2
-OVS_WAIT_UNTIL([ovn-nbctl show | grep ts-lr1])
-check ovn-nbctl lsp-set-options ts-lr1 requested-chassis=hv1
-
-dnl Enable IP multicast snooping and IP multicast relay.  Reports are
-dnl forwarded statically.
-ovn_as az1
-check ovn-nbctl set logical_switch ls1 other_config:mcast_snoop="true"
-check ovn-nbctl set Logical_Switch_Port ls1-lr1 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_router lr1 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr1-ts options:mcast_flood="true"
-check ovn-nbctl set logical_switch ts other_config:mcast_snoop="true"
-check ovn-nbctl set logical_switch_port ts-lr1 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_switch_port ts-lr2 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_switch_port ts-lr3 options:mcast_flood_reports="true"
-
-ovn_as az2
-check ovn-nbctl set logical_switch ls2 other_config:mcast_snoop="true"
-check ovn-nbctl set Logical_Switch_Port ls2-lr2 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_router lr2 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr2-ts options:mcast_flood="true"
-check ovn-nbctl set logical_switch ls3 other_config:mcast_snoop="true"
-check ovn-nbctl set Logical_Switch_Port ls3-lr3 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_router lr3 options:mcast_relay="true"
-check ovn-nbctl set logical_router_port lr3-ts options:mcast_flood="true"
-check ovn-nbctl set logical_switch ts other_config:mcast_snoop="true"
-check ovn-nbctl set logical_switch_port ts-lr1 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_switch_port ts-lr2 options:mcast_flood_reports="true"
-check ovn-nbctl set logical_switch_port ts-lr3 options:mcast_flood_reports="true"
-
-check ovn_as az1 ovn-nbctl --wait=hv sync
-check ovn_as az2 ovn-nbctl --wait=hv sync
-
-# Pre-populate the hypervisors' ARP tables so that we don't lose any
-# packets for ARP resolution (native tunneling doesn't queue packets
-# for ARP resolution).
-OVN_POPULATE_ARP
-
-# Inject IGMP Join for 239.0.1.68 on LSP1.
-send_igmp_v3_report hv1-vif1 hv1 \
-    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
-    $(ip_to_hex 239 0 1 68) 04 e9b9 \
-    /dev/null
-
-# Inject MLD Join for ff0a:dead:beef::1 on LSP1.
-send_mld_v2_report hv1-vif1 hv1 \
-    000000000001 10000000000000000000000000000001 \
-    ff0adeadbeef00000000000000000001 04 c0e4 \
-    /dev/null
-
-# Inject IGMP Join for 239.0.1.68 on LSP3.
-send_igmp_v3_report hv2-vif2 hv2 \
-    000000000001 $(ip_to_hex 10 0 0 1) f9f8 \
-    $(ip_to_hex 239 0 1 68) 04 e9b9 \
-    /dev/null
-
-# Inject MLD Join for ff0a:dead:beef::1 on LSP3.
-send_mld_v2_report hv2-vif2 hv2 \
-    000000000001 10000000000000000000000000000001 \
-    ff0adeadbeef00000000000000000001 04 c0e4 \
-    /dev/null
-
-# Check that the IGMP and MLD groups are learned on both AZs (on the LS
-# and TS).
-ovn_as az1
-wait_row_count IGMP_Group 2 address=239.0.1.68
-wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"'
-check ovn-nbctl --wait=hv sync
-
-ovn_as az2
-wait_row_count IGMP_Group 2 address=239.0.1.68
-wait_row_count IGMP_Group 2 address='"ff0a:dead:beef::1"'
-check ovn-nbctl --wait=hv sync
-
-# Send an IP multicast packet from LSP2, it should be forwarded
-# to lsp1 and lsp3.
-> expected_az1
-> expected_az2
-send_ip_multicast_pkt hv2-vif1 hv2 \
-    000000000001 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 20 7c6b 11 \
-    e518e518000aed350000
-store_ip_multicast_pkt \
-    000000010100 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
-    e518e518000aed350000 expected_az1
-store_ip_multicast_pkt \
-    000000020200 01005e000144 \
-    $(ip_to_hex 44 44 44 2) $(ip_to_hex 239 0 1 68) 1e 1e 7e6b 11 \
-    e518e518000aed350000 expected_az2
-
-send_ip6_multicast_pkt hv2-vif1 hv2 \
-    000000000001 333300000001 \
-    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
-    000e 40 11 \
-    93407a69000e2b4e61736461640a
-store_ip6_multicast_pkt \
-    000000010100 333300000001 \
-    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
-    000e 3e 11 \
-    93407a69000e2b4e61736461640a \
-    expected_az1
-store_ip6_multicast_pkt \
-    000000020200 333300000001 \
-    00100000000000000000000000000042 ff0adeadbeef00000000000000000001 \
-    000e 3e 11 \
-    93407a69000e2b4e61736461640a \
-    expected_az2
-
-OVS_WAIT_UNTIL(
-  [check_packets 'hv1/vif1-tx.pcap expected_az1' \
-                 'hv2/vif2-tx.pcap expected_az2'],
-  [$at_diff -F'^---' exp rcv])
-
-OVN_CLEANUP_SBOX([hv1], ["/IGMP Querier enabled without a valid IPv4/d
-/IGMP Querier enabled with invalid ETH src/d"])
-
-OVN_CLEANUP_SBOX([hv2], ["/IGMP Querier enabled without a valid IPv4/d
-/IGMP Querier enabled with invalid ETH src/d"])
-
-OVN_CLEANUP_IC([az1],[az2])
-AT_CLEANUP
-])
-
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([ECMP static routes])
 ovn_start