+
+ADD_NAMESPACES(lsp1)
+ADD_VETH(lsp1, lsp1, br-int, "192.168.1.1/24", "f0:00:00:00:00:01", \
+ "192.168.1.100")
+
+ADD_NAMESPACES(lsp2)
+ADD_VETH(lsp2, lsp2, br-int, "192.168.1.2/24", "f0:00:00:00:00:02", \
+ "192.168.1.100")
+
+# First, set up a "pass" ACL by itself.
+check ovn-nbctl acl-add ls from-lport 1000 "ip4.src == 192.168.1.1" pass
+check ovn-nbctl acl-add ls to-lport 1000 "ip4.src == 192.168.1.2" pass
+check ovn-nbctl --wait=hv sync
+
+# Ping should succeed since from-lport "pass" ACL is the only one matched.
+NS_CHECK_EXEC([lsp1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.2 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# Ping the other way should also succeed since to-lport "pass" ACL is matched.
+NS_CHECK_EXEC([lsp2], [ping -q -c 3 -i 0.3 -w 2 192.168.1.1 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# There should be no conntrack entries created since there are no stateful
ACLs.
+# Check conntrack here
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.1.2) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | grep icmp], [1], [dnl
+])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.1.1) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | grep icmp], [1], [dnl
+])
+
+# Now add an arbitrary stateful ACL to the mix. We'll never match on this
+# ACL, but its presence should change things.
+check ovn-nbctl acl-add ls from-lport 200 "ip4.src == 192.168.1.50"
allow-related
+check ovn-nbctl --wait=hv sync
+
+# Pings should still succeed.
+NS_CHECK_EXEC([lsp1], [ping -q -c 3 -i 0.3 -w 2 192.168.1.2 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+NS_CHECK_EXEC([lsp2], [ping -q -c 3 -i 0.3 -w 2 192.168.1.1 | FORMAT_PING], \
+[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+# Now there should be conntrack entries from the pings
+# We should have an entry for each direction of traffic in
+# each port's zone: a total of four.
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.1.2) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | grep icmp], [0], [dnl
+icmp,orig=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=8,code=0),reply=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=8,code=0),reply=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
+])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(192.168.1.1) | \
+sed -e 's/zone=[[0-9]]*/zone=<cleared>/' | grep icmp], [0], [dnl
+icmp,orig=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=8,code=0),reply=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=8,code=0),reply=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
+icmp,orig=(src=192.168.1.2,dst=192.168.1.1,id=<cleared>,type=8,code=0),reply=(src=192.168.1.1,dst=192.168.1.2,id=<cleared>,type=0,code=0),zone=<cleared>
+])
+
+OVN_CLEANUP_CONTROLLER([hv1])
+
+as ovn-sb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as ovn-nb
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+
+as northd
+OVS_APP_EXIT_AND_WAIT([ovn-northd])
+
+as
+OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d
+/connection dropped.*/d"])
+
+AT_CLEANUP
+])