This extends the existing system EVPN tests to make sure the feature
also works fine for IPv6 underlays (IPv6 VXLAN TEPs).

Signed-off-by: Dumitru Ceara <[email protected]>
---
 tests/system-common-macros.at |  29 ++
 tests/system-ovn.at           | 552 +++++++++++++++++++++++++++++++++-
 2 files changed, 571 insertions(+), 10 deletions(-)

diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index ed1c24d953..9c5a124a05 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -195,6 +195,35 @@ m4_define([LOAD_MODULE],
     ]
 )
 
+# SET_EVPN_IFACE_NAMES IFNAME SWITCH [VNI]
+#
+# If IFNAME != "default" configures LS to use br-<IFNAME>, vxlan-<IFNAME> and
+# lo-<IFNAME> as EVPN host interfaces.
+# If IFNAME == "default" configures LS to use the default br-$vni, vxlan-$vni
+# and lo-$vni host interfaces.
+#
+# The host interface names are exported as environment variables BR_NAME,
+# VXLAN_NAME and LO_NAME.
+m4_define([SET_EVPN_IFACE_NAMES],
+    [
+        ifname=$1 switch=$2 vni=$3
+
+        [[ $ifname = "default" ]] && BR_NAME=br-$vni || BR_NAME=br-$ifname
+        [[ $ifname = "default" ]] && VXLAN_NAME=vxlan-$vni || 
VXLAN_NAME=vxlan-$ifname
+        [[ $ifname = "default" ]] && LO_NAME=lo-$vni || LO_NAME=lo-$ifname
+
+        if [[ $ifname != "default" ]]; then
+            check ovn-nbctl set logical_switch $switch                 \
+                other_config:dynamic-routing-bridge-ifname=$BR_NAME    \
+                other_config:dynamic-routing-vxlan-ifname=$VXLAN_NAME  \
+                other_config:dynamic-routing-advertise-ifname=$LO_NAME
+        fi
+
+        export BR_NAME VXLAN_NAME LO_NAME
+        on_exit 'unset BR_NAME VXLAN_NAME LO_NAME'
+    ]
+)
+
 # OVN_TEST_IPV6_PREFIX_DELEGATION()
 m4_define([OVN_TEST_IPV6_PREFIX_DELEGATION],
 [
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index 1b4b30743f..feab4a118e 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -17610,6 +17610,7 @@ AT_CLEANUP
 ])
 
 m4_define([EVPN_SWITCH_TESTS],[
+
 OVN_FOR_EACH_NORTHD([
 AT_SETUP([dynamic-routing - EVPN $1 naming])
 AT_KEYWORDS([dynamic-routing])
@@ -17620,6 +17621,7 @@ CHECK_CONNTRACK_NAT()
 
 IFNAME=$1
 vni=10
+
 VRF_RESERVE([$vni])
 ovn_start
 OVS_TRAFFIC_VSWITCHD_START()
@@ -17650,16 +17652,7 @@ check ovn-nbctl                                        
                       \
     -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20 172:16::20" \
     -- lsp-add-localnet-port ls-evpn ln_port phynet
 
-[[ $IFNAME = "default" ]] && BR_NAME=br-$vni || BR_NAME=br-evpn
-[[ $IFNAME = "default" ]] && VXLAN_NAME=vxlan-$vni || VXLAN_NAME=vxlan-evpn
-[[ $IFNAME = "default" ]] && LO_NAME=lo-$vni || LO_NAME=lo-evpn
-
-if [[ $IFNAME != "default" ]]; then
-    check ovn-nbctl                                                            
             \
-        -- set logical_switch ls-evpn 
other_config:dynamic-routing-bridge-ifname=$BR_NAME   \
-        -- set logical_switch ls-evpn 
other_config:dynamic-routing-vxlan-ifname=$VXLAN_NAME \
-        -- set logical_switch ls-evpn 
other_config:dynamic-routing-advertise-ifname=$LO_NAME
-fi
+SET_EVPN_IFACE_NAMES([$IFNAME], [ls-evpn], [$vni])
 
 ADD_NAMESPACES(workload1)
 ADD_VETH(workload1, workload1, br-int, "172:16::10/64", "f0:00:0f:16:01:10", \
@@ -18155,8 +18148,547 @@ OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port 
patch-.*/d
 /connection dropped.*/d"])
 AT_CLEANUP
 ])
+
+OVN_FOR_EACH_NORTHD([
+AT_SETUP([dynamic-routing - EVPN $1 naming - IPv6 underlay])
+AT_KEYWORDS([dynamic-routing])
+
+CHECK_VRF()
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_NAT()
+
+IFNAME=$1
+vni=10
+
+VRF_RESERVE([$vni])
+ovn_start
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-int])
+ADD_BR([br-ext], [set Bridge br-ext fail-mode=standalone])
+
+# Set external-ids in br-int needed for ovn-controller.
+check ovs-vsctl \
+    -- set Open_vSwitch . external-ids:system-id=hv1 \
+    -- set Open_vSwitch . 
external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \
+    -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \
+    -- set Open_vSwitch . external-ids:ovn-encap-ip=169::1 \
+    -- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext \
+    -- set Open_vSwitch . external-ids:ovn-evpn-local-ip=169::1 \
+    -- set Open_vSwitch . external-ids:ovn-evpn-vxlan-ports=4789 \
+    -- set bridge br-int fail-mode=secure other-config:disable-in-band=true
+
+# Start ovn-controller.
+start_daemon ovn-controller
+
+OVS_WAIT_WHILE([ip link | grep -q ovnvrf$vni:.*UP])
+
+check ovn-nbctl                                                               \
+    -- ls-add ls-evpn                                                         \
+    -- lsp-add ls-evpn workload1                                              \
+    -- lsp-set-addresses workload1 "f0:00:0f:16:01:10 172.16.1.10 172:16::10" \
+    -- lsp-add ls-evpn workload2                                              \
+    -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20 172:16::20" \
+    -- lsp-add-localnet-port ls-evpn ln_port phynet
+
+SET_EVPN_IFACE_NAMES([$IFNAME], [ls-evpn], [$vni])
+
+ADD_NAMESPACES(workload1)
+ADD_VETH(workload1, workload1, br-int, "172:16::10/64", "f0:00:0f:16:01:10", \
+         "172:16::1", "nodad", "172.16.1.10/24", "172.16.1.1")
+
+ADD_NAMESPACES(workload2)
+ADD_VETH(workload2, workload2, br-int, "172:16::20/64", "f0:00:0f:16:01:20", \
+         "172:16::1", "nodad", "172.16.1.20/24", "172.16.1.1")
+
+OVN_POPULATE_ARP
+check ovn-nbctl --wait=hv sync
+wait_for_ports_up
+
+# Setup a VRF for the VNI.
+check ip link add vrf-$vni type vrf table $vni
+on_exit "ip link del vrf-$vni"
+check ip link set vrf-$vni up
+
+# Add VNI bridge.
+check ip link add $BR_NAME type bridge
+on_exit "ip link del $BR_NAME"
+check ip link set $BR_NAME master vrf-$vni addrgenmode none
+check ip link set dev $BR_NAME up
+
+# Add VXLAN VTEP for the VNI (linked to the OVS vxlan_sys_<port> interface).
+# Use a dstport different than the one used by OVS.
+# This is fine because we don't actually want traffic to pass through
+# the $vxlan interface.  FRR should read the dstport from the linked
+# vxlan_sys_${vxlan_port} device.
+dstport=$((60000 + $vni))
+check ip link add $VXLAN_NAME type vxlan \
+    id $vni dstport $dstport local 169::1 nolearning
+on_exit "ip link del $VXLAN_NAME"
+check ip link set dev $VXLAN_NAME up
+check ip link set $VXLAN_NAME master $BR_NAME
+
+# Add a dummy loopback to the VNI bridge to be used for advertising local
+# MACs.
+check ip link add name $LO_NAME type dummy
+on_exit "ip link del $LO_NAME"
+check ip link set $LO_NAME master $BR_NAME
+check ip link set $LO_NAME up
+
+AS_BOX([L2 EVPN VTEP and FDB learning])
+
+check ovn-nbctl --wait=hv set logical_switch ls-evpn 
other_config:dynamic-routing-vni=$vni
+ofport=$(ovs-vsctl --bare --columns ofport find Interface name="ovn-evpn-4789")
+dp_key=$(fetch_column Datapath tunnel_key external_ids:name=ls-evpn)
+
+AT_CHECK([ovn-appctl evpn/remote-vtep-list], [0], [dnl
+])
+
+AT_CHECK([ovn-appctl evpn/vtep-binding-list], [0], [dnl
 ])
 
+AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list], [0], [dnl
+])
+
+# Simulate remote VTEP.
+check bridge fdb append 00:00:00:00:00:00 dev $VXLAN_NAME dst 169::10 static 
permanent
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/remote-vtep-list], [0], [dnl
+IP: 169::10, port: 4789, vni: $vni
+])
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-binding-list | cut -d',' 
-f2-], [0], [dnl
+ Remote IP: 169::10, vni: $vni, binding_key: 0x80000001, tunnel_ofport: 
$ofport, dp_key: $dp_key
+])
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-multicast-group-list | cut 
-d',' -f2-], [0], [dnl
+ Remote IPs: 169::10, vni: $vni
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG | grep 
priority=1050 | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=1050,tun_id=0xa,tun_ipv6_src=169::10,tun_ipv6_dst=169::1,in_port=$ofport
 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int 
table=OFTABLE_REMOTE_VTEP_OUTPUT | grep output | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=50,reg15=0x8000,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
+priority=50,reg15=0x80000001,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
+priority=50,reg15=0x8001,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
+priority=50,reg15=0x8004,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],output:$ofport,resubmit(,OFTABLE_LOCAL_OUTPUT)
+priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+])
+
+# Simulate more remote VTEPs.
+check bridge fdb append 00:00:00:00:00:00 dev $VXLAN_NAME dst 169::20 static 
permanent
+check bridge fdb append 00:00:00:00:00:01 dev $VXLAN_NAME dst 169::30 
extern_learn
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/remote-vtep-list | sort], [0], 
[dnl
+IP: 169::10, port: 4789, vni: $vni
+IP: 169::20, port: 4789, vni: $vni
+IP: 169::30, port: 4789, vni: $vni
+])
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-binding-list | cut -d',' 
-f2- | sort], [0], [dnl
+ Remote IP: 169::10, vni: $vni, binding_key: 0x80000001, tunnel_ofport: 
$ofport, dp_key: $dp_key
+ Remote IP: 169::20, vni: $vni, binding_key: 0x80000002, tunnel_ofport: 
$ofport, dp_key: $dp_key
+ Remote IP: 169::30, vni: $vni, binding_key: 0x80000003, tunnel_ofport: 
$ofport, dp_key: $dp_key
+])
+
+# We cannot check the output directly because the order might change.
+OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q "169::10"])
+OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q "169::20"])
+OVS_WAIT_UNTIL([ovn-appctl evpn/vtep-multicast-group-list | grep -q "169::30"])
+AT_CHECK([ovn-appctl evpn/vtep-multicast-group-list | wc -l], [0], [1
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_PHY_TO_LOG | grep 
priority=1050 | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=1050,tun_id=0xa,tun_ipv6_src=169::10,tun_ipv6_dst=169::1,in_port=$ofport
 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000001->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+priority=1050,tun_id=0xa,tun_ipv6_src=169::20,tun_ipv6_dst=169::1,in_port=$ofport
 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000002->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+priority=1050,tun_id=0xa,tun_ipv6_src=169::30,tun_ipv6_dst=169::1,in_port=$ofport
 
actions=load:0x$dp_key->OXM_OF_METADATA[[0..31]],load:0x80000003->NXM_NX_REG14[[]],resubmit(,OFTABLE_LEARN_REMOTE_FDB),resubmit(,OFTABLE_LOG_INGRESS_PIPELINE)
+])
+
+ovs-ofctl dump-flows br-int table=OFTABLE_REMOTE_VTEP_OUTPUT > 
oftable_remote_vtep_output
+AT_CHECK_UNQUOTED([grep "output" oftable_remote_vtep_output | grep -v resubmit 
| \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=50,reg15=0x80000001,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
+priority=50,reg15=0x80000002,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x20->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
+priority=50,reg15=0x80000003,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x30->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],output:$ofport
+priority=55,reg10=0x1/0x1,reg15=0x80000001,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x10->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
+priority=55,reg10=0x1/0x1,reg15=0x80000002,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x20->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
+priority=55,reg10=0x1/0x1,reg15=0x80000003,metadata=0x$dp_key 
actions=load:0x1->NXM_NX_TUN_IPV6_SRC[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_SRC[[64..127]],load:0x30->NXM_NX_TUN_IPV6_DST[[0..63]],load:0x169000000000000->NXM_NX_TUN_IPV6_DST[[64..127]],load:0xa->NXM_NX_TUN_ID[[0..23]],load:0xffff->NXM_OF_IN_PORT[[]],output:$ofport
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000003,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000003,metadata=0x1,dl_src=00:00:00:00:00:01 
actions=drop
+])
+
+AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c 
"load:0x10->NXM_NX_TUN_IPV6_DST\[[0\.\.63\]],*load:0x169000000000000->NXM_NX_TUN_IPV6_DST\[[64\.\.127\]]"],
 [0], [3
+])
+AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c 
"load:0x20->NXM_NX_TUN_IPV6_DST\[[0\.\.63\]],*load:0x169000000000000->NXM_NX_TUN_IPV6_DST\[[64\.\.127\]]"],
 [0], [3
+])
+AT_CHECK([grep "resubmit" oftable_remote_vtep_output | grep -c 
"load:0x30->NXM_NX_TUN_IPV6_DST\[[0\.\.63\]],*load:0x169000000000000->NXM_NX_TUN_IPV6_DST\[[64\.\.127\]]"],
 [0], [3
+])
+
+# Simulate remote workload.
+check bridge fdb add f0:00:0f:16:10:50 dev $VXLAN_NAME dst 169::10 static 
extern_learn
+check bridge fdb add f0:00:0f:16:10:60 dev $VXLAN_NAME dst 169::20 static 
extern_learn
+check bridge fdb add f0:00:0f:16:10:70 dev $VXLAN_NAME dst 169::30 static 
extern_learn
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-fdb-list | cut -d',' -f2- | 
sort], [0], [dnl
+ MAC: 00:00:00:00:00:01, vni: $vni, binding_key: 0x80000003, dp_key: $dp_key
+ MAC: f0:00:0f:16:10:50, vni: $vni, binding_key: 0x80000001, dp_key: $dp_key
+ MAC: f0:00:0f:16:10:60, vni: $vni, binding_key: 0x80000002, dp_key: $dp_key
+ MAC: f0:00:0f:16:10:70, vni: $vni, binding_key: 0x80000003, dp_key: $dp_key
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_GET_REMOTE_FDB | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=0 actions=load:0->NXM_NX_REG1[[]]
+priority=150,metadata=0x$dp_key,dl_dst=00:00:00:00:00:01 
actions=load:0x80000003->NXM_NX_REG1[[]]
+priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:50 
actions=load:0x80000001->NXM_NX_REG1[[]]
+priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:60 
actions=load:0x80000002->NXM_NX_REG1[[]]
+priority=150,metadata=0x$dp_key,dl_dst=f0:00:0f:16:10:70 
actions=load:0x80000003->NXM_NX_REG1[[]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000003,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=00:00:00:00:00:01 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70 
actions=drop
+])
+
+# Check that the recompute won't change the UUIDs and tunnel keys.
+ovn-appctl evpn/vtep-binding-list > bindings_before
+ovn-appctl evpn/vtep-multicast-group-list > mc_groups_before
+ovn-appctl evpn/vtep-fdb-list > fdb_before
+
+check ovn-appctl inc-engine/recompute
+check ovn-nbctl --wait=hv sync
+
+ovn-appctl evpn/vtep-binding-list > bindings_after
+ovn-appctl evpn/vtep-multicast-group-list > mc_groups_after
+ovn-appctl evpn/vtep-fdb-list > fdb_after
+
+check diff -q bindings_before bindings_after
+check diff -q mc_groups_before mc_groups_after
+check diff -q fdb_before fdb_after
+
+AS_BOX([L2 EVPN FDB advertising])
+
+check ovn-nbctl --wait=hv set logical_switch ls-evpn 
other_config:dynamic-routing-redistribute=fdb
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep 
"f0:00:0f:16:01" | sort], [0], [dnl
+f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
+f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
+f0:00:0f:16:01:20 dev $LO_NAME master $BR_NAME static
+f0:00:0f:16:01:20 dev $LO_NAME vlan 1 master $BR_NAME static
+])
+
+check ovn-nbctl --wait=hv lsp-del workload2
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep 
"f0:00:0f:16:01" | sort], [0], [dnl
+f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
+f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
+])
+
+check ovn-nbctl --wait=hv remove logical_switch ls-evpn other_config 
dynamic-routing-redistribute
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep 
"f0:00:0f:16:01" | sort], [0], [dnl
+])
+
+check ovn-nbctl --wait=hv set logical_switch ls-evpn 
other_config:fdb_age_threshold=300
+ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000003,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,hard_timeout=300,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=00:00:00:00:00:01 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70 
actions=drop
+])
+
+check ovn-nbctl --wait=hv remove logical_switch ls-evpn other_config 
fdb_age_threshold
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_LEARN_REMOTE_FDB 
| grep priority | \
+                   awk '{print $[7], $[8]}' | strip_cookie | sort], [0], [dnl
+priority=100,reg14=0x80000001,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000002,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=100,reg14=0x80000003,metadata=0x$dp_key 
actions=learn(table=OFTABLE_GET_REMOTE_FDB,priority=150,delete_learned,OXM_OF_METADATA[[]],NXM_OF_ETH_DST[[]]=NXM_OF_ETH_SRC[[]],load:NXM_NX_REG14[[]]->NXM_NX_REG1[[]])
+priority=150,reg14=0x80000001,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:50 
actions=drop
+priority=150,reg14=0x80000002,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:60 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=00:00:00:00:00:01 
actions=drop
+priority=150,reg14=0x80000003,metadata=0x$dp_key,dl_src=f0:00:0f:16:10:70 
actions=drop
+])
+
+AS_BOX([L2 EVPN ARP learning])
+# Add a router connected to the EVPN logical switch.
+check ovn-nbctl --wait=hv                                                 \
+    -- lr-add lr                                                          \
+    -- lrp-add lr lr-ls-evpn f0:00:0f:16:01:01 172.16.1.1/24 172:16::1/64 \
+    -- lsp-add-router-port ls-evpn ls-evpn-lr lr-ls-evpn
+
+rtr_dp_key=$(fetch_column Datapath tunnel_key external_ids:name=lr)
+rtr_port_key=$(fetch_column Port_Binding tunnel_key logical_port=lr-ls-evpn)
+
+# Simulate remote workload ARPs (type-2 MAC+IP EVPN route).
+# ovn-controller needs to add OF rules for ARP lookup but no rules for
+# MAC_CACHE use.  These entries do not age out automatically, their lifetime
+# is controlled by the BGP-EVPN control plane.
+check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
+check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
+check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud noarp 
extern_learn
+
+check ip -6 neigh add dev $BR_NAME 172:16::50 lladdr f0:00:0f:16:10:50 nud 
noarp extern_learn
+check ip -6 neigh add dev $BR_NAME 172:16::60 lladdr f0:00:0f:16:10:60 nud 
noarp extern_learn
+check ip -6 neigh add dev $BR_NAME 172:16::70 lladdr f0:00:0f:16:10:70 nud 
noarp extern_learn
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | 
sort], [0], [dnl
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
+])
+
+AS_BOX([Check dynamic-routing-arp-prefer-local=true])
+check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routing-arp-prefer-local=true
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=20,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=20,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+])
+
+AS_BOX([Check dynamic-routing-arp-prefer-local=false])
+check ovn-nbctl --wait=hv set Logical_Switch ls-evpn 
other_config:dynamic-routing-arp-prefer-local=false
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+])
+
+# Check that the recompute won't change the UUIDs and flows.
+ovn-appctl evpn/vtep-arp-list > arp_before
+
+check ovn-appctl inc-engine/recompute
+check ovn-nbctl --wait=hv sync
+
+ovn-appctl evpn/vtep-arp-list > arp_after
+
+check diff -q arp_before arp_after
+
+# Remove remote workload ARP entries and check ovn-controller's state.
+check ip neigh del dev $BR_NAME 172.16.1.50
+check ip neigh del dev $BR_NAME 172.16.1.60
+check ip neigh del dev $BR_NAME 172.16.1.70
+
+check ip -6 neigh del dev $BR_NAME 172:16::50
+check ip -6 neigh del dev $BR_NAME 172:16::60
+check ip -6 neigh del dev $BR_NAME 172:16::70
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | 
sort], [0], [dnl
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_CACHE_USE | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,arp_spa=172.16.1.10,arp_op=2
 actions=drop
+priority=100,ip,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10,nw_src=172.16.1.10
 actions=drop
+])
+
+# Re-add the remote workload ARPs, remove the router, check that flows are
+# removed (vtep-arp-list should still list the ARPs as they're learned on
+# the logical switch that still exists).
+check ip neigh add dev $BR_NAME 172.16.1.50 lladdr f0:00:0f:16:10:50 nud noarp 
extern_learn
+check ip neigh add dev $BR_NAME 172.16.1.60 lladdr f0:00:0f:16:10:60 nud noarp 
extern_learn
+check ip neigh add dev $BR_NAME 172.16.1.70 lladdr f0:00:0f:16:10:70 nud noarp 
extern_learn
+
+check ip -6 neigh add dev $BR_NAME 172:16::50 lladdr f0:00:0f:16:10:50 nud 
noarp extern_learn
+check ip -6 neigh add dev $BR_NAME 172:16::60 lladdr f0:00:0f:16:10:60 nud 
noarp extern_learn
+check ip -6 neigh add dev $BR_NAME 172:16::70 lladdr f0:00:0f:16:10:70 nud 
noarp extern_learn
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | 
sort], [0], [dnl
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,reg0=0xac10010a,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:01:10,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac100132,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac10013c,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg0=0xac100146,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key 
actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x50,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:50,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x60,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:60,load:0x1->NXM_NX_REG10[[6]]
+priority=200,reg4=0x1720016,reg5=0,reg6=0,reg7=0x70,reg15=0x$rtr_port_key,metadata=0x$rtr_dp_key
 actions=mod_dl_dst:f0:00:0f:16:10:70,load:0x1->NXM_NX_REG10[[6]]
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+priority=100,arp,reg0=0xac10010a,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:01:10
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac100132,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac10013c,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,arp,reg0=0xac100146,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x50,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:50,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x60,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:60,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+priority=200,icmp6,reg0=0x1720016,reg1=0,reg2=0,reg3=0x70,reg14=0x$rtr_port_key,metadata=0x$rtr_dp_key,dl_src=f0:00:0f:16:10:70,icmp_code=0
 actions=load:0x1->NXM_NX_REG10[[6]]
+])
+
+check ovn-nbctl --wait=hv lr-del lr
+AT_CHECK_UNQUOTED([ovn-appctl evpn/vtep-arp-list | cut -d',' -f2- | sort], 
[0], [dnl
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172.16.1.50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:50, IP: 172:16::50, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172.16.1.60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:60, IP: 172:16::60, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172.16.1.70, dp_key: $dp_key
+ VNI: 10, MAC: f0:00:0f:16:10:70, IP: 172:16::70, dp_key: $dp_key
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_BINDING | 
grep priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+])
+
+AT_CHECK_UNQUOTED([ovs-ofctl dump-flows br-int table=OFTABLE_MAC_LOOKUP | grep 
priority | \
+                   awk '{print $[7], $[8]}' | sort], [0], [dnl
+])
+
+AS_BOX([L2 EVPN ARP advertising])
+# Add a router connected to the EVPN logical switch.
+check ovn-nbctl --wait=hv                                                 \
+    -- lr-add lr                                                          \
+    -- set Logical_Router lr options:chassis=hv1                          \
+    -- lrp-add lr lr-ls-evpn f0:00:0f:16:01:01 172.16.1.1/24 172:16::1/64
+
+ls_evpn_uuid=$(fetch_column Datapath_Binding _uuid external_ids:name=ls-evpn)
+check ovn-nbctl --wait=hv set logical_switch ls-evpn 
other_config:dynamic-routing-redistribute=fdb,ip
+check_row_count Advertised_MAC_Binding 1 ip='172.16.1.10' 
mac='f0\:00\:0f\:16\:01\:10' datapath=$ls_evpn_uuid
+check_row_count Advertised_MAC_Binding 1 ip='172.16.1.1' 
mac='f0\:00\:0f\:16\:01\:01' datapath=$ls_evpn_uuid
+check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:10' 
mac='f0\:00\:0f\:16\:01\:10' datapath=$ls_evpn_uuid
+check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:1' 
mac='f0\:00\:0f\:16\:01\:01' datapath=$ls_evpn_uuid
+check_row_count Advertised_MAC_Binding 4
+
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.10 lladdr 
f0:00:0f:16:01:10 NOARP'])
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.1 lladdr 
f0:00:0f:16:01:01 NOARP'])
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::10 lladdr 
f0:00:0f:16:01:10 NOARP'])
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::1 lladdr 
f0:00:0f:16:01:01 NOARP'])
+
+OVS_WAIT_FOR_OUTPUT_UNQUOTED([bridge fdb show | grep $LO_NAME | grep 
"f0:00:0f:16:01" | sort], [0], [dnl
+f0:00:0f:16:01:01 dev $LO_NAME master $BR_NAME static
+f0:00:0f:16:01:01 dev $LO_NAME vlan 1 master $BR_NAME static
+f0:00:0f:16:01:10 dev $LO_NAME master $BR_NAME static
+f0:00:0f:16:01:10 dev $LO_NAME vlan 1 master $BR_NAME static
+])
+
+check ovn-nbctl --wait=hv lsp-add ls-evpn workload2 \
+    -- lsp-set-addresses workload2 "f0:00:0f:16:01:20 172.16.1.20 172:16::20"
+
+check_row_count Advertised_MAC_Binding 1 ip='172.16.1.20' 
mac='f0\:00\:0f\:16\:01\:20' datapath=$ls_evpn_uuid
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.20 lladdr 
f0:00:0f:16:01:20 NOARP'])
+
+check_row_count Advertised_MAC_Binding 1 ip='172\:16\:\:20' 
mac='f0\:00\:0f\:16\:01\:20' datapath=$ls_evpn_uuid
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::20 lladdr 
f0:00:0f:16:01:20 NOARP'])
+
+check ovn-nbctl --wait=hv lsp-del workload2
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.20 lladdr 
f0:00:0f:16:01:20 NOARP'], [1])
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::20 lladdr 
f0:00:0f:16:01:20 NOARP'], [1])
+
+check ovn-nbctl --wait=hv lsp-del workload1
+check_row_count Advertised_MAC_Binding 2
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.10 lladdr 
f0:00:0f:16:01:10 NOARP'], [1])
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::10 lladdr 
f0:00:0f:16:01:10 NOARP'], [1])
+
+check ovn-nbctl --wait=hv lrp-del lr-ls-evpn
+check_row_count Advertised_MAC_Binding 0
+AT_CHECK([ip neigh show dev $BR_NAME nud noarp | grep -q '172.16.1.1 lladdr 
f0:00:0f:16:01:01 NOARP'], [1])
+AT_CHECK([ip -6 neigh show dev $BR_NAME nud noarp | grep -q '172:16::1 lladdr 
f0:00:0f:16:01:01 NOARP'], [1])
+
+check ovn-nbctl --wait=hv ls-del ls-evpn
+check ovn-nbctl --wait=hv lr-del lr
+
+OVN_CLEANUP_CONTROLLER([hv1])
+
+OVN_CLEANUP_NORTHD
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+/Failed to acquire.*/d
+/connection dropped.*/d"])
+AT_CLEANUP
+])
+
+]) dnl EVPN_SWITCH_TESTS
+
 EVPN_SWITCH_TESTS([default])
 EVPN_SWITCH_TESTS([custom])
 
-- 
2.52.0

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

Reply via email to